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