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 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 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.