* Copyright (c) 1980, 1991 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)set.c 5.12 (Berkeley) 6/14/91";
static Char
*getinx
__P((Char
*, int *));
static void asx
__P((Char
*, int, Char
*));
*getvx
__P((Char
*, int));
static Char
*xset
__P((Char
*, Char
***));
static Char
*operate
__P((int, Char
*, Char
*));
static void putn1
__P((int));
*madrof
__P((Char
*, struct varent
*));
static void unsetv1
__P((struct varent
*));
static void exportpath
__P((Char
**));
static void balance
__P((struct varent
*, int, int));
if (vp
== p
|| !letter(*vp
))
stderror(ERR_NAME
| ERR_VARBEGIN
);
if ((p
- vp
) > MAXVARLEN
) {
stderror(ERR_NAME
| ERR_VARTOOLONG
);
if (*p
== 0 && *v
&& **v
== '(')
else if (*v
&& eq(*v
, STRequal
)) {
stderror(ERR_NAME
| ERR_SYNTAX
);
stderror(ERR_NAME
| ERR_SYNTAX
);
stderror(ERR_NAME
| ERR_MISSING
, ')');
asx(vp
, subscr
, Strsave(p
));
exportpath(adrof(STRpath
)->vec
);
else if (eq(vp
, STRhistchars
)) {
register Char
*pn
= value(STRhistchars
);
else if (eq(vp
, STRuser
)) {
Setenv(STRUSER
, value(vp
));
Setenv(STRLOGNAME
, value(vp
));
else if (eq(vp
, STRwordchars
)) {
else if (eq(vp
, STRterm
))
Setenv(STRTERM
, value(vp
));
else if (eq(vp
, STRhome
)) {
cp
= Strsave(value(vp
)); /* get the old value back */
* convert to cononical pathname (possibly resolving symlinks)
set(vp
, Strsave(cp
)); /* have to save the new val */
/* and now mirror home with HOME */
/* fix directory stack for new tilde home */
else if (eq(vp
, STRfilec
))
while (*cp
&& Isdigit(*cp
))
*ip
= *ip
* 10 + *cp
++ - '0';
stderror(ERR_NAME
| ERR_SUBSCRIPT
);
register struct varent
*v
= getvx(vp
, subscr
);
xfree((ptr_t
) v
->vec
[subscr
- 1]);
v
->vec
[subscr
- 1] = globone(p
, G_APPEND
);
register struct varent
*v
= adrof(vp
);
if (subscr
< 1 || subscr
> blklen(v
->vec
))
stderror(ERR_NAME
| ERR_RANGE
);
if (vp
== p
|| !letter(*vp
))
stderror(ERR_NAME
| ERR_VARBEGIN
);
if ((p
- vp
) > MAXVARLEN
)
stderror(ERR_NAME
| ERR_VARTOOLONG
);
stderror(ERR_NAME
| ERR_ASSIGN
);
if (*p
== '\0' && *v
== NULL
)
stderror(ERR_NAME
| ERR_ASSIGN
);
stderror(ERR_NAME
| ERR_UNKNOWNOP
);
stderror(ERR_NAME
| ERR_UNKNOWNOP
);
stderror(ERR_NAME
| ERR_SYNTAX
);
stderror(ERR_NAME
| ERR_UNKNOWNOP
);
struct varent
*gv
= getvx(vp
, subscr
);
asx(vp
, subscr
, operate(op
, gv
->vec
[subscr
- 1], p
));
set(vp
, operate(op
, value(vp
), p
));
exportpath(adrof(STRpath
)->vec
);
if (op
== '<' || op
== '>')
stderror(ERR_NAME
| ERR_EXPRESSION
);
num
= 2; /* confuse lint */
if (sizeof(int) == num
&& n
== -32768) {
num
= 4; /* confuse lint */
if (sizeof(int) == num
&& n
== -2147483648) {
return (Strsave(number
));
if (cp
[0] == '+' && cp
[1])
stderror(ERR_NAME
| ERR_BADNUM
);
n
= n
* 10 + *cp
++ - '0';
stderror(ERR_NAME
| ERR_BADNUM
);
register struct varent
*vp
;
return (vp
== 0 || vp
->vec
[0] == 0 ? STRNULL
: vp
->vec
[0]);
register struct varent
*vp
;
register struct varent
*vp1
;
for (; vp
; vp
= vp
->v_right
) {
if (vp
->v_left
&& (vp1
= madrof(pat
, vp
->v_left
)))
if (Gmatch(vp
->v_name
, pat
))
register struct varent
*v
;
while (v
&& ((cmp
= *name
- *v
->v_name
) ||
(cmp
= Strcmp(name
, v
->v_name
))))
* The caller is responsible for putting value in a safe place
register Char
**vec
= (Char
**) xmalloc((size_t) (2 * sizeof(Char
**)));
register Char
**oldv
= vec
;
stderror(ERR_NAME
| ERR_NOMATCH
);
register struct varent
*p
;
register struct varent
*c
;
f
= 0; /* tree hangs off the header's left link */
while (c
= p
->v_link
[f
]) {
if ((f
= *name
- *c
->v_name
) == 0 &&
(f
= Strcmp(name
, c
->v_name
)) == 0) {
p
->v_link
[f
] = c
= (struct varent
*) xmalloc((size_t) sizeof(struct varent
));
c
->v_name
= Strsave(name
);
c
->v_left
= c
->v_right
= 0;
if (adrof(STRfilec
) == 0)
if (adrof(STRhistchars
) == 0) {
if (adrof(STRwordchars
) == 0)
word_chars
= STR_WORD_CHARS
;
register struct varent
*vp
;
while (vp
= madrof(*v
, head
->v_left
))
register struct varent
*vp
;
if ((vp
= adrof1(var
, &shvhed
)) == 0)
register struct varent
*p
;
register struct varent
*c
, *pp
;
* Free associated memory first to avoid complications.
xfree((ptr_t
) p
->v_name
);
* If p is missing one child, then we can move the other into where p is.
* Otherwise, we find the predecessor of p, which is guaranteed to have no
* right child, copy it into p, and move it's left child into it.
for (c
= p
->v_left
; c
->v_right
; c
= c
->v_right
);
* Move c into where p is.
* Free the deleted node, and rebalance.
set(cp
, Strsave(STRNULL
));
register struct varent
*argv
;
stderror(ERR_NAME
| ERR_NOMORE
);
if (Strlen(*val
) + Strlen(exppath
) + 2 > BUFSIZ
) {
xprintf("Warning: ridiculously long PATH truncated\n");
(void) Strcat(exppath
, *val
++);
if (*val
== 0 || eq(*val
, STRRparen
))
(void) Strcat(exppath
, STRcolon
);
Setenv(STRPATH
, exppath
);
* Lint thinks these have null effect
/* macros to do single rotations on node p */
(t)->v_parent = (p)->v_parent,\
((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
(t->v_right = (p))->v_parent = t,\
(t)->v_parent = (p)->v_parent,\
((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
(t->v_left = (p))->v_parent = t,\
* Rebalance a tree, starting at p and up.
* F == 0 means we've come from p's left child.
* D == 1 means we've just done a delete, otherwise an insert.
register struct varent
*p
;
register struct varent
*pp
;
register struct varent
*t
; /* used by the rotate macros */
* Ok, from here on, p is the node we're operating on; pp is it's parent; f
* is the branch of p from which we have come; ff is the branch of pp which
for (; pp
= p
->v_parent
; p
= pp
, f
= ff
) {
if (f
^ d
) { /* right heavy */
case -1: /* was left heavy */
case 0: /* was balanced */
case 1: /* was already right heavy */
switch (p
->v_right
->v_bal
) {
case 1: /* sigle rotate */
pp
->v_link
[ff
] = rleft(p
);
case 0: /* single rotate */
pp
->v_link
[ff
] = rleft(p
);
case -1: /* double rotate */
(void) rright(p
->v_right
);
pp
->v_link
[ff
] = rleft(p
);
case 1: /* was right heavy */
case 0: /* was balanced */
case -1: /* was already left heavy */
switch (p
->v_left
->v_bal
) {
case -1: /* single rotate */
pp
->v_link
[ff
] = rright(p
);
case 0: /* signle rotate */
pp
->v_link
[ff
] = rright(p
);
case 1: /* double rotate */
pp
->v_link
[ff
] = rright(p
);
* If from insert, then we terminate when p is balanced. If from
* delete, then we terminate when p is unbalanced.
register struct varent
*p
;
register struct varent
*c
;
(void) sigsetmask(sigblock((sigset_t
) 0) & ~sigmask(SIGINT
));
if (p
->v_parent
== 0) /* is it the header? */
xprintf(short2str(p
->v_name
));
} while (p
->v_right
== c
);