perl 3.0 patch #44 patch #42, continued
[p5sagit/p5-mst-13.2.git] / evalargs.xc
1 /* This file is included by eval.c.  It's separate from eval.c to keep
2  * kit sizes from getting too big.
3  */
4
5 /* $Header: evalargs.xc,v 3.0.1.9 91/01/11 18:00:18 lwall Locked $
6  *
7  * $Log:        evalargs.xc,v $
8  * Revision 3.0.1.9  91/01/11  18:00:18  lwall
9  * patch42: <> input to individual array elements was suboptimal
10  * 
11  * Revision 3.0.1.8  90/11/10  01:35:49  lwall
12  * patch38: array slurps are now faster and take less memory
13  * 
14  * Revision 3.0.1.7  90/10/15  16:48:11  lwall
15  * patch29: non-existent array values no longer cause core dumps
16  * patch29: added caller
17  * 
18  * Revision 3.0.1.6  90/08/09  03:37:15  lwall
19  * patch19: passing *name to subroutine now forces filehandle and array creation
20  * patch19: `command` in array context now returns array of lines
21  * patch19: <handle> input is a little more efficient
22  * 
23  * Revision 3.0.1.5  90/03/27  15:54:42  lwall
24  * patch16: MSDOS support
25  * 
26  * Revision 3.0.1.4  90/02/28  17:38:37  lwall
27  * patch9: $#foo -= 2 didn't work
28  * 
29  * Revision 3.0.1.3  89/11/17  15:25:07  lwall
30  * patch5: constant numeric subscripts disappeared in ?:
31  * 
32  * Revision 3.0.1.2  89/11/11  04:33:05  lwall
33  * patch2: Configure now locates csh
34  * 
35  * Revision 3.0.1.1  89/10/26  23:12:55  lwall
36  * patch1: glob didn't free a temporary string
37  * 
38  * Revision 3.0  89/10/18  15:17:16  lwall
39  * 3.0 baseline
40  * 
41  */
42
43     for (anum = 1; anum <= maxarg; anum++) {
44         argflags = arg[anum].arg_flags;
45         argtype = arg[anum].arg_type;
46         argptr = arg[anum].arg_ptr;
47       re_eval:
48         switch (argtype) {
49         default:
50             st[++sp] = &str_undef;
51 #ifdef DEBUGGING
52             tmps = "NULL";
53 #endif
54             break;
55         case A_EXPR:
56 #ifdef DEBUGGING
57             if (debug & 8) {
58                 tmps = "EXPR";
59                 deb("%d.EXPR =>\n",anum);
60             }
61 #endif
62             sp = eval(argptr.arg_arg,
63                 (argflags & AF_ARYOK) ? G_ARRAY : G_SCALAR, sp);
64             if (sp + (maxarg - anum) > stack->ary_max)
65                 astore(stack, sp + (maxarg - anum), Nullstr);
66             st = stack->ary_array;      /* possibly reallocated */
67             break;
68         case A_CMD:
69 #ifdef DEBUGGING
70             if (debug & 8) {
71                 tmps = "CMD";
72                 deb("%d.CMD (%lx) =>\n",anum,argptr.arg_cmd);
73             }
74 #endif
75             sp = cmd_exec(argptr.arg_cmd, gimme, sp);
76             if (sp + (maxarg - anum) > stack->ary_max)
77                 astore(stack, sp + (maxarg - anum), Nullstr);
78             st = stack->ary_array;      /* possibly reallocated */
79             break;
80         case A_LARYSTAB:
81             ++sp;
82             switch (optype) {
83                 case O_ITEM2: argtype = 2; break;
84                 case O_ITEM3: argtype = 3; break;
85                 default:      argtype = anum; break;
86             }
87             str = afetch(stab_array(argptr.arg_stab),
88                 arg[argtype].arg_len - arybase, TRUE);
89 #ifdef DEBUGGING
90             if (debug & 8) {
91                 (void)sprintf(buf,"LARYSTAB $%s[%d]",stab_name(argptr.arg_stab),
92                     arg[argtype].arg_len);
93                 tmps = buf;
94             }
95 #endif
96             goto do_crement;
97         case A_ARYSTAB:
98             switch (optype) {
99                 case O_ITEM2: argtype = 2; break;
100                 case O_ITEM3: argtype = 3; break;
101                 default:      argtype = anum; break;
102             }
103             st[++sp] = afetch(stab_array(argptr.arg_stab),
104                 arg[argtype].arg_len - arybase, FALSE);
105 #ifdef DEBUGGING
106             if (debug & 8) {
107                 (void)sprintf(buf,"ARYSTAB $%s[%d]",stab_name(argptr.arg_stab),
108                     arg[argtype].arg_len);
109                 tmps = buf;
110             }
111 #endif
112             break;
113         case A_STAR:
114             stab = argptr.arg_stab;
115             st[++sp] = (STR*)stab;
116             if (!stab_xarray(stab))
117                 aadd(stab);
118             if (!stab_xhash(stab))
119                 hadd(stab);
120             if (!stab_io(stab))
121                 stab_io(stab) = stio_new();
122 #ifdef DEBUGGING
123             if (debug & 8) {
124                 (void)sprintf(buf,"STAR *%s",stab_name(argptr.arg_stab));
125                 tmps = buf;
126             }
127 #endif
128             break;
129         case A_LSTAR:
130             str = st[++sp] = (STR*)argptr.arg_stab;
131 #ifdef DEBUGGING
132             if (debug & 8) {
133                 (void)sprintf(buf,"LSTAR *%s",stab_name(argptr.arg_stab));
134                 tmps = buf;
135             }
136 #endif
137             break;
138         case A_STAB:
139             st[++sp] = STAB_STR(argptr.arg_stab);
140 #ifdef DEBUGGING
141             if (debug & 8) {
142                 (void)sprintf(buf,"STAB $%s",stab_name(argptr.arg_stab));
143                 tmps = buf;
144             }
145 #endif
146             break;
147         case A_LEXPR:
148 #ifdef DEBUGGING
149             if (debug & 8) {
150                 tmps = "LEXPR";
151                 deb("%d.LEXPR =>\n",anum);
152             }
153 #endif
154             if (argflags & AF_ARYOK) {
155                 sp = eval(argptr.arg_arg, G_ARRAY, sp);
156                 if (sp + (maxarg - anum) > stack->ary_max)
157                     astore(stack, sp + (maxarg - anum), Nullstr);
158                 st = stack->ary_array;  /* possibly reallocated */
159             }
160             else {
161                 sp = eval(argptr.arg_arg, G_SCALAR, sp);
162                 st = stack->ary_array;  /* possibly reallocated */
163                 str = st[sp];
164                 goto do_crement;
165             }
166             break;
167         case A_LVAL:
168 #ifdef DEBUGGING
169             if (debug & 8) {
170                 (void)sprintf(buf,"LVAL $%s",stab_name(argptr.arg_stab));
171                 tmps = buf;
172             }
173 #endif
174             ++sp;
175             str = STAB_STR(argptr.arg_stab);
176             if (!str)
177                 fatal("panic: A_LVAL");
178           do_crement:
179             assigning = TRUE;
180             if (argflags & AF_PRE) {
181                 if (argflags & AF_UP)
182                     str_inc(str);
183                 else
184                     str_dec(str);
185                 STABSET(str);
186                 st[sp] = str;
187                 str = arg->arg_ptr.arg_str;
188             }
189             else if (argflags & AF_POST) {
190                 st[sp] = str_static(str);
191                 if (argflags & AF_UP)
192                     str_inc(str);
193                 else
194                     str_dec(str);
195                 STABSET(str);
196                 str = arg->arg_ptr.arg_str;
197             }
198             else
199                 st[sp] = str;
200             break;
201         case A_LARYLEN:
202             ++sp;
203             stab = argptr.arg_stab;
204             str = stab_array(argptr.arg_stab)->ary_magic;
205             if (optype != O_SASSIGN || argflags & (AF_PRE|AF_POST))
206                 str_numset(str,(double)(stab_array(stab)->ary_fill+arybase));
207 #ifdef DEBUGGING
208             tmps = "LARYLEN";
209 #endif
210             if (!str)
211                 fatal("panic: A_LEXPR");
212             goto do_crement;
213         case A_ARYLEN:
214             stab = argptr.arg_stab;
215             st[++sp] = stab_array(stab)->ary_magic;
216             str_numset(st[sp],(double)(stab_array(stab)->ary_fill+arybase));
217 #ifdef DEBUGGING
218             tmps = "ARYLEN";
219 #endif
220             break;
221         case A_SINGLE:
222             st[++sp] = argptr.arg_str;
223 #ifdef DEBUGGING
224             tmps = "SINGLE";
225 #endif
226             break;
227         case A_DOUBLE:
228             (void) interp(str,argptr.arg_str,sp);
229             st = stack->ary_array;
230             st[++sp] = str;
231 #ifdef DEBUGGING
232             tmps = "DOUBLE";
233 #endif
234             break;
235         case A_BACKTICK:
236             tmps = str_get(interp(str,argptr.arg_str,sp));
237             st = stack->ary_array;
238 #ifdef TAINT
239             taintproper("Insecure dependency in ``");
240 #endif
241             fp = mypopen(tmps,"r");
242             str_set(str,"");
243             if (fp) {
244                 if (gimme == G_SCALAR) {
245                     while (str_gets(str,fp,str->str_cur) != Nullch)
246                         ;
247                 }
248                 else {
249                     for (;;) {
250                         if (++sp > stack->ary_max) {
251                             astore(stack, sp, Nullstr);
252                             st = stack->ary_array;
253                         }
254                         str = st[sp] = Str_new(56,80);
255                         if (str_gets(str,fp,0) == Nullch) {
256                             sp--;
257                             break;
258                         }
259                         if (str->str_len - str->str_cur > 20) {
260                             str->str_len = str->str_cur+1;
261                             Renew(str->str_ptr, str->str_len, char);
262                         }
263                         str_2static(str);
264                     }
265                 }
266                 statusvalue = mypclose(fp);
267             }
268             else
269                 statusvalue = -1;
270
271             if (gimme == G_SCALAR)
272                 st[++sp] = str;
273 #ifdef DEBUGGING
274             tmps = "BACK";
275 #endif
276             break;
277         case A_WANTARRAY:
278             {
279                 if (curcsv->wantarray == G_ARRAY)
280                     st[++sp] = &str_yes;
281                 else
282                     st[++sp] = &str_no;
283             }
284 #ifdef DEBUGGING
285             tmps = "WANTARRAY";
286 #endif
287             break;
288         case A_INDREAD:
289             last_in_stab = stabent(str_get(STAB_STR(argptr.arg_stab)),TRUE);
290             old_record_separator = record_separator;
291             goto do_read;
292         case A_GLOB:
293             argflags |= AF_POST;        /* enable newline chopping */
294             last_in_stab = argptr.arg_stab;
295             old_record_separator = record_separator;
296 #ifdef MSDOS
297             record_separator = 0;
298 #else
299 #ifdef CSH
300             record_separator = 0;
301 #else
302             record_separator = '\n';
303 #endif  /* !CSH */
304 #endif  /* !MSDOS */
305             goto do_read;
306         case A_READ:
307             last_in_stab = argptr.arg_stab;
308             old_record_separator = record_separator;
309           do_read:
310             if (anum > 1)               /* assign to scalar */
311                 gimme = G_SCALAR;       /* force context to scalar */
312             if (gimme == G_ARRAY)
313                 str = Str_new(57,0);
314             ++sp;
315             fp = Nullfp;
316             if (stab_io(last_in_stab)) {
317                 fp = stab_io(last_in_stab)->ifp;
318                 if (!fp) {
319                     if (stab_io(last_in_stab)->flags & IOF_ARGV) {
320                         if (stab_io(last_in_stab)->flags & IOF_START) {
321                             stab_io(last_in_stab)->flags &= ~IOF_START;
322                             stab_io(last_in_stab)->lines = 0;
323                             if (alen(stab_array(last_in_stab)) < 0) {
324                                 tmpstr = str_make("-",1); /* assume stdin */
325                                 (void)apush(stab_array(last_in_stab), tmpstr);
326                             }
327                         }
328                         fp = nextargv(last_in_stab);
329                         if (!fp) { /* Note: fp != stab_io(last_in_stab)->ifp */
330                             (void)do_close(last_in_stab,FALSE); /* now it does*/
331                             stab_io(last_in_stab)->flags |= IOF_START;
332                         }
333                     }
334                     else if (argtype == A_GLOB) {
335                         (void) interp(str,stab_val(last_in_stab),sp);
336                         st = stack->ary_array;
337                         tmpstr = Str_new(55,0);
338 #ifdef MSDOS
339                         str_set(tmpstr, "perlglob ");
340                         str_scat(tmpstr,str);
341                         str_cat(tmpstr," |");
342 #else
343 #ifdef CSH
344                         str_nset(tmpstr,cshname,cshlen);
345                         str_cat(tmpstr," -cf 'set nonomatch; glob ");
346                         str_scat(tmpstr,str);
347                         str_cat(tmpstr,"'|");
348 #else
349                         str_set(tmpstr, "echo ");
350                         str_scat(tmpstr,str);
351                         str_cat(tmpstr,
352                           "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
353 #endif /* !CSH */
354 #endif /* !MSDOS */
355                         (void)do_open(last_in_stab,tmpstr->str_ptr,
356                           tmpstr->str_cur);
357                         fp = stab_io(last_in_stab)->ifp;
358                         str_free(tmpstr);
359                     }
360                 }
361             }
362             if (!fp && dowarn)
363                 warn("Read on closed filehandle <%s>",stab_name(last_in_stab));
364             when = str->str_len;        /* remember if already alloced */
365             if (!when)
366                 Str_Grow(str,80);       /* try short-buffering it */
367           keepgoing:
368             if (!fp)
369                 st[sp] = &str_undef;
370             else if (!str_gets(str,fp, optype == O_RCAT ? str->str_cur : 0)) {
371                 clearerr(fp);
372                 if (stab_io(last_in_stab)->flags & IOF_ARGV) {
373                     fp = nextargv(last_in_stab);
374                     if (fp)
375                         goto keepgoing;
376                     (void)do_close(last_in_stab,FALSE);
377                     stab_io(last_in_stab)->flags |= IOF_START;
378                 }
379                 else if (argflags & AF_POST) {
380                     (void)do_close(last_in_stab,FALSE);
381                 }
382                 st[sp] = &str_undef;
383                 record_separator = old_record_separator;
384                 if (gimme == G_ARRAY) {
385                     --sp;
386                     str_2static(str);
387                     goto array_return;
388                 }
389                 break;
390             }
391             else {
392                 stab_io(last_in_stab)->lines++;
393                 st[sp] = str;
394 #ifdef TAINT
395                 str->str_tainted = 1; /* Anything from the outside world...*/
396 #endif
397                 if (argflags & AF_POST) {
398                     if (str->str_cur > 0)
399                         str->str_cur--;
400                     if (str->str_ptr[str->str_cur] == record_separator)
401                         str->str_ptr[str->str_cur] = '\0';
402                     else
403                         str->str_cur++;
404                     for (tmps = str->str_ptr; *tmps; tmps++)
405                         if (!isalpha(*tmps) && !isdigit(*tmps) &&
406                             index("$&*(){}[]'\";\\|?<>~`",*tmps))
407                                 break;
408                     if (*tmps && stat(str->str_ptr,&statbuf) < 0)
409                         goto keepgoing;         /* unmatched wildcard? */
410                 }
411                 if (gimme == G_ARRAY) {
412                     if (str->str_len - str->str_cur > 20) {
413                         str->str_len = str->str_cur+1;
414                         Renew(str->str_ptr, str->str_len, char);
415                     }
416                     str_2static(str);
417                     if (++sp > stack->ary_max) {
418                         astore(stack, sp, Nullstr);
419                         st = stack->ary_array;
420                     }
421                     str = Str_new(58,80);
422                     goto keepgoing;
423                 }
424                 else if (!when && str->str_len - str->str_cur > 80) {
425                     /* try to reclaim a bit of scalar space on 1st alloc */
426                     if (str->str_cur < 60)
427                         str->str_len = 80;
428                     else
429                         str->str_len = str->str_cur+40; /* allow some slop */
430                     Renew(str->str_ptr, str->str_len, char);
431                 }
432             }
433             record_separator = old_record_separator;
434 #ifdef DEBUGGING
435             tmps = "READ";
436 #endif
437             break;
438         }
439 #ifdef DEBUGGING
440         if (debug & 8)
441             deb("%d.%s = '%s'\n",anum,tmps,str_peek(st[sp]));
442 #endif
443         if (anum < 8)
444             arglast[anum] = sp;
445     }