perl 5.0 alpha 3
[perl.git] / do / assign
1 int
2 do_assign(arg,gimme,arglast)
3 register ARG *arg;
4 int gimme;
5 int *arglast;
6 {
7
8     register STR **st = stack->ary_array;
9     STR **firstrelem = st + arglast[1] + 1;
10     STR **firstlelem = st + arglast[0] + 1;
11     STR **lastrelem = st + arglast[2];
12     STR **lastlelem = st + arglast[1];
13     register STR **relem;
14     register STR **lelem;
15
16     register STR *TARG;
17     register ARRAY *ary;
18     register int makelocal;
19     HASH *hash;
20     int i;
21
22     makelocal = (arg->arg_flags & AF_LOCAL) != 0;
23     localizing = makelocal;
24     delaymagic = DM_DELAY;              /* catch simultaneous items */
25
26     /* If there's a common identifier on both sides we have to take
27      * special care that assigning the identifier on the left doesn't
28      * clobber a value on the right that's used later in the list.
29      */
30     if (arg->arg_flags & AF_COMMON) {
31         for (relem = firstrelem; relem <= lastrelem; relem++) {
32             /*SUPPRESS 560*/
33             if (TARG = *relem)
34                 *relem = str_mortal(TARG);
35         }
36     }
37     relem = firstrelem;
38     lelem = firstlelem;
39     ary = Null(ARRAY*);
40     hash = Null(HASH*);
41     while (lelem <= lastlelem) {
42         TARG = *lelem++;
43         if (TARG->str_state >= SS_HASH) {
44             if (TARG->str_state == SS_ARY) {
45                 if (makelocal)
46                     ary = saveary(TARG->str_u.str_stab);
47                 else {
48                     ary = stab_array(TARG->str_u.str_stab);
49                     ary->ary_fill = -1;
50                 }
51                 i = 0;
52                 while (relem <= lastrelem) {    /* gobble up all the rest */
53                     TARG = Str_new(28,0);
54                     if (*relem)
55                         str_sset(TARG,*relem);
56                     *(relem++) = TARG;
57                     (void)astore(ary,i++,TARG);
58                 }
59             }
60             else if (TARG->str_state == SS_HASH) {
61                 char *tmps;
62                 STR *tmpstr;
63                 int magic = 0;
64                 STAB *tmpstab = TARG->str_u.str_stab;
65
66                 if (makelocal)
67                     hash = savehash(TARG->str_u.str_stab);
68                 else {
69                     hash = stab_hash(TARG->str_u.str_stab);
70                     if (tmpstab == envstab) {
71                         magic = 'E';
72                         environ[0] = Nullch;
73                     }
74                     else if (tmpstab == sigstab) {
75                         magic = 'S';
76 #ifndef NSIG
77 #define NSIG 32
78 #endif
79                         for (i = 1; i < NSIG; i++)
80                             signal(i, SIG_DFL); /* crunch, crunch, crunch */
81                     }
82 #ifdef SOME_DBM
83                     else if (hash->tbl_dbm)
84                         magic = 'D';
85 #endif
86                     hclear(hash, magic == 'D'); /* wipe any dbm file too */
87
88                 }
89                 while (relem < lastrelem) {     /* gobble up all the rest */
90                     if (*relem)
91                         TARG = *(relem++);
92                     else
93                         TARG = &str_no, relem++;
94                     tmps = str_get(TARG);
95                     tmpstr = Str_new(29,0);
96                     if (*relem)
97                         str_sset(tmpstr,*relem);        /* value */
98                     *(relem++) = tmpstr;
99                     (void)hstore(hash,tmps,TARG->str_cur,tmpstr,0);
100                     if (magic) {
101                         str_magic(tmpstr, tmpstab, magic, tmps, TARG->str_cur);
102                         stabset(tmpstr->str_magic, tmpstr);
103                     }
104                 }
105             }
106             else
107                 fatal("panic: do_assign");
108         }
109         else {
110             if (makelocal)
111                 saveitem(TARG);
112             if (relem <= lastrelem) {
113                 str_sset(TARG, *relem);
114                 *(relem++) = TARG;
115             }
116             else {
117                 str_sset(TARG, &str_undef);
118                 if (gimme == G_ARRAY) {
119                     i = ++lastrelem - firstrelem;
120                     relem++;            /* tacky, I suppose */
121                     astore(stack,i,TARG);
122                     if (st != stack->ary_array) {
123                         st = stack->ary_array;
124                         firstrelem = st + arglast[1] + 1;
125                         firstlelem = st + arglast[0] + 1;
126                         lastlelem = st + arglast[1];
127                         lastrelem = st + i;
128                         relem = lastrelem + 1;
129                     }
130                 }
131             }
132             STABSET(TARG);
133         }
134     }
135     if (delaymagic & ~DM_DELAY) {
136         if (delaymagic & DM_UID) {
137 #ifdef HAS_SETREUID
138             (void)setreuid(uid,euid);
139 #else /* not HAS_SETREUID */
140 #ifdef HAS_SETRUID
141             if ((delaymagic & DM_UID) == DM_RUID) {
142                 (void)setruid(uid);
143                 delaymagic =~ DM_RUID;
144             }
145 #endif /* HAS_SETRUID */
146 #ifdef HAS_SETEUID
147             if ((delaymagic & DM_UID) == DM_EUID) {
148                 (void)seteuid(uid);
149                 delaymagic =~ DM_EUID;
150             }
151 #endif /* HAS_SETEUID */
152             if (delaymagic & DM_UID) {
153                 if (uid != euid)
154                     fatal("No setreuid available");
155                 (void)setuid(uid);
156             }
157 #endif /* not HAS_SETREUID */
158             uid = (int)getuid();
159             euid = (int)geteuid();
160         }
161         if (delaymagic & DM_GID) {
162 #ifdef HAS_SETREGID
163             (void)setregid(gid,egid);
164 #else /* not HAS_SETREGID */
165 #ifdef HAS_SETRGID
166             if ((delaymagic & DM_GID) == DM_RGID) {
167                 (void)setrgid(gid);
168                 delaymagic =~ DM_RGID;
169             }
170 #endif /* HAS_SETRGID */
171 #ifdef HAS_SETEGID
172             if ((delaymagic & DM_GID) == DM_EGID) {
173                 (void)setegid(gid);
174                 delaymagic =~ DM_EGID;
175             }
176 #endif /* HAS_SETEGID */
177             if (delaymagic & DM_GID) {
178                 if (gid != egid)
179                     fatal("No setregid available");
180                 (void)setgid(gid);
181             }
182 #endif /* not HAS_SETREGID */
183             gid = (int)getgid();
184             egid = (int)getegid();
185         }
186     }
187     delaymagic = 0;
188     localizing = FALSE;
189     if (gimme == G_ARRAY) {
190         i = lastrelem - firstrelem + 1;
191         if (ary || hash)
192             Copy(firstrelem, firstlelem, i, STR*);
193         return arglast[0] + i;
194     }
195     else {
196         str_numset(ARGTARG,(double)(arglast[2] - arglast[1]));
197         *firstlelem = ARGTARG;
198         return arglast[0] + 1;
199     }
200 }
201