home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume24
/
zsh2.1
/
part09
< prev
next >
Wrap
Text File
|
1991-10-24
|
49KB
|
2,479 lines
Newsgroups: comp.sources.misc
From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
Subject: v24i009: zsh2.1 - The Z shell, Part09/19
Message-ID: <1991Oct24.190947.25915@sparky.imd.sterling.com>
X-Md4-Signature: 06654ce88b5661b0e7f5ad07c8b24377
Date: Thu, 24 Oct 1991 19:09:47 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
Posting-number: Volume 24, Issue 9
Archive-name: zsh2.1/part09
Environment: BSD
Supersedes: zsh2.00: Volume 18, Issue 84-98
#!/bin/sh
# this is zshar.09 (part 9 of zsh2.1.0)
# do not concatenate these parts, unpack them in order with /bin/sh
# file zsh2.1/src/math.c continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 9; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping zsh2.1/src/math.c'
else
echo 'x - continuing file zsh2.1/src/math.c'
sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.1/src/math.c' &&
X case PREMINUS: stack[sp].val = setvar(stack[sp].lval,
X stack[sp].val-1); break;
X default: zerr("out of integers",NULL,0); exit(1);
X }
X}
X
Xvoid bop(tk) /**/
Xint tk;
X{
X switch (tk) {
X case DAND: case DANDEQ: if (!stack[sp].val) noeval++; break;
X case DOR: case DOREQ: if (stack[sp].val) noeval++; break;
X };
X}
X
Xlong mathevall(s,prek,ep) /**/
Xchar *s;int prek;char **ep;
X{
Xint t0;
X
X lastbase = -1;
X for (t0 = 0; t0 != LVCOUNT; t0++)
X lvals[t0] = NULL;
X lvc = 0;
X ptr = s;
X sp = -1;
X unary = 1;
X mathparse(prek);
X *ep = ptr;
X if (sp)
X zerr("bad math expression: unbalanced stack",NULL,0);
X for (t0 = 0; t0 != lvc; t0++)
X free(lvals[t0]);
X return stack[0].val;
X}
X
Xlong matheval(s) /**/
Xchar *s;
X{
Xchar *junk;
Xlong x;
X
X if (!*s)
X return 0;
X x = mathevall(s,TOPPREC,&junk);
X if (*junk)
X zerr("bad math expression: illegal character: %c",NULL,*junk);
X return x;
X}
X
Xlong mathevalarg(s,ss) /**/
Xchar *s;char **ss;
X{
Xlong x;
X
X x = mathevall(s,ARGPREC,ss);
X if (mtok == COMMA)
X (*ss)--;
X return x;
X}
X
X/* operator-precedence parse the string and execute */
X
Xvoid mathparse(pc) /**/
Xint pc;
X{
X if (errflag)
X return;
X mtok = zzlex();
X while (prec[mtok] <= pc)
X {
X if (errflag)
X return;
X if (mtok == NUM)
X push(yyval,-1);
X else if (mtok == ID)
X push(getvar(yylval),yylval);
X else if (mtok == M_INPAR)
X {
X mathparse(TOPPREC);
X if (mtok != M_OUTPAR)
X exit(1);
X }
X else if (mtok == QUEST)
X {
X int q = stack[sp].val;
X if (!q) noeval++;
X mathparse(prec[QUEST]-1);
X if (!q) noeval--; else noeval++;
X mathparse(prec[QUEST]);
X if (q) noeval--;
X op(QUEST);
X continue;
X }
X else
X {
X int otok = mtok,onoeval = noeval;
X
X if (type[otok] == BOOL)
X bop(otok);
X mathparse(prec[otok]-(type[otok] != RL));
X noeval = onoeval;
X op(otok);
X continue;
X }
X mtok = zzlex();
X }
X}
X
SHAR_EOF
echo 'File zsh2.1/src/math.c is complete' &&
chmod 0644 zsh2.1/src/math.c ||
echo 'restore of zsh2.1/src/math.c failed'
Wc_c="`wc -c < 'zsh2.1/src/math.c'`"
test 10626 -eq "$Wc_c" ||
echo 'zsh2.1/src/math.c: original size 10626, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.1/src/mem.c ==============
if test -f 'zsh2.1/src/mem.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.1/src/mem.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.1/src/mem.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/mem.c' &&
X/*
X
X mem.c - memory management
X
X This file is part of zsh, the Z shell.
X
X zsh is free software; no one can prevent you from reading the source
X code, or giving it to someone else.
X
X This file is copyrighted under the GNU General Public License, which
X can be found in the file called COPYING.
X
X Copyright (C) 1990, 1991 Paul Falstad
X
X zsh is distributed in the hope that it will be useful, but
X WITHOUT ANY WARRANTY. No author or distributor accepts
X responsibility to anyone for the consequences of using it or for
X whether it serves any particular purpose or works at all, unless he
X says so in writing. Refer to the GNU General Public License
X for full details.
X
X Everyone is granted permission to copy, modify and redistribute
X zsh, but only under the conditions described in the GNU General Public
X License. A copy of this license is supposed to have been given to you
X along with zsh so you can know your rights and responsibilities.
X It should be in a file named COPYING.
X
X Among other things, the copyright notice and this notice must be
X preserved on all copies.
X
X*/
X
X#include "zsh.h"
X#define HEAPSIZE 8192
X
X/*
X
X There are two ways to allocate memory in zsh. The first way is
X to call zalloc/zcalloc, which call malloc/calloc directly. It
X is legal to call realloc() or free() on memory allocated this way.
X The second way is to call halloc/hcalloc, which allocates memory
X from one of the memory pools on the heap stack. A pool can be
X created by calling pushheap(), and destroyed by calling popheap().
X To free the memory in the pool without destroying it, call
X freeheap(); this is equivalent to { popheap(); pushheap(); }
X Memory allocated in this way does not have to be freed explicitly;
X it will all be freed when the pool is destroyed. In fact,
X attempting to free this memory may result in a core dump.
X The pair of pointers ncalloc and alloc may point to either
X zalloc & zcalloc or halloc & hcalloc; permalloc() sets them to the
X former, and heapalloc() sets them to the latter. This can be useful.
X For example, the dupstruct() routine duplicates a syntax tree,
X allocating the new memory for the tree using alloc(). If you want
X to duplicate a structure for a one-time use (i.e. to execute the list
X in a for loop), call heapalloc(), then dupstruct(). If you want
X to duplicate a structure in order to preserve it (i.e. a function
X definition), call permalloc(), then dupstruct().
X
X*/
X
X/* initialize heap stack */
X
Xvoid meminit() /**/
X{
X permalloc();
X heaplist = newlist();
X pushheap();
X}
X
X/* set default allocation to heap stack */
X
Xvoid heapalloc() /**/
X{
X alloc = hcalloc;
X ncalloc = halloc;
X useheap = 1;
X}
X
Xstatic vptr (*lastcalloc) DCLPROTO((int));
Xstatic vptr (*lastncalloc) DCLPROTO((int));
X
X/* set default allocation to malloc() */
X
Xvoid permalloc() /**/
X{
X lastcalloc = alloc;
X lastncalloc = ncalloc;
X alloc = zcalloc;
X ncalloc = zalloc;
X useheap = 0;
X}
X
X/* reset previous default allocation */
X
Xvoid lastalloc() /**/
X{
X alloc = lastcalloc;
X ncalloc = lastncalloc;
X}
X
Xstruct heap {
X char *pool,*ptr;
X int free;
X struct heap *next;
X };
X
X/* create a memory pool */
X
Xvoid pushheap() /**/
X{
XHeap h;
X
X h = (Heap) zalloc(sizeof *h);
X h->pool = h->ptr = zalloc(HEAPSIZE);
X h->free = HEAPSIZE;
X h->next = NULL;
X permalloc();
X pushnode(heaplist,h);
X lastalloc();
X}
X
X/* reset a memory pool */
X
Xvoid freeheap() /**/
X{
XHeap h = (Heap) peekfirst(heaplist);
X
X freeh(h->next);
X h->free += (h->ptr-h->pool);
X h->ptr = h->pool;
X}
X
X/* destroy a memory pool */
X
Xvoid popheap() /**/
X{
XHeap h = (Heap) getnode(heaplist);
X
X freeh(h);
X}
X
Xvoid freeh(h) /**/
XHeap h;
X{
X if (h)
X {
X freeh(h->next);
X free(h->pool);
X free(h);
X }
X}
X
X/* allocate memory from the current memory pool */
X
Xvptr halloc(size) /**/
Xint size;
X{
XHeap h = (Heap) peekfirst(heaplist),h2;
Xchar *ret;
X
X size = (size|7)+1;
X while (h && h->free-size < 0)
X h = h->next;
X if (!h)
X {
X h2 = (Heap) zalloc(sizeof *h2);
X h2->pool = h2->ptr = zalloc(h2->free =
X (size < HEAPSIZE) ? HEAPSIZE : (size|(HEAPSIZE-1))+1);
X h2->next = h;
X setdata(firstnode(heaplist),(Heap) h2);
X h = h2;
X }
X h->free -= size;
X ret = h->ptr;
X h->ptr += size;
X return ret;
X}
X
X/* allocate memory from the current memory pool and clear it */
X
Xvptr hcalloc(size) /**/
Xint size;
X{
Xvptr ptr;
X
X ptr = halloc(size);
X memset(ptr,0,size);
X return ptr;
X}
X
Xvptr hrealloc(p,old,new) /**/
Xchar *p;int old;int new;
X{
Xchar *ptr;
X
X ptr = halloc(new);
X memcpy(ptr,p,old);
X return ptr;
X}
X
X/* allocate permanent memory */
X
Xvptr zalloc(l) /**/
Xint l;
X{
Xvptr z;
X
X if (!l)
X l = 1;
X if (!(z = malloc(l)))
X {
X zerr("fatal error: out of memory",NULL,0);
X exit(1);
X }
X return z;
X}
X
Xvptr zcalloc(size) /**/
Xint size;
X{
Xvptr ptr;
X
X ptr = zalloc(size);
X memset(ptr,0,size);
X return ptr;
X}
X
Xchar *strdup(s) /**/
Xchar *s;
X{
Xchar *t;
X
X if (!s)
X return NULL;
X t = ncalloc(strlen(s)+1);
X strcpy(t,s);
X return t;
X}
X
Xchar *ztrdup(s) /**/
Xchar *s;
X{
Xchar *t;
X
X if (!s)
X return NULL;
X t = zalloc(strlen(s)+1);
X strcpy(t,s);
X return t;
X}
X
SHAR_EOF
chmod 0644 zsh2.1/src/mem.c ||
echo 'restore of zsh2.1/src/mem.c failed'
Wc_c="`wc -c < 'zsh2.1/src/mem.c'`"
test 5007 -eq "$Wc_c" ||
echo 'zsh2.1/src/mem.c: original size 5007, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.1/src/params.c ==============
if test -f 'zsh2.1/src/params.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.1/src/params.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.1/src/params.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/params.c' &&
X/*
X
X params.c - parameters
X
X This file is part of zsh, the Z shell.
X
X zsh is free software; no one can prevent you from reading the source
X code, or giving it to someone else.
X
X This file is copyrighted under the GNU General Public License, which
X can be found in the file called COPYING.
X
X Copyright (C) 1990, 1991 Paul Falstad
X
X zsh is distributed in the hope that it will be useful, but
X WITHOUT ANY WARRANTY. No author or distributor accepts
X responsibility to anyone for the consequences of using it or for
X whether it serves any particular purpose or works at all, unless he
X says so in writing. Refer to the GNU General Public License
X for full details.
X
X Everyone is granted permission to copy, modify and redistribute
X zsh, but only under the conditions described in the GNU General Public
X License. A copy of this license is supposed to have been given to you
X along with zsh so you can know your rights and responsibilities.
X It should be in a file named COPYING.
X
X Among other things, the copyright notice and this notice must be
X preserved on all copies.
X
X*/
X
X#include "zsh.h"
X#include <pwd.h>
X
X#define new(X) (X=(vptr)alloc(sizeof(*(X))))
X
Xstatic Param argvparam;
X
X/* put predefined params in hash table */
X
Xvoid setupparams() /**/
X{
X/* special integer params */
Xstatic struct { char *name;
X long (*get) DCLPROTO((Param));
X void (*set) DCLPROTO((Param,long)); } x1[] = {
X "#",poundgetfn,NULL,
X "ARGC",poundgetfn,NULL,
X "ERRNO",errnogetfn,NULL,
X "GID",gidgetfn,NULL,
X "HISTSIZE",histsizegetfn,histsizesetfn,
X "LITHISTSIZE",lithistsizegetfn,lithistsizesetfn,
X "RANDOM",randomgetfn,randomsetfn,
X "SECONDS",secondsgetfn,secondssetfn,
X "UID",uidgetfn,NULL,
X NULL,NULL,NULL
X }, *p1 = x1;
X/* special string params */
Xstatic struct { char *name;
X char *(*get) DCLPROTO((Param));
X void (*set) DCLPROTO((Param,char *)); } x2[] = {
X "-",dashgetfn,NULL,
X "HISTCHARS",histcharsgetfn,histcharssetfn,
X "HOME",homegetfn,homesetfn,
X "TERM",termgetfn,termsetfn,
X "WORDCHARS",wordcharsgetfn,wordcharssetfn,
X "IFS",ifsgetfn,ifssetfn,
X "_",underscoregetfn,NULL,
X NULL,NULL,NULL
X }, *p2 = x2;
X/* constant string params */
Xstatic struct { char *name,*data; } x3[] = {
X "HOSTTYPE",HOSTTYPE,
X "VERSION",VERSIONSTR,
X NULL,NULL
X }, *p3 = x3;
X/* variable integer params */
Xstatic struct { char *name; long *data; } x4[] = {
X "!",&lastpid, /* read only */
X "$",&mypid,
X "?",&lastval,
X "status",&lastval,
X "LINENO",&lineno,
X "PPID",&ppid,
X NULL,NULL,
X
X "BAUD",&baud, /* read/write */
X "COLUMNS",&columns,
X "DIRSTACKSIZE",&dirstacksize,
X "LINES",&lines,
X "LISTMAX",&listmax,
X "LOGCHECK",&logcheck,
X "MAILCHECK",&mailcheck,
X "OPTIND",&optind,
X "PERIOD",&period,
X "SAVEHIST",&savehist,
X "SHLVL",&shlvl,
X "TMOUT",&tmout,
X NULL,NULL
X }, *p4 = x4;
X/* variable string params */
Xstatic struct { char *name; char **data; } x5[] = {
X "LOGNAME",&username, /* read only */
X "OLDPWD",&oldpwd,
X "PWD",&cwd,
X "TTY",&ttystrname,
X "USERNAME",&username,
X NULL,NULL,
X
X "FCEDIT",&fceditparam, /* read/write */
X "HOST",&hostnam,
X "OPTARG",&optarg,
X "MAIL",&mailfile,
X "NULLCMD",&nullcmd,
X "prompt",&prompt,
X "PROMPT",&prompt,
X "PROMPT2",&prompt2,
X "PROMPT3",&prompt3,
X "PROMPT4",&prompt4,
X "RPROMPT",&rprompt,
X "PS1",&prompt,
X "PS2",&prompt2,
X "PS3",&prompt3,
X "PS4",&prompt4,
X "RPS1",&rprompt,
X "SPROMPT",&sprompt,
X "TIMEFMT",&timefmt,
X "TMPPREFIX",&tmpprefix,
X "WATCHFMT",&watchfmt,
X "0",&argzero,
X NULL,NULL
X }, *p5 = x5;
X/* colonsplit string params */
Xstatic struct { char *name; } x6[] = {
X "CDPATH","FIGNORE","FPATH","MAILPATH","WATCH","HOSTS",
X "HOSTCMDS","OPTCMDS","BINDCMDS","VARCMDS",
X NULL
X }, *p6 = x6;
X/* variable array params */
Xstatic struct { char *name; char ***data; } x7[] = {
X "cdpath",&cdpath,
X "fignore",&fignore,
X "fpath",&fpath,
X "mailpath",&mailpath,
X "watch",&watch,
X "hosts",&hosts,
X "hostcmds",&hostcmds,
X "optcmds",&optcmds,
X "bindcmds",&bindcmds,
X "varcmds",&varcmds,
X "signals",(char ***) &sigptr,
X "argv",&pparams,
X "*",&pparams,
X "@",&pparams,
X NULL,NULL
X }, *p7 = x7;
X/* special array params */
Xstatic struct { char *name;
X char **(*get) DCLPROTO((Param));
X void (*set) DCLPROTO((Param,char **)); } x8[] = {
X "path",pathgetfn,pathsetfn,
X NULL,NULL,NULL
X }, *p8 = x8;
XParam pm,pm2;
X
X for (;p1->name;p1++)
X {
X new(pm);
X pm->gets.ifn = p1->get;
X pm->sets.ifn = p1->set;
X pm->flags = (p1->set) ? PMFLAG_i|PMFLAG_SPECIAL :
X PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL;
X pm->ct = 10;
X addhperm(p1->name,pm,paramtab,NULL);
X }
X for (;p2->name;p2++)
X {
X new(pm);
X pm->gets.cfn = p2->get;
X pm->sets.cfn = p2->set;
X pm->flags = (p2->set) ? PMFLAG_SPECIAL : PMFLAG_r|PMFLAG_SPECIAL;
X addhperm(p2->name,pm,paramtab,NULL);
X }
X for (;p3->name;p3++)
X {
X new(pm);
X pm->gets.cfn = strconstgetfn;
X pm->flags = PMFLAG_r|PMFLAG_SPECIAL;
X pm->data = p3->data;
X addhperm(p3->name,pm,paramtab,NULL);
X }
X for (;p4->name;p4++)
X {
X new(pm);
X pm->gets.ifn = intvargetfn;
X pm->sets.ifn = NULL;
X pm->data = p4->data;
X pm->flags = PMFLAG_r|PMFLAG_i|PMFLAG_SPECIAL;
X pm->ct = 10;
X addhperm(p4->name,pm,paramtab,NULL);
X }
X for (p4++;p4->name;p4++)
X {
X new(pm);
X pm->gets.ifn = intvargetfn;
X pm->sets.ifn = intvarsetfn;
X pm->data = p4->data;
X pm->flags = PMFLAG_i|PMFLAG_SPECIAL;
X pm->ct = 10;
X addhperm(p4->name,pm,paramtab,NULL);
X }
X for (;p5->name;p5++)
X {
X new(pm);
X pm->gets.cfn = strvargetfn;
X pm->sets.cfn = NULL;
X pm->data = p5->data;
X pm->flags = PMFLAG_r|PMFLAG_SPECIAL;
X addhperm(p5->name,pm,paramtab,NULL);
X }
X for (p5++;p5->name;p5++)
X {
X new(pm);
X pm->gets.cfn = strvargetfn;
X pm->sets.cfn = strvarsetfn;
X pm->data = p5->data;
X pm->flags = PMFLAG_SPECIAL;
X addhperm(p5->name,pm,paramtab,NULL);
X }
X for (;p6->name;p6++,p7++)
X {
X new(pm);
X new(pm2);
X pm->gets.cfn = colonarrgetfn;
X pm->sets.cfn = colonarrsetfn;
X pm2->gets.afn = arrvargetfn;
X pm2->sets.afn = arrvarsetfn;
X pm->data = p7->data;
X pm2->data = p7->data;
X pm->flags = PMFLAG_SPECIAL;
X pm2->flags = PMFLAG_A|PMFLAG_SPECIAL;
X pm2->ename = p6->name;
X addhperm(p6->name,pm,paramtab,NULL);
X addhperm(p7->name,pm2,paramtab,NULL);
X }
X new(pm);
X pm->gets.cfn = colonarrgetfn;
X pm->sets.cfn = colonarrsetfn;
X pm->data = NULL;
X pm->flags = PMFLAG_SPECIAL;
X addhperm("PATH",pm,paramtab,NULL);
X for (;p7->name;p7++)
X {
X new(pm);
X pm->gets.afn = arrvargetfn;
X pm->sets.afn = arrvarsetfn;
X pm->data = p7->data;
X pm->flags = PMFLAG_A|PMFLAG_SPECIAL;
X if (pm->data == &sigptr)
X pm->flags |= PMFLAG_r;
X addhperm(p7->name,pm,paramtab,NULL);
X }
X for (;p8->name;p8++)
X {
X new(pm);
X pm->gets.afn = p8->get;
X pm->sets.afn = p8->set;
X pm->flags = PMFLAG_A|PMFLAG_SPECIAL;
X addhperm(p8->name,pm,paramtab,NULL);
X }
X argvparam = gethnode("argv",paramtab);
X}
X
Xstatic int unsetflag;
X
Xstruct param *createparam(name,value,flags) /**/
Xchar *name;vptr value;int flags;
X{
Xstruct param *pm;
Xchar buf[20];
X
X pm = zcalloc(sizeof *pm);
X if (isset(ALLEXPORT))
X flags |= PMFLAG_x;
X pm->flags = flags;
X if ((flags & PMTYPE) == PMFLAG_s)
X {
X pm->u.str = ztrdup(value);
X pm->sets.cfn = strsetfn;
X pm->gets.cfn = strgetfn;
X }
X else if ((flags & PMTYPE) == PMFLAG_A)
X {
X pm->u.arr = value;
X pm->sets.afn = arrsetfn;
X pm->gets.afn = arrgetfn;
X }
X else
X {
X pm->u.val = (value) ? matheval(value) : 0;
X pm->sets.ifn = intsetfn;
X pm->gets.ifn = intgetfn;
X sprintf(buf,"%ld",pm->u.val);
X value = buf;
X }
X if (flags & PMFLAG_x)
X pm->env = addenv(name,value);
X addhnode(ztrdup(name),pm,paramtab,freepm);
X return pm;
X}
X
Xint isident(s) /**/
Xchar *s;
X{
Xchar *ss;
X
X for (ss = s; *ss; ss++) if (!iident(*ss)) break;
X if (!*ss || *ss == '[') return 1;
X if (*s == Quest)
X *s = '?';
X else if (*s == Pound)
X *s = '#';
X else if (*s == String || *s == Qstring)
X *s = '$';
X else if (*s == Star)
X *s = '*';
X if (*s == '#' || *s == '-' || *s == '?' || *s == '$' || *s == '_' ||
X *s == '!' || *s == '@' || *s == '*')
X return 1;
X return 0;
X}
X
XValue getvalue(pptr,bracks) /**/
Xchar **pptr;int bracks;
X{
Xchar *s = *pptr,*t = *pptr;
Xchar sav;
XValue v;
X
X if (idigit(*s)) while (idigit(*s)) s++;
X else if (iident(*s)) while (iident(*s)) s++;
X else if (*s == Quest) *s++ = '?';
X else if (*s == Pound) *s++ = '#';
X else if (*s == String) *s++ = '$';
X else if (*s == Qstring) *s++ = '$';
X else if (*s == Star) *s++ = '*';
X else if (*s == '#' || *s == '-' || *s == '?' || *s == '$' ||
X *s == '_' || *s == '!' || *s == '@' || *s == '*') s++;
X else return NULL;
X if (sav = *s) *s = '\0';
X if (idigit(*t) && *t != '0') {
X v = (Value) alloc(sizeof *v);
X v->pm = argvparam;
X v->a = v->b = atoi(t)-1;
X if (sav)
X *s = sav;
X } else {
X struct param *pm;
X int isvarat = !strcmp(t, "@");
X
X pm = gethnode(t,paramtab);
X if (sav)
X *s = sav;
X *pptr = s;
X if (!pm)
X return NULL;
X v = alloc(sizeof *v);
X if (pmtype(pm) == PMFLAG_A)
X v->isarr = isvarat ? -1 : 1;
X v->pm = pm;
X v->a = 0; v->b = -1;
X if (bracks && (*s == '[' || *s == Inbrack)) {
X int a,b;
X char *olds = s,*t;
X
X *s++ = '[';
X for (t = s; *t && *t != ']' && *t != Outbrack; t++)
X if (itok(*t))
X *t = ztokens[*t-Pound];
X if (*t == Outbrack)
X *t = ']';
X if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
X v->isarr = (s[0] == '*') ? 1 : -1;
X v->a = 0;
X v->b = -1;
X s += 2;
X } else {
X a = mathevalarg(s,&s);
X if (a > 0) a--;
X if (*s == ',' || *s == Comma) {
X s++;
X b = mathevalarg(s,&s);
X if (b > 0) b--;
X } else
X b = a;
X if (*s == ']') {
X s++;
X if (v->isarr && a == b)
X v->isarr = 0;
X v->a = a;
X v->b = b;
X } else
X s = olds;
X }
X }
X }
X if (!bracks && *s)
X return NULL;
X *pptr = s;
X return v;
X}
X
Xchar *getstrvalue(v) /**/
XValue v;
X{
Xchar *s,**ss;
Xstatic char buf[20];
X
X if (!v)
X return "";
X if (pmtype(v->pm) != PMFLAG_A) {
X if ((pmtype(v->pm) == PMFLAG_i))
X convbase(s = buf,v->pm->gets.ifn(v->pm),v->pm->ct);
X else
X s = v->pm->gets.cfn(v->pm);
X if (v->a == 0 && v->b == -1) return s;
X if (v->a < 0) v->a += strlen(s);
X if (v->b < 0) v->b += strlen(s);
X s = (v->a > strlen(s)) ? strdup("") : strdup(s+v->a);
X if (v->b < v->a) s[0] = '\0';
X else if (v->b-v->a < strlen(s)) s[v->b-v->a+1] = '\0';
X return s;
X }
X if (v->isarr) return spacejoin(v->pm->gets.afn(v->pm));
X
X ss = v->pm->gets.afn(v->pm);
X if (v->a < 0) v->a += arrlen(ss);
X s = (v->a >= arrlen(ss) || v->a < 0) ? "" : ss[v->a];
X return s;
X}
X
Xchar **getarrvalue(v) /**/
XValue v;
X{
Xchar **s;
Xstatic char *nular[] = { "", NULL };
X
X if (!v)
X return arrdup(nular);
X s = v->pm->gets.afn(v->pm);
X if (v->a == 0 && v->b == -1) return s;
X if (v->a < 0) v->a += arrlen(s);
X if (v->b < 0) v->b += arrlen(s);
X if (v->a > arrlen(s) || v->a < 0)
X s = arrdup(nular);
X else
X s = arrdup(s)+v->a;
X if (v->b < v->a) s[0] = NULL;
X else if (v->b-v->a < arrlen(s)) s[v->b-v->a+1] = NULL;
X return s;
X}
X
Xlong getintvalue(v) /**/
XValue v;
X{
Xchar **ss;
X
X if (!v || v->isarr)
X return 0;
X if (pmtype(v->pm) != PMFLAG_A) {
X if (pmtype(v->pm) == PMFLAG_i)
X return v->pm->gets.ifn(v->pm);
X return atol(v->pm->gets.cfn(v->pm));
X }
X ss = v->pm->gets.afn(v->pm);
X if (v->a < 0) v->a += arrlen(ss);
X if (v->a < 0 || v->a > arrlen(ss)) return 0;
X return atol(ss[v->a]);
X}
X
Xvoid setstrvalue(v,val) /**/
XValue v;char *val;
X{
Xchar *s;
X
X if (v->pm->flags & PMFLAG_r)
X return;
X if ((s = v->pm->env) && val)
X v->pm->env = replenv(v->pm->env,val);
X switch (pmtype(v->pm)) {
X case PMFLAG_s:
X if (v->a == 0 && v->b == -1)
X (v->pm->sets.cfn)(v->pm,val);
X else {
X char *z,*y,*x;
X
X z = strdup((v->pm->gets.cfn)(v->pm));
X if (v->a < 0) {
X v->a += strlen(z);
X if (v->a < 0) v->a = 0;
X }
X if (v->a > strlen(z)) v->a = strlen(z);
X if (v->b < 0) v->b += strlen(z);
X if (v->b <= v->a) v->b = v->a-1;
X z[v->a] = '\0';
X y = z+v->b+1;
X x = zalloc(strlen(z)+strlen(y)+strlen(val)+1);
X strcpy(x,z);
X strcat(x,val);
X strcat(x,y);
X (v->pm->sets.cfn)(v->pm,z);
X }
X if (v->pm->flags & (PMFLAG_L|PMFLAG_R|PMFLAG_Z) && !v->pm->ct)
X v->pm->ct = strlen(val);
X break;
X case PMFLAG_i:
X (v->pm->sets.ifn)(v->pm,matheval(val));
X if (!v->pm->ct && lastbase != 1)
X v->pm->ct = lastbase;
X free(val);
X break;
X case PMFLAG_A:
X if (v->a != v->b)
X zerr("illegal array assignment",NULL,0);
X else {
X char **ss = (v->pm->gets.afn)(v->pm);
X int ac,ad,t0;
X
X ac = arrlen(ss);
X if (v->a < 0) {
X v->a += ac;
X if (v->a < 0) v->a = 0;
X }
X if (v->a >= ac) {
X char **st = ss;
X
X ad = v->a+1;
X ss = zalloc((ad+1)*sizeof *ss);
X memcpy(ss,st,(ad+1)*sizeof *ss);
X for (t0 = 0; t0 != ac; t0++)
X ss[t0] = ztrdup(ss[t0]);
X while (ac < ad)
X ss[ac++] = ztrdup("");
X ss[ac] = NULL;
X }
X if (ss[v->a]) free(ss[v->a]);
X ss[v->a] = val;
X (v->pm->sets.afn)(v->pm,ss);
X }
X break;
X }
X}
X
Xvoid setintvalue(v,val) /**/
XValue v;long val;
X{
Xchar buf[20];
X
X if (v->pm->flags & PMFLAG_r)
X return;
X if (v->pm->env) {
X sprintf(buf,"%ld",val);
X v->pm->env = replenv(v->pm->env,buf);
X }
X switch (pmtype(v->pm))
X {
X case PMFLAG_s:
X sprintf(buf,"%ld",val);
X (v->pm->sets.cfn)(v->pm,ztrdup(buf));
X break;
X case PMFLAG_i:
X (v->pm->sets.ifn)(v->pm,val);
X if (!v->pm->ct && lastbase != -1)
X v->pm->ct = lastbase;
X break;
X case PMFLAG_A:
X zerr("attempt to assign integer to array",NULL,0);
X break;
X }
X}
X
Xvoid setarrvalue(v,val) /**/
XValue v;char **val;
X{
X if (v->pm->flags & PMFLAG_r)
X return;
X if (pmtype(v->pm) != PMFLAG_A)
X {
X zerr("attempt to assign non-array to array",NULL,0);
X return;
X }
X (v->pm->sets.afn)(v->pm,val);
X}
X
Xchar *getsparamval(s,l) /**/
Xchar *s;int l;
X{
Xchar sav,*t = s;
XValue v;
X
X if (sav = t[l])
X t[l] = '\0';
X if (!(v = getvalue(&s,0)))
X return NULL;
X t[l] = sav;
X t = getstrvalue(v);
X return t;
X}
X
Xlong getiparam(s) /**/
Xchar *s;
X{
XValue v;
X
X if (!(v = getvalue(&s,0)))
X return 0;
X return getintvalue(v);
X}
X
Xchar *getsparam(s) /**/
Xchar *s;
X{
XValue v;
X
X if (!(v = getvalue(&s,0)))
X return NULL;
X return getstrvalue(v);
X}
X
XParam setsparam(s,val) /**/
Xchar *s;char *val;
X{
XValue v;
Xchar *t = s;
X
X if (!isident(s))
X {
X zerr("not an identifier: %s",s,0);
X return NULL;
X }
X if (!(v = getvalue(&s,1)) || *s)
X return createparam(t,val,PMFLAG_s);
X if ((v->pm->flags & PMTYPE) != PMFLAG_s &&
X !(v->pm->flags & PMFLAG_SPECIAL)) {
X unsetparam(s);
X return createparam(t,val,PMFLAG_s);
X }
X setstrvalue(v,val);
X return v->pm;
X}
X
XParam setaparam(s,val) /**/
Xchar *s;char **val;
X{
XValue v;
Xchar *t = s;
X
X if (!isident(s))
X {
X zerr("not an identifier: %s",s,0);
X return NULL;
X }
X if (!(v = getvalue(&s,1)) || *s)
X return createparam(t,val,PMFLAG_A);
X if ((v->pm->flags & PMTYPE) != PMFLAG_A &&
X !(v->pm->flags & PMFLAG_SPECIAL)) {
X unsetparam(s);
X return createparam(t,val,PMFLAG_A);
X }
X setarrvalue(v,val);
X return v->pm;
X}
X
XParam setiparam(s,val) /**/
Xchar *s;long val;
X{
XValue v;
Xchar *t = s;
XParam pm;
X
X if (!isident(s))
X {
X zerr("not an identifier: %s",s,0);
X return NULL;
X }
X if (!(v = getvalue(&s,0)))
X {
X pm = createparam(t,NULL,PMFLAG_i);
X pm->u.val = val;
X return pm;
X }
X setintvalue(v,val);
X return v->pm;
X}
X
Xvoid unsetparam(s) /**/
Xchar *s;
X{
XParam pm;
X
X if (!(pm = gethnode(s,paramtab)))
X return;
X if (pm->flags & PMFLAG_r)
X return;
X unsetflag = 1;
X switch (pmtype(pm))
X {
X case 0:
X (pm->sets.cfn)(pm,ztrdup(""));
X break;
X case PMFLAG_i:
X (pm->sets.ifn)(pm,0);
X break;
X case PMFLAG_A:
X (pm->sets.afn)(pm,mkarray(NULL));
X break;
X }
X if (pmtype(pm) == PMFLAG_s && (pm->flags & PMFLAG_x))
X delenv(pm->env);
X if (!(pm->flags & PMFLAG_SPECIAL))
X freepm(remhnode(s,paramtab));
X unsetflag = 0;
X}
X
Xvoid intsetfn(pm,x) /**/
XParam pm;long x;
X{
X pm->u.val = x;
X}
X
Xlong intgetfn(pm) /**/
XParam pm;
X{
X return pm->u.val;
X}
X
Xvoid strsetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (x)
X {
X if (pm->u.str)
X free(pm->u.str);
X pm->u.str = x;
X }
X}
X
Xchar *strgetfn(pm) /**/
XParam pm;
X{
X return pm->u.str;
X}
X
Xvoid arrsetfn(pm,x) /**/
XParam pm;char **x;
X{
Xint ct;
X
X if (x)
X {
X if (pm->u.arr && pm->u.arr != x)
X freearray(pm->u.arr);
X pm->u.arr = x;
X for (ct = 0; *x; x++,ct++);
X pm->ct = ct;
X }
X}
X
Xchar **arrgetfn(pm) /**/
XParam pm;
X{
X return pm->u.arr;
X}
X
Xvoid intvarsetfn(pm,x) /**/
XParam pm;long x;
X{
X *((long *) pm->data) = x;
X}
X
Xlong intvargetfn(pm) /**/
XParam pm;
X{
X return *((long *) pm->data);
X}
X
Xvoid strvarsetfn(pm,x) /**/
XParam pm;char *x;
X{
X *((char **) pm->data) = x;
X}
X
Xvoid strvarnonullsetfn(pm,x) /**/
XParam pm;char *x;
X{
X *((char **) pm->data) = (x) ? x : ztrdup("");
X}
X
Xchar *strvargetfn(pm) /**/
XParam pm;
X{
Xchar *s;
X
X s = *((char **) pm->data);
X if (!s)
X return "";
X return s;
X}
X
Xchar *strconstgetfn(pm) /**/
XParam pm;
X{
X return (char *) pm->data;
X}
X
Xvoid colonarrsetfn(pm,x) /**/
XParam pm;char *x;
X{
Xchar **s,**t,*u;
X
X s = colonsplit(x);
X for (t = s; *t; t++)
X {
X u = *t;
X if (*u == '~')
X *u = Tilde;
X if (*u == '=')
X *u = Equals;
X u = strdup(u);
X filesub(&u);
X if (!*u)
X u = ".";
X *t = ztrdup(u);
X }
X if (pm->data)
X {
X *((char ***) pm->data) = s;
X if (pm->ename)
X arrfixenv(pm->ename,s);
X }
X else
X {
X path = s;
X newcmdnamtab();
X arrfixenv("PATH",s);
X }
X}
X
Xchar *colonarrgetfn(pm) /**/
XParam pm;
X{
X if ((char **) pm->data)
X return colonjoin(*(char ***) pm->data);
X else
X return colonjoin(path);
X}
X
Xchar **arrvargetfn(pm) /**/
XParam pm;
X{
X return *((char ***) pm->data);
X}
X
Xvoid arrvarsetfn(pm,x) /**/
XParam pm;char **x;
X{
X if ((*(char ***) pm->data) != x)
X freearray(*(char ***) pm->data);
X *((char ***) pm->data) = x;
X if (pm->ename)
X arrfixenv(pm->ename,x);
X}
X
Xchar **pathgetfn(pm) /**/
XParam pm;
X{
X return path;
X}
X
Xvoid pathsetfn(pm,x) /**/
XParam pm;char **x;
X{
X if (path != x)
X freearray(path);
X path = x;
X newcmdnamtab();
X arrfixenv("PATH",x);
X}
X
Xvoid unsettablesetfn(pm,x) /**/
XParam pm;char *x;
X{ ; }
X
Xlong poundgetfn(pm) /**/
XParam pm;
X{
X return arrlen(pparams);
X}
X
Xlong randomgetfn(pm) /**/
XParam pm;
X{
X return rand() & 0x7fff;
X}
X
Xvoid randomsetfn(pm,v) /**/
XParam pm;long v;
X{
X srand((unsigned int) v);
X}
X
Xlong secondsgetfn(pm) /**/
XParam pm;
X{
X return time(NULL)-shtimer;
X}
X
Xvoid secondssetfn(pm,x) /**/
XParam pm;long x;
X{
X shtimer = x+time(NULL);
X}
X
Xlong uidgetfn(pm) /**/
XParam pm;
X{
X return getuid();
X}
X
Xlong gidgetfn(pm) /**/
XParam pm;
X{
X return getegid();
X}
X
Xchar *usernamegetfn(pm) /**/
XParam pm;
X{
Xstruct passwd *pwd;
X
X pwd = getpwuid(getuid());
X return pwd->pw_name;
X}
X
Xchar *hostgetfn(pm) /**/
XParam pm;
X{
Xstatic char hostnam[65];
Xstatic int got = 0;
X
X if (!got)
X {
X gethostname(hostnam,64);
X hostnam[64] = '\0';
X got = 1;
X }
X return hostnam;
X}
X
Xchar *ifsgetfn(pm) /**/
XParam pm;
X{
X return ifs;
X}
X
Xvoid ifssetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (x) ifs = x;
X inittyptab();
X}
X
Xvoid histsizesetfn(pm,v) /**/
XParam pm;long v;
X{
X if ((histsiz = v) <= 2)
X histsiz = 2;
X}
X
Xlong histsizegetfn(pm) /**/
XParam pm;
X{
X return histsiz;
X}
X
Xvoid lithistsizesetfn(pm,v) /**/
XParam pm;long v;
X{
X if ((lithistsiz = v) <= 2)
X lithistsiz = 2;
X}
X
Xlong lithistsizegetfn(pm) /**/
XParam pm;
X{
X return lithistsiz;
X}
X
Xvoid mailchecksetfn(pm,x) /**/
XParam pm;long x;
X{
X mailcheck = (unsetflag) ? 600 : x;
X}
X
Xvoid pathasetfn(pm,x) /**/
XParam pm;char **x;
X{
X freearray(path);
X path = x;
X newcmdnamtab();
X}
X
Xchar **pathagetfn(pm) /**/
XParam pm;
X{
X return path;
X}
X
Xlong errnogetfn(pm) /**/
XParam pm;
X{
X return errno;
X}
X
Xchar *dashgetfn(pm) /**/
XParam pm;
X{
Xstatic char buf[100];
Xchar *val = buf;
Xint t0;
X
X for (val = buf, t0 = ' ';t0 <= 'z'; t0++)
X if (opts[t0] == OPT_SET)
X *val++ = t0;
X *val = '\0';
X return buf;
X}
X
Xchar *ttygetfn(pm) /**/
XParam pm;
X{
X return ttyname(SHTTY);
X}
X
Xvoid histcharssetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (x)
X {
X bangchar = x[0];
X hatchar = (bangchar) ? x[1] : '\0';
X hashchar = (hatchar) ? x[2] : '\0';
X free(x);
X }
X}
X
Xchar *histcharsgetfn(pm) /**/
XParam pm;
X{
Xstatic char buf[4];
X
X buf[0] = bangchar;
X buf[1] = hatchar;
X buf[2] = hashchar;
X buf[3] = '\0';
X return buf;
X}
X
Xchar *homegetfn(pm) /**/
XParam pm;
X{
X return home;
X}
X
Xvoid homesetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (isset(CHASELINKS) && (home = xsymlink(x)))
X free(x);
X else
X home = x;
X}
X
Xchar *wordcharsgetfn(pm) /**/
XParam pm;
X{
X return wordchars;
X}
X
Xvoid wordcharssetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (x)
X wordchars = x;
X else
X wordchars = ztrdup(DEFWORDCHARS);
X inittyptab();
X}
X
Xchar *underscoregetfn(pm) /**/
XParam pm;
X{
Xchar *s,*t;
X
X if (!(s = qgetevent(curhist-1)))
X return "";
X for (t = s+strlen(s); t > s; t--)
X if (*t == HISTSPACE)
X break;
X if (t != s)
X t++;
X return t;
X}
X
Xchar *termgetfn(pm) /**/
XParam pm;
X{
X return term;
X}
X
Xvoid termsetfn(pm,x) /**/
XParam pm;char *x;
X{
X if (term)
X free(term);
X term = x;
X if (!interact || unset(USEZLE))
X return;
X if (tgetent(termbuf,term) != 1)
X {
X zerr("can't find termcap info for %s",term,0);
X errflag = 0;
X termok = 0;
X }
X else
X {
X char tbuf[1024],*pp;
X int t0;
X
X termok = 1;
X for (t0 = 0; t0 != TC_COUNT; t0++)
X {
X pp = tbuf;
X if (tcstr[t0])
X free(tcstr[t0]);
X if (!tgetstr(tccapnams[t0],&pp))
X tcstr[t0] = NULL, tclen[t0] = 0;
X else
X {
X tcstr[t0] = zalloc(tclen[t0] = pp-tbuf);
X memcpy(tcstr[t0],tbuf,tclen[t0]);
X }
X }
X
X/* if there's no termcap entry for cursor left, use \b. */
X
X if (!tccan(TCLEFT))
X {
X tcstr[TCLEFT] = ztrdup("\b");
X tclen[TCLEFT] = 1;
X }
X
X/* if there's no termcap entry for clear, use ^L. */
X
X if (!tccan(TCCLEARSCREEN))
X {
X tcstr[TCCLEARSCREEN] = ztrdup("\14");
X tclen[TCCLEARSCREEN] = 1;
X }
X
X/* if the termcap entry for down is \n, don't use it. */
X
X if (tccan(TCDOWN) && tcstr[TCDOWN][0] == '\n')
X {
X tclen[TCDOWN] = 0;
X tcstr[TCDOWN] = NULL;
X }
X
X/* if there's no termcap entry for cursor up, forget it.
X Use single line mode. */
X
X if (!tccan(TCUP))
X termok = 0;
X }
X}
X
Xvoid setparams() /**/
X{
Xchar **envp,**envp2,**envp3,*str;
Xchar buf[50];
Xstruct param *pm;
Xint ct;
X
X noerrs = 1;
X for (envp = environ, ct = 2; *envp; envp++,ct++);
X envp = environ;
X envp2 = envp3 = (char **) zalloc(sizeof(char *)*ct);
X for (; *envp; envp++)
X *envp2++ = ztrdup(*envp);
X *envp2 = NULL;
X envp = environ;
X environ = envp2 = envp3;
X for (; *envp; envp++,envp2++) {
X for (str = *envp; *str && *str != '='; str++);
X if (*str == '=') {
X char *iname;
X
X *str = '\0';
X if (isident(*envp))
X pm = setsparam(iname = ztrdup(*envp),ztrdup(str+1));
X *str = '=';
X if (pm) {
X pm->flags |= PMFLAG_x;
X pm->env = *envp2;
X if (pm->flags & PMFLAG_SPECIAL)
X pm->env = replenv(pm->env,getsparam(iname));
X }
X }
X }
X pm = gethnode("HOME",paramtab);
X if (!(pm->flags & PMFLAG_x))
X {
X pm->flags |= PMFLAG_x;
X pm->env = addenv("HOME",home);
X }
X pm = gethnode("PWD",paramtab);
X if (!(pm->flags & PMFLAG_x))
X {
X pm->flags |= PMFLAG_x;
X pm->env = addenv("PWD",cwd);
X }
X pm = gethnode("SHLVL",paramtab);
X if (!(pm->flags & PMFLAG_x))
X pm->flags |= PMFLAG_x;
X sprintf(buf,"%d",++shlvl);
X pm->env = addenv("SHLVL",buf);
X noerrs = 0;
X}
X
Xchar *mkenvstr(x,y) /**/
Xchar *x;char *y;
X{
Xchar *z;
Xint xl = strlen(x),yl = strlen(y);
X
X z = zalloc(xl+yl+2);
X strcpy(z,x);
X z[xl] = '=';
X strcpy(z+xl+1,y);
X z[xl+yl+1] = '\0';
X return z;
X}
X
Xvoid arrfixenv(s,t) /**/
Xchar *s;char **t;
X{
Xchar **ep;
Xint sl = strlen(s);
X
X for (ep = environ; *ep; ep++)
X if (!strncmp(*ep,s,sl) && (*ep)[sl] == '=')
X {
X char *u = colonjoin(t);
X
X replenv(*ep,u);
X free(u);
X break;
X }
X}
X
Xchar *replenv(e,value) /**/
Xchar *e;char *value;
X{
Xchar **ep;
X
X for (ep = environ; *ep; ep++)
X if (*ep == e)
X {
X char *s = e;
X
X while (*s++ != '=');
X *s = '\0';
X *ep = zalloc(strlen(e)+strlen(value)+2);
X strcpy(*ep,e);
X strcat(*ep,value);
X free(e);
X return *ep;
X }
X return NULL;
X}
X
Xchar *addenv(name,value) /**/
Xchar *name;char *value;
X{
Xchar **ep,**ep2,**ep3;
Xint envct;
X
X for (ep = environ; *ep; ep++)
X {
X char *s = *ep,*t = name;
X
X while (*s && *s == *t) s++,t++;
X if (*s == '=' && !*t)
X {
X free(*ep);
X return *ep = mkenvstr(name,value);
X }
X }
X envct = arrlen(environ);
X ep = ep2 = (char **) zalloc((sizeof (char *))*(envct+3));
X for (ep3 = environ; *ep2 = *ep3; ep3++,ep2++);
X *ep2 = mkenvstr(name,value);
X ep2[1] = NULL;
X free(environ);
X environ = ep;
X return *ep2;
X}
X
Xvoid delenv(x) /**/
Xchar *x;
X{
Xchar **ep;
X
X ep = environ;
X for (; *ep; ep++)
X if (*ep == x)
X break;
X if (*ep)
X for (; ep[0] = ep[1]; ep++);
X}
X
Xvoid convbase(s,v,base) /**/
Xchar *s;long v;int base;
X{
Xint digs = 0;
Xlong x;
X
X if (base <= 1)
X base = 10;
X x = v;
X if (x < 0)
X {
X x = -x;
X digs++;
X }
X for (; x; digs++)
X x /= base;
X if (!digs)
X digs = 1;
X s[digs--] = '\0';
X x = (v < 0) ? -v : v;
X while (digs >= 0)
X {
X int dig = x%base;
X s[digs--] = (dig < 10) ? '0'+dig : dig-10+'A';
X x /= base;
X }
X if (v < 0)
X s[0] = '-';
X}
X
X
SHAR_EOF
chmod 0644 zsh2.1/src/params.c ||
echo 'restore of zsh2.1/src/params.c failed'
Wc_c="`wc -c < 'zsh2.1/src/params.c'`"
test 24528 -eq "$Wc_c" ||
echo 'zsh2.1/src/params.c: original size 24528, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= zsh2.1/src/subst.c ==============
if test -f 'zsh2.1/src/subst.c' -a X"$1" != X"-c"; then
echo 'x - skipping zsh2.1/src/subst.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting zsh2.1/src/subst.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/subst.c' &&
X/*
X
X subst.c - various substitutions
X
X This file is part of zsh, the Z shell.
X
X zsh is free software; no one can prevent you from reading the source
X code, or giving it to someone else.
X
X This file is copyrighted under the GNU General Public License, which
X can be found in the file called COPYING.
X
X Copyright (C) 1990, 1991 Paul Falstad
X
X zsh is distributed in the hope that it will be useful, but
X WITHOUT ANY WARRANTY. No author or distributor accepts
X responsibility to anyone for the consequences of using it or for
X whether it serves any particular purpose or works at all, unless he
X says so in writing. Refer to the GNU General Public License
X for full details.
X
X Everyone is granted permission to copy, modify and redistribute
X zsh, but only under the conditions described in the GNU General Public
X License. A copy of this license is supposed to have been given to you
X along with zsh so you can know your rights and responsibilities.
X It should be in a file named COPYING.
X
X Among other things, the copyright notice and this notice must be
X preserved on all copies.
X
X*/
X
X#include "zsh.h"
X#include <pwd.h>
X
X/* do substitutions before fork */
X
Xvoid prefork(list) /**/
XLklist list;
X{
XLknode node = firstnode(list);
Xint qt;
X
X while (node)
X {
X char *str,*str3;
X
X str = str3 = getdata(node);
X if (str[1] == Inpar && (*str == Inang ||
X *str == Outang || *str == Equals))
X {
X if (*str == Inang)
X setdata(node,getoutproc(str+2)); /* <(...) */
X else if (*str == Equals)
X setdata(node,getoutputfile(str+2)); /* =(...) */
X else
X setdata(node,getinproc(str+2)); /* >(...) */
X if (!getdata(node))
X {
X zerr("parse error in process substitution",NULL,0);
X return;
X }
X }
X else while (*str)
X {
X if ((qt = *str == Qstring) || *str == String)
X if (str[1] != Inpar)
X if (str[1] == Inbrack)
X {
X arithsubst((vptr*) &str,&str3); /* $[...] */
X setdata(node,str3);
X }
X else
X {
X paramsubst(list,node,str,str3,qt);
X if (errflag)
X return;
X str3 = str = getdata(node);
X continue;
X }
X str++;
X if (errflag)
X return;
X }
X if (*(char *) getdata(node))
X remnulargs(getdata(node));
X if (unset(IGNOREBRACES))
X while (hasbraces(getdata(node)))
X xpandbraces(list,&node);
X filesub((char **) getaddrdata(node));
X if (errflag)
X return;
X incnode(node);
X }
X}
X
Xvoid postfork(list,doglob) /**/
XLklist list;int doglob;
X{
XLknode node = firstnode(list);
Xint glb = 1;
X
X badcshglob = 0;
X if (isset(NOGLOBOPT) || !doglob)
X glb = 0;
X while (node)
X {
X char *str3,*str;
X
X str = str3 = getdata(node);
X while (*str)
X {
X if (((*str == String || *str == Qstring) && str[1] == Inpar) ||
X *str == Tick || *str == Qtick)
X {
X Lknode n = prevnode(node);
X
X commsubst(list,node,str,str3,
X (*str == Qstring || *str == Qtick)); /* `...`,$(...) */
X if (errflag)
X return;
X str = str3 = getdata(node = nextnode(n));
X }
X str++;
X }
X if (glb)
X {
X if (haswilds(getdata(node)))
X glob(list,&node);
X if (errflag)
X return;
X }
X incnode(node);
X }
X if (badcshglob == 1) zerr("no match",NULL,0);
X}
X
X/* perform substitution on a single word */
X
Xvoid singsub(s) /**/
Xchar **s;
X{
XLklist foo;
Xchar *t;
X
X for (t = *s; *t; t++)
X if (*t == String)
X *t = Qstring;
X else if (*t == Tick)
X *t = Qtick;
X foo = newlist();
X addnode(foo,*s);
X prefork(foo);
X if (errflag)
X return;
X postfork(foo,0);
X if (errflag)
X return;
X *s = ugetnode(foo);
X if (firstnode(foo))
X zerr("ambiguous: %s",*s,0);
X}
X
X/* strdup, but returns "Nularg" if this is a null string */
X
Xvptr nstrdup(s) /**/
Xvptr s;
X{
Xchar *t = s;
Xchar u[2];
X
X u[0] = Nularg; u[1] = '\0';
X if (!*t)
X return strdup(u);
X return strdup(t);
X}
X
Xchar *dynread(stop) /**/
Xint stop;
X{
Xint bsiz = 256,ct = 0,c;
Xchar *buf = zalloc(bsiz),*ptr;
X
X ptr = buf;
X while ((c = hgetc()) != stop)
X {
X *ptr++ = c;
X if (++ct == bsiz)
X {
X buf = realloc(buf,bsiz *= 2);
X ptr = buf+ct;
X }
X }
X *ptr = 0;
X return buf;
X}
X
Xint filesub(namptr) /**/
Xchar **namptr;
X{
Xchar *str = *namptr,*cnam;
X
X if (*str == Tilde && str[1] != '=')
X {
X if (str[1] == '+' && (str[2] == '/' || str[2] == '\0'))
X {
X char *foo = strdup(cwd); /* ~+ */
X
X str+=2;
X modify(&foo,&str);
X *namptr = dyncat(cwd,str);
X return 1;
X }
X else if (str[1] == '-' && (str[2] == '/' || str[2] == '\0'))
X {
X char *foo; /* ~- */
X
X if (cnam = oldpwd)
X foo = cnam;
X else
X foo = cwd;
X str += 2;
X foo = strdup(foo);
X modify(&foo,&str);
X *namptr = dyncat(foo,str);
X return 1;
X }
X if (ialpha(str[1])) /* ~foo */
X {
X char *ptr,*hom;
X
X for (ptr = ++str; *ptr && iuser(*ptr); ptr++)
X if (*ptr == '-')
X *ptr = '-';
X if (*ptr && *ptr != '/') return 0;
X if (!(hom = gethome(str,ptr-str)))
X {
X zerr("user not found: %l",str,ptr-str);
X errflag = 1;
X return 0;
X }
X modify(&hom,&ptr);
X *namptr = dyncat(hom,ptr);
X return 1;
X }
X else if (str[1] == '/') /* ~/foo */
X {
X *namptr = dyncat(home,str+1);
X return 1;
X }
X else if (!str[1]) /* ~ by itself */
X {
X *namptr = strdup(home);
X return 1;
X }
X }
X if (*str == Equals && iuser(str[1]) && unset(NOEQUALS))
X {
X char *ptr,*s,*ds;
X int val;
X
X if (ialpha(str[1])) /* =foo */
X {
X char sav,*pp;
X
X for (pp = str+1; *pp && *pp != ':'; pp++);
X sav = *pp;
X *pp = '\0';
X if (!(cnam = findcmd(str+1)))
X {
X zerr("%s not found",str+1,0);
X errflag = 1;
X return 0;
X }
X *namptr = cnam;
X if ((*pp = sav) == ':')
X {
X modify(namptr,&pp);
X s = *namptr;
X *namptr = dyncat(*namptr,pp);
X }
X return 1;
X }
X if (str[1] == '-') /* =- */
X {
X val = -1;
X ptr = str+2;
X }
X else
X val = zstrtol(str+1,&ptr,10); /* =# */
X ds = dstackent(val);
X if (!ds)
X return 1;
X s = strdup(ds);
X modify(&s,&ptr);
X *namptr = dyncat(s,ptr);
X return 1;
X }
X return 0;
X}
X
X/* get a named directory */
X
Xchar *gethome(user,len) /**/
Xchar *user;int len;
X{
Xchar sav,*str;
Xstruct passwd *pw;
X
X if (len == 0)
X return strdup(home);
X sav = user[len];
X user[len] = '\0';
X if ((str = getsparamval(user,len)) && *str == '/')
X {
X str = strdup(str);
X adduserdir(user,str);
X user[len] = sav;
X return str;
X }
X if (!(pw = getpwnam(user))) {
X user[len] = sav;
X return NULL;
X }
X str = xsymlink(pw->pw_dir);
X adduserdir(user,str);
X user[len] = sav;
X return str;
X}
X
X/* `...`, $(...) */
X
Xvoid commsubst(l,n,str3,str,qt) /**/
XLklist l;Lknode n;char *str3;char *str;int qt;
X{
Xchar *str2;
XLknode where = prevnode(n);
XLklist pl;
X
X if (*str3 == Tick || *str3 == Qtick)
X {
X *str3 = '\0';
X for (str2 = ++str3; *str3 != Tick && *str3 != Qtick; str3++);
X *str3++ = '\0';
X }
X else
X {
X *str3++ = '\0';
X for (str2 = ++str3; *str3 != Outpar; str3++);
X *str3++ = '\0';
X }
X uremnode(l,n);
X if (!(pl = getoutput(str2,qt)))
X {
X zerr("parse error in command substitution",NULL,0);
X errflag = 1;
X return;
X }
X if (full(pl))
X {
X setdata(firstnode(pl),dyncat(str,peekfirst(pl)));
X setdata(lastnode(pl),dyncat(getdata(lastnode(pl)),str3));
X inslist(pl,where,l);
X }
X else
X insnode(l,where,dyncat(str,str3));
X}
X
X/* parameter substitution */
X
Xvoid paramsubst(l,n,aptr,bptr,qt) /**/
XLklist l;Lknode n;char *aptr;char *bptr;int qt;
X{
Xchar *s = aptr,*u,*idbeg,*idend,*ostr = bptr;
Xint brs; /* != 0 means ${...}, otherwise $... */
Xint colf; /* != 0 means we found a colon after the name */
Xint doub = 0; /* != 0 means we have %%, not %, or ##, not # */
Xint isarr = 0;
Xint wasnularr = 0;
Xint plan9 = isset(RCEXPANDPARAM);
Xint getlen = 0;
Xint vunset = 0;
Xint spbreak = isset(SHWORDSPLIT) && !qt;
Xchar *val = NULL,**aval = NULL;
Xint fwidth = 0;
XValue v;
X
X *s++ = '\0';
X if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
X *s != '!' && *s != '$' && *s != String && *s != Qstring &&
X *s != '?' && *s != Quest && *s != '_' &&
X *s != '*' && *s != Star && *s != '@' && *s != '{' &&
X *s != Inbrace && *s != '=' && *s != Hat && *s != '^')
X {
X s[-1] = '$';
X return;
X }
X if (brs = (*s == '{' || *s == Inbrace))
X s++;
X for (;;)
X if (*s == '^' || *s == Hat)
X plan9 ^= 1,s++;
X else if (*s == '=')
X spbreak ^= 1,s++;
X else if ((*s == '#' || *s == Pound) && iident(s[1]))
X getlen = 1,s++;
X else
X break;
X
X idbeg = s;
X if (!(v = getvalue(&s,1)))
X {
X vunset = 1;
X idend = s;
X }
X else
X if (isarr = v->isarr)
X aval = getarrvalue(v);
X else
X {
X val = getstrvalue(v);
X fwidth = v->pm->ct;
X switch (v->pm->flags & (PMFLAG_L | PMFLAG_R | PMFLAG_Z))
X {
X char *t;
X int t0;
X
X case PMFLAG_L:
X case PMFLAG_L|PMFLAG_Z:
X t = val;
X if (v->pm->flags & PMFLAG_Z)
X while (*t == '0') t++;
X else
X while (isep(*t)) t++;
X val = ncalloc(fwidth+1);
X val[fwidth] = '\0';
X if ((t0 = strlen(t)) > fwidth)
X t0 = fwidth;
X memset(val,' ',fwidth);
X strncpy(val,t,t0);
X break;
X case PMFLAG_R:
X case PMFLAG_Z:
X case PMFLAG_Z|PMFLAG_R:
X if (strlen(val) < fwidth) {
X t = ncalloc(fwidth+1);
X memset(t,(v->pm->flags & PMFLAG_R) ? ' ' : '0',fwidth);
X if ((t0 = strlen(val)) > fwidth)
X t0 = fwidth;
X strcpy(t+(fwidth-t0),val);
X val = t;
X } else {
X t = ncalloc(fwidth+1);
X t[fwidth] = '\0';
X strncpy(t,val+strlen(val)-fwidth,fwidth);
X val = t;
X }
X break;
X }
X switch (v->pm->flags & (PMFLAG_l | PMFLAG_u))
X {
X char *t;
X
X case PMFLAG_l:
X t = val;
X for (;*t;t++)
X *t = tulower(*t);
X break;
X case PMFLAG_u:
X t = val;
X for (;*t;t++)
X *t = tuupper(*t);
X break;
X }
X }
X if (colf = *s == ':')
X s++;
X
X /* check for ${..?...} or ${..=..} or one of those. Only works
X if the name is in braces. */
X
X if (brs && (*s == '-' || *s == '=' || *s == '?' || *s == '+' || *s == '#' ||
X *s == '%' || *s == Quest || *s == Pound))
X {
X if (v && v->isarr && (*s == '%' || *s == '#' || *s == Pound))
X {
X zerr("operator requires a scalar",NULL,0);
X return;
X }
X if (*s == s[1])
X {
X s++;
X doub = 1;
X }
X u = ++s;
X if (brs)
X {
X int bct = 1;
X
X for (;;)
X {
X if (*s == '{' || *s == Inbrace)
X bct++;
X else if (*s == '}' || *s == Outbrace)
X bct--;
X if (!bct || !*s)
X break;
X s++;
X }
X }
X else
X {
X while (*s++);
X s--;
X }
X *s++ = '\0';
X if (colf && !vunset)
X vunset = (isarr) ? !*aval : !*val;
X switch (u[-1])
X {
X case '-':
X if (vunset)
X val = strdup(u), isarr = 0;
X break;
X case '=':
X if (vunset)
X {
X char sav = *idend;
X
X *idend = '\0';
X setsparam(idbeg,ztrdup(val = strdup(u)));
X *idend = sav;
X isarr = 0;
X }
X break;
X case '?':
X case Quest:
X if (vunset)
X {
X zerr("%s",(*u) ? u : "parameter not set",0);
X if (!interact)
X exit(1);
X return;
X }
X break;
X case '+':
X if (vunset)
X val = strdup("");
X else
X val = strdup(u);
X isarr = 0;
X break;
X case '#':
X case Pound:
X if (vunset)
X val = strdup("");
X singsub(&u);
X getmatch(&val,u,doub);
X break;
X case '%':
X if (vunset)
X val = strdup("");
X singsub(&u);
X getmatch(&val,u,doub+2);
X break;
X }
X }
X else /* no ${...=...} or anything, but possible modifiers. */
X {
X if (vunset)
X {
X if (isset(NOUNSET))
X {
X zerr("parameter not set",NULL,0);
X return;
X }
X val = strdup("");
X }
X if (colf)
X {
X s--;
X if (!isarr)
X modify(&val,&s);
X /*else
X modifyarr(&aval,&s);*/
X }
X if (brs)
X {
X if (*s != '}' && *s != Outbrace)
X {
X zerr("closing brace expected",NULL,0);
X errflag = 1;
X return;
X }
X s++;
X }
X }
X if (errflag)
X return;
X if (getlen)
X {
X long len = 0;
X char buf[14];
X
X if (isarr)
X {
X char **ctr;
X for (ctr = aval; *ctr; ctr++,len++);
X }
X else
X len = strlen(val);
X sprintf(buf,"%ld",len);
X val = strdup(buf);
X isarr = 0;
X }
X if (isarr)
X if (!aval || !aval[0])
X {
X if (isarr < 0)
X wasnularr = 1;
X val = strdup("");
X isarr = 0;
X }
X else if (!aval[1])
X {
X val = aval[0];
X isarr = 0;
X }
X if (qt)
X {
X if (isarr > 0)
X {
X val = spacejoin(aval);
X isarr = 0;
X }
X }
X else if (spbreak)
X {
X if (isarr)
X val = spacejoin(aval);
X isarr = 1;
X aval = spacesplit(val);
X if (!aval || !aval[0])
X {
X val = strdup("");
X isarr = 0;
X }
X else if (!aval[1])
X {
X val = aval[0];
X isarr = 0;
X }
X /* if only one member, not really an array */
X if (!aval[1])
X isarr = 0;
X }
SHAR_EOF
true || echo 'restore of zsh2.1/src/subst.c failed'
fi
echo 'End of zsh2.1.0 part 9'
echo 'File zsh2.1/src/subst.c is continued in part 10'
echo 10 > _shar_seq_.tmp
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.