diff options
Diffstat (limited to 'do/assign')
-rw-r--r-- | do/assign | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/do/assign b/do/assign new file mode 100644 index 0000000000..2799d024b0 --- /dev/null +++ b/do/assign @@ -0,0 +1,201 @@ +int +do_assign(arg,gimme,arglast) +register ARG *arg; +int gimme; +int *arglast; +{ + + register STR **st = stack->ary_array; + STR **firstrelem = st + arglast[1] + 1; + STR **firstlelem = st + arglast[0] + 1; + STR **lastrelem = st + arglast[2]; + STR **lastlelem = st + arglast[1]; + register STR **relem; + register STR **lelem; + + register STR *TARG; + register ARRAY *ary; + register int makelocal; + HASH *hash; + int i; + + makelocal = (arg->arg_flags & AF_LOCAL) != 0; + localizing = makelocal; + delaymagic = DM_DELAY; /* catch simultaneous items */ + + /* If there's a common identifier on both sides we have to take + * special care that assigning the identifier on the left doesn't + * clobber a value on the right that's used later in the list. + */ + if (arg->arg_flags & AF_COMMON) { + for (relem = firstrelem; relem <= lastrelem; relem++) { + /*SUPPRESS 560*/ + if (TARG = *relem) + *relem = str_mortal(TARG); + } + } + relem = firstrelem; + lelem = firstlelem; + ary = Null(ARRAY*); + hash = Null(HASH*); + while (lelem <= lastlelem) { + TARG = *lelem++; + if (TARG->str_state >= SS_HASH) { + if (TARG->str_state == SS_ARY) { + if (makelocal) + ary = saveary(TARG->str_u.str_stab); + else { + ary = stab_array(TARG->str_u.str_stab); + ary->ary_fill = -1; + } + i = 0; + while (relem <= lastrelem) { /* gobble up all the rest */ + TARG = Str_new(28,0); + if (*relem) + str_sset(TARG,*relem); + *(relem++) = TARG; + (void)astore(ary,i++,TARG); + } + } + else if (TARG->str_state == SS_HASH) { + char *tmps; + STR *tmpstr; + int magic = 0; + STAB *tmpstab = TARG->str_u.str_stab; + + if (makelocal) + hash = savehash(TARG->str_u.str_stab); + else { + hash = stab_hash(TARG->str_u.str_stab); + if (tmpstab == envstab) { + magic = 'E'; + environ[0] = Nullch; + } + else if (tmpstab == sigstab) { + magic = 'S'; +#ifndef NSIG +#define NSIG 32 +#endif + for (i = 1; i < NSIG; i++) + signal(i, SIG_DFL); /* crunch, crunch, crunch */ + } +#ifdef SOME_DBM + else if (hash->tbl_dbm) + magic = 'D'; +#endif + hclear(hash, magic == 'D'); /* wipe any dbm file too */ + + } + while (relem < lastrelem) { /* gobble up all the rest */ + if (*relem) + TARG = *(relem++); + else + TARG = &str_no, relem++; + tmps = str_get(TARG); + tmpstr = Str_new(29,0); + if (*relem) + str_sset(tmpstr,*relem); /* value */ + *(relem++) = tmpstr; + (void)hstore(hash,tmps,TARG->str_cur,tmpstr,0); + if (magic) { + str_magic(tmpstr, tmpstab, magic, tmps, TARG->str_cur); + stabset(tmpstr->str_magic, tmpstr); + } + } + } + else + fatal("panic: do_assign"); + } + else { + if (makelocal) + saveitem(TARG); + if (relem <= lastrelem) { + str_sset(TARG, *relem); + *(relem++) = TARG; + } + else { + str_sset(TARG, &str_undef); + if (gimme == G_ARRAY) { + i = ++lastrelem - firstrelem; + relem++; /* tacky, I suppose */ + astore(stack,i,TARG); + if (st != stack->ary_array) { + st = stack->ary_array; + firstrelem = st + arglast[1] + 1; + firstlelem = st + arglast[0] + 1; + lastlelem = st + arglast[1]; + lastrelem = st + i; + relem = lastrelem + 1; + } + } + } + STABSET(TARG); + } + } + if (delaymagic & ~DM_DELAY) { + if (delaymagic & DM_UID) { +#ifdef HAS_SETREUID + (void)setreuid(uid,euid); +#else /* not HAS_SETREUID */ +#ifdef HAS_SETRUID + if ((delaymagic & DM_UID) == DM_RUID) { + (void)setruid(uid); + delaymagic =~ DM_RUID; + } +#endif /* HAS_SETRUID */ +#ifdef HAS_SETEUID + if ((delaymagic & DM_UID) == DM_EUID) { + (void)seteuid(uid); + delaymagic =~ DM_EUID; + } +#endif /* HAS_SETEUID */ + if (delaymagic & DM_UID) { + if (uid != euid) + fatal("No setreuid available"); + (void)setuid(uid); + } +#endif /* not HAS_SETREUID */ + uid = (int)getuid(); + euid = (int)geteuid(); + } + if (delaymagic & DM_GID) { +#ifdef HAS_SETREGID + (void)setregid(gid,egid); +#else /* not HAS_SETREGID */ +#ifdef HAS_SETRGID + if ((delaymagic & DM_GID) == DM_RGID) { + (void)setrgid(gid); + delaymagic =~ DM_RGID; + } +#endif /* HAS_SETRGID */ +#ifdef HAS_SETEGID + if ((delaymagic & DM_GID) == DM_EGID) { + (void)setegid(gid); + delaymagic =~ DM_EGID; + } +#endif /* HAS_SETEGID */ + if (delaymagic & DM_GID) { + if (gid != egid) + fatal("No setregid available"); + (void)setgid(gid); + } +#endif /* not HAS_SETREGID */ + gid = (int)getgid(); + egid = (int)getegid(); + } + } + delaymagic = 0; + localizing = FALSE; + if (gimme == G_ARRAY) { + i = lastrelem - firstrelem + 1; + if (ary || hash) + Copy(firstrelem, firstlelem, i, STR*); + return arglast[0] + i; + } + else { + str_numset(ARGTARG,(double)(arglast[2] - arglast[1])); + *firstlelem = ARGTARG; + return arglast[0] + 1; + } +} + |