Change the scan policy of the *.t and test.pl files,
[p5sagit/p5-mst-13.2.git] / x2p / a2py.c
CommitLineData
79072805 1/* $RCSfile: a2py.c,v $$Revision: 4.1 $$Date: 92/08/07 18:29:14 $
a687059c 2 *
9607fc9c 3 * Copyright (c) 1991-1997, Larry Wall
a687059c 4 *
2b317908 5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
8d063cd8 7 *
8 * $Log: a2py.c,v $
8d063cd8 9 */
10
2986a63f 11#if defined(OS2) || defined(WIN32) || defined(NETWARE)
2c5424a7 12#if defined(WIN32)
13#include <io.h>
14#endif
2986a63f 15#if defined(NETWARE)
16#include "../netware/clibstuf.h"
17#endif
bf10efe7 18#include "../patchlevel.h"
39c3038c 19#endif
8d063cd8 20#include "util.h"
8d063cd8 21
22char *filename;
39c3038c 23char *myname;
8d063cd8 24
378cc40b 25int checkers = 0;
748a9306 26
f0f333f4 27int oper0(int type);
28int oper1(int type, int arg1);
29int oper2(int type, int arg1, int arg2);
30int oper3(int type, int arg1, int arg2, int arg3);
31int oper4(int type, int arg1, int arg2, int arg3, int arg4);
32int oper5(int type, int arg1, int arg2, int arg3, int arg4, int arg5);
33STR *walk(int useval, int level, register int node, int *numericptr, int minprec);
378cc40b 34
2986a63f 35#if defined(OS2) || defined(WIN32) || defined(NETWARE)
d07c2202 36static void usage(void);
37
9607fc9c 38static void
39c3038c 39usage()
40{
cceca5ed 41 printf("\nThis is the AWK to PERL translator, revision %d.0, version %d\n", PERL_REVISION, PERL_VERSION);
39c3038c 42 printf("\nUsage: %s [-D<number>] [-F<char>] [-n<fieldlist>] [-<number>] filename\n", myname);
43 printf("\n -D<number> sets debugging flags."
44 "\n -F<character> the awk script to translate is always invoked with"
45 "\n this -F switch."
46 "\n -n<fieldlist> specifies the names of the input fields if input does"
47 "\n not have to be split into an array."
48 "\n -<number> causes a2p to assume that input will always have that"
49 "\n many fields.\n");
50 exit(1);
51}
52#endif
9607fc9c 53
54int
f0f333f4 55main(register int argc, register char **argv, register char **env)
8d063cd8 56{
57 register STR *str;
8d063cd8 58 int i;
8d063cd8 59 STR *tmpstr;
60
2986a63f 61 #ifdef NETWARE
62 fnInitGpfGlobals(); // For importing the CLIB calls in place of Watcom calls
63 #endif /* NETWARE */
64
39c3038c 65 myname = argv[0];
8d063cd8 66 linestr = str_new(80);
67 str = str_new(0); /* first used for -I flags */
68 for (argc--,argv++; argc; argc--,argv++) {
69 if (argv[0][0] != '-' || !argv[0][1])
70 break;
8d063cd8 71 switch (argv[0][1]) {
72#ifdef DEBUGGING
73 case 'D':
74 debug = atoi(argv[0]+2);
9d116dd7 75#if YYDEBUG
8d063cd8 76 yydebug = (debug & 1);
77#endif
78 break;
79#endif
80 case '0': case '1': case '2': case '3': case '4':
81 case '5': case '6': case '7': case '8': case '9':
82 maxfld = atoi(argv[0]+1);
83 absmaxfld = TRUE;
84 break;
85 case 'F':
86 fswitch = argv[0][2];
87 break;
88 case 'n':
89 namelist = savestr(argv[0]+2);
90 break;
a5571d59 91 case 'o':
92 old_awk = TRUE;
93 break;
8d063cd8 94 case '-':
95 argc--,argv++;
96 goto switch_end;
97 case 0:
98 break;
99 default:
2986a63f 100#if defined(OS2) || defined(WIN32) || defined(NETWARE)
d07c2202 101 fprintf(stderr, "Unrecognized switch: %s\n",argv[0]);
39c3038c 102 usage();
d07c2202 103#else
104 fatal("Unrecognized switch: %s\n",argv[0]);
39c3038c 105#endif
8d063cd8 106 }
107 }
108 switch_end:
109
110 /* open script */
111
39c3038c 112 if (argv[0] == Nullch) {
2986a63f 113#if defined(OS2) || defined(WIN32) || defined(NETWARE)
39c3038c 114 if ( isatty(fileno(stdin)) )
115 usage();
116#endif
117 argv[0] = "-";
118 }
119 filename = savestr(argv[0]);
120
8d063cd8 121 filename = savestr(argv[0]);
122 if (strEQ(filename,"-"))
123 argv[0] = "";
124 if (!*argv[0])
125 rsfp = stdin;
126 else
127 rsfp = fopen(argv[0],"r");
128 if (rsfp == Nullfp)
129 fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
130
131 /* init tokener */
132
133 bufptr = str_get(linestr);
134 symtab = hnew();
a687059c 135 curarghash = hnew();
8d063cd8 136
137 /* now parse the report spec */
138
139 if (yyparse())
140 fatal("Translation aborted due to syntax errors.\n");
141
142#ifdef DEBUGGING
143 if (debug & 2) {
144 int type, len;
145
146 for (i=1; i<mop;) {
147 type = ops[i].ival;
148 len = type >> 8;
149 type &= 255;
150 printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
151 if (type == OSTRING)
152 printf("\t\"%s\"\n",ops[i].cval),i++;
153 else {
154 while (len--) {
155 printf("\t%d",ops[i].ival),i++;
156 }
157 putchar('\n');
158 }
159 }
160 }
161 if (debug & 8)
162 dump(root);
163#endif
164
165 /* first pass to look for numeric variables */
166
167 prewalk(0,0,root,&i);
168
169 /* second pass to produce new program */
170
a687059c 171 tmpstr = walk(0,0,root,&i,P_MIN);
207d4cd0 172 str = str_make(STARTPERL);
5f05dabc 173 str_cat(str, "\neval 'exec ");
174 str_cat(str, BIN);
175 str_cat(str, "/perl -S $0 ${1+\"$@\"}'\n\
378cc40b 176 if $running_under_some_shell;\n\
177 # this emulates #! processing on NIH machines.\n\
178 # (remove #! line above if indigestible)\n\n");
a559c259 179 str_cat(str,
a0d0e21e 180 "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;\n");
a559c259 181 str_cat(str,
182 " # process any FOO=bar switches\n\n");
8d063cd8 183 if (do_opens && opens) {
184 str_scat(str,opens);
185 str_free(opens);
186 str_cat(str,"\n");
187 }
188 str_scat(str,tmpstr);
189 str_free(tmpstr);
190#ifdef DEBUGGING
191 if (!(debug & 16))
192#endif
193 fixup(str);
194 putlines(str);
378cc40b 195 if (checkers) {
196 fprintf(stderr,
197 "Please check my work on the %d line%s I've marked with \"#???\".\n",
198 checkers, checkers == 1 ? "" : "s" );
199 fprintf(stderr,
200 "The operation I've selected may be wrong for the operand types.\n");
201 }
8d063cd8 202 exit(0);
203}
204
205#define RETURN(retval) return (bufptr = s,retval)
206#define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
207#define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
a687059c 208#define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,idtype)
209
210int idtype;
8d063cd8 211
748a9306 212int
f0f333f4 213yylex(void)
8d063cd8 214{
215 register char *s = bufptr;
216 register char *d;
217 register int tmp;
218
219 retry:
9d116dd7 220#if YYDEBUG
b7953727 221 if (yydebug) {
a0d0e21e 222 if (strchr(s,'\n'))
8d063cd8 223 fprintf(stderr,"Tokener at %s",s);
224 else
225 fprintf(stderr,"Tokener at %s\n",s);
b7953727 226 }
8d063cd8 227#endif
228 switch (*s) {
229 default:
230 fprintf(stderr,
231 "Unrecognized character %c in file %s line %d--ignoring.\n",
232 *s++,filename,line);
233 goto retry;
234 case '\\':
bf10efe7 235 s++;
236 if (*s && *s != '\n') {
237 yyerror("Ignoring spurious backslash");
238 goto retry;
239 }
240 /*FALLSTHROUGH*/
8d063cd8 241 case 0:
242 s = str_get(linestr);
243 *s = '\0';
244 if (!rsfp)
245 RETURN(0);
246 line++;
247 if ((s = str_gets(linestr, rsfp)) == Nullch) {
248 if (rsfp != stdin)
249 fclose(rsfp);
250 rsfp = Nullfp;
251 s = str_get(linestr);
252 RETURN(0);
253 }
254 goto retry;
255 case ' ': case '\t':
256 s++;
257 goto retry;
258 case '\n':
259 *s = '\0';
260 XTERM(NEWLINE);
261 case '#':
262 yylval = string(s,0);
263 *s = '\0';
264 XTERM(COMMENT);
265 case ';':
266 tmp = *s++;
267 if (*s == '\n') {
268 s++;
269 XTERM(SEMINEW);
270 }
271 XTERM(tmp);
272 case '(':
a687059c 273 tmp = *s++;
274 XTERM(tmp);
8d063cd8 275 case '{':
276 case '[':
277 case ')':
278 case ']':
a687059c 279 case '?':
280 case ':':
8d063cd8 281 tmp = *s++;
282 XOP(tmp);
9d116dd7 283#ifdef EBCDIC
284 case 7:
285#else
8d063cd8 286 case 127:
9d116dd7 287#endif
8d063cd8 288 s++;
289 XTERM('}');
290 case '}':
3f939f22 291 for (d = s + 1; isSPACE(*d); d++) ;
8d063cd8 292 if (!*d)
293 s = d - 1;
294 *s = 127;
295 XTERM(';');
296 case ',':
297 tmp = *s++;
298 XTERM(tmp);
299 case '~':
300 s++;
378cc40b 301 yylval = string("~",1);
8d063cd8 302 XTERM(MATCHOP);
303 case '+':
304 case '-':
305 if (s[1] == *s) {
306 s++;
307 if (*s++ == '+')
308 XTERM(INCR);
309 else
310 XTERM(DECR);
311 }
312 /* FALL THROUGH */
313 case '*':
314 case '%':
a687059c 315 case '^':
8d063cd8 316 tmp = *s++;
317 if (*s == '=') {
a687059c 318 if (tmp == '^')
319 yylval = string("**=",3);
320 else
321 yylval = string(s-1,2);
8d063cd8 322 s++;
323 XTERM(ASGNOP);
324 }
325 XTERM(tmp);
326 case '&':
327 s++;
328 tmp = *s++;
329 if (tmp == '&')
330 XTERM(ANDAND);
331 s--;
332 XTERM('&');
333 case '|':
334 s++;
335 tmp = *s++;
336 if (tmp == '|')
337 XTERM(OROR);
338 s--;
a687059c 339 while (*s == ' ' || *s == '\t')
340 s++;
341 if (strnEQ(s,"getline",7))
342 XTERM('p');
343 else
344 XTERM('|');
8d063cd8 345 case '=':
346 s++;
347 tmp = *s++;
348 if (tmp == '=') {
349 yylval = string("==",2);
350 XTERM(RELOP);
351 }
352 s--;
353 yylval = string("=",1);
354 XTERM(ASGNOP);
355 case '!':
356 s++;
357 tmp = *s++;
358 if (tmp == '=') {
359 yylval = string("!=",2);
360 XTERM(RELOP);
361 }
362 if (tmp == '~') {
363 yylval = string("!~",2);
364 XTERM(MATCHOP);
365 }
366 s--;
367 XTERM(NOT);
368 case '<':
369 s++;
370 tmp = *s++;
371 if (tmp == '=') {
372 yylval = string("<=",2);
373 XTERM(RELOP);
374 }
375 s--;
a687059c 376 XTERM('<');
8d063cd8 377 case '>':
378 s++;
379 tmp = *s++;
378cc40b 380 if (tmp == '>') {
381 yylval = string(">>",2);
382 XTERM(GRGR);
383 }
8d063cd8 384 if (tmp == '=') {
385 yylval = string(">=",2);
386 XTERM(RELOP);
387 }
388 s--;
a687059c 389 XTERM('>');
8d063cd8 390
391#define SNARFWORD \
392 d = tokenbuf; \
3f939f22 393 while (isALPHA(*s) || isDIGIT(*s) || *s == '_') \
8d063cd8 394 *d++ = *s++; \
395 *d = '\0'; \
a687059c 396 d = tokenbuf; \
397 if (*s == '(') \
398 idtype = USERFUN; \
399 else \
400 idtype = VAR;
8d063cd8 401
402 case '$':
403 s++;
404 if (*s == '0') {
405 s++;
406 do_chop = TRUE;
407 need_entire = TRUE;
a687059c 408 idtype = VAR;
8d063cd8 409 ID("0");
410 }
411 do_split = TRUE;
3f939f22 412 if (isDIGIT(*s)) {
413 for (d = s; isDIGIT(*s); s++) ;
8d063cd8 414 yylval = string(d,s-d);
415 tmp = atoi(d);
416 if (tmp > maxfld)
417 maxfld = tmp;
418 XOP(FIELD);
419 }
420 split_to_array = set_array_base = TRUE;
421 XOP(VFIELD);
422
423 case '/': /* may either be division or pattern */
424 if (expectterm) {
425 s = scanpat(s);
426 XTERM(REGEX);
427 }
428 tmp = *s++;
429 if (*s == '=') {
430 yylval = string("/=",2);
431 s++;
432 XTERM(ASGNOP);
433 }
434 XTERM(tmp);
435
436 case '0': case '1': case '2': case '3': case '4':
a687059c 437 case '5': case '6': case '7': case '8': case '9': case '.':
8d063cd8 438 s = scannum(s);
439 XOP(NUMBER);
440 case '"':
441 s++;
442 s = cpy2(tokenbuf,s,s[-1]);
443 if (!*s)
444 fatal("String not terminated:\n%s",str_get(linestr));
445 s++;
446 yylval = string(tokenbuf,0);
447 XOP(STRING);
448
449 case 'a': case 'A':
450 SNARFWORD;
a687059c 451 if (strEQ(d,"ARGC"))
452 set_array_base = TRUE;
453 if (strEQ(d,"ARGV")) {
454 yylval=numary(string("ARGV",0));
455 XOP(VAR);
456 }
457 if (strEQ(d,"atan2")) {
458 yylval = OATAN2;
459 XTERM(FUNN);
460 }
8d063cd8 461 ID(d);
462 case 'b': case 'B':
463 SNARFWORD;
464 if (strEQ(d,"break"))
465 XTERM(BREAK);
466 if (strEQ(d,"BEGIN"))
467 XTERM(BEGIN);
468 ID(d);
469 case 'c': case 'C':
470 SNARFWORD;
471 if (strEQ(d,"continue"))
472 XTERM(CONTINUE);
a687059c 473 if (strEQ(d,"cos")) {
474 yylval = OCOS;
475 XTERM(FUN1);
476 }
477 if (strEQ(d,"close")) {
478 do_fancy_opens = 1;
479 yylval = OCLOSE;
480 XTERM(FUN1);
481 }
482 if (strEQ(d,"chdir"))
3f939f22 483 *d = toUPPER(*d);
a687059c 484 else if (strEQ(d,"crypt"))
3f939f22 485 *d = toUPPER(*d);
a687059c 486 else if (strEQ(d,"chop"))
3f939f22 487 *d = toUPPER(*d);
a687059c 488 else if (strEQ(d,"chmod"))
3f939f22 489 *d = toUPPER(*d);
a687059c 490 else if (strEQ(d,"chown"))
3f939f22 491 *d = toUPPER(*d);
8d063cd8 492 ID(d);
493 case 'd': case 'D':
494 SNARFWORD;
a687059c 495 if (strEQ(d,"do"))
496 XTERM(DO);
497 if (strEQ(d,"delete"))
498 XTERM(DELETE);
499 if (strEQ(d,"die"))
3f939f22 500 *d = toUPPER(*d);
8d063cd8 501 ID(d);
502 case 'e': case 'E':
503 SNARFWORD;
504 if (strEQ(d,"END"))
505 XTERM(END);
506 if (strEQ(d,"else"))
507 XTERM(ELSE);
508 if (strEQ(d,"exit")) {
509 saw_line_op = TRUE;
510 XTERM(EXIT);
511 }
512 if (strEQ(d,"exp")) {
513 yylval = OEXP;
514 XTERM(FUN1);
515 }
a687059c 516 if (strEQ(d,"elsif"))
3f939f22 517 *d = toUPPER(*d);
a687059c 518 else if (strEQ(d,"eq"))
3f939f22 519 *d = toUPPER(*d);
a687059c 520 else if (strEQ(d,"eval"))
3f939f22 521 *d = toUPPER(*d);
a687059c 522 else if (strEQ(d,"eof"))
3f939f22 523 *d = toUPPER(*d);
a687059c 524 else if (strEQ(d,"each"))
3f939f22 525 *d = toUPPER(*d);
a687059c 526 else if (strEQ(d,"exec"))
3f939f22 527 *d = toUPPER(*d);
8d063cd8 528 ID(d);
529 case 'f': case 'F':
530 SNARFWORD;
531 if (strEQ(d,"FS")) {
532 saw_FS++;
533 if (saw_FS == 1 && in_begin) {
3f939f22 534 for (d = s; *d && isSPACE(*d); d++) ;
8d063cd8 535 if (*d == '=') {
3f939f22 536 for (d++; *d && isSPACE(*d); d++) ;
8d063cd8 537 if (*d == '"' && d[2] == '"')
538 const_FS = d[1];
539 }
540 }
541 ID(tokenbuf);
542 }
8d063cd8 543 if (strEQ(d,"for"))
544 XTERM(FOR);
a687059c 545 else if (strEQ(d,"function"))
546 XTERM(FUNCTION);
547 if (strEQ(d,"FILENAME"))
548 d = "ARGV";
549 if (strEQ(d,"foreach"))
3f939f22 550 *d = toUPPER(*d);
a687059c 551 else if (strEQ(d,"format"))
3f939f22 552 *d = toUPPER(*d);
a687059c 553 else if (strEQ(d,"fork"))
3f939f22 554 *d = toUPPER(*d);
a687059c 555 else if (strEQ(d,"fh"))
3f939f22 556 *d = toUPPER(*d);
8d063cd8 557 ID(d);
558 case 'g': case 'G':
559 SNARFWORD;
560 if (strEQ(d,"getline"))
561 XTERM(GETLINE);
a687059c 562 if (strEQ(d,"gsub"))
563 XTERM(GSUB);
564 if (strEQ(d,"ge"))
3f939f22 565 *d = toUPPER(*d);
a687059c 566 else if (strEQ(d,"gt"))
3f939f22 567 *d = toUPPER(*d);
a687059c 568 else if (strEQ(d,"goto"))
3f939f22 569 *d = toUPPER(*d);
a687059c 570 else if (strEQ(d,"gmtime"))
3f939f22 571 *d = toUPPER(*d);
8d063cd8 572 ID(d);
573 case 'h': case 'H':
574 SNARFWORD;
a687059c 575 if (strEQ(d,"hex"))
3f939f22 576 *d = toUPPER(*d);
8d063cd8 577 ID(d);
578 case 'i': case 'I':
579 SNARFWORD;
580 if (strEQ(d,"if"))
581 XTERM(IF);
582 if (strEQ(d,"in"))
583 XTERM(IN);
584 if (strEQ(d,"index")) {
585 set_array_base = TRUE;
586 XTERM(INDEX);
587 }
588 if (strEQ(d,"int")) {
589 yylval = OINT;
590 XTERM(FUN1);
591 }
592 ID(d);
593 case 'j': case 'J':
594 SNARFWORD;
a687059c 595 if (strEQ(d,"join"))
3f939f22 596 *d = toUPPER(*d);
8d063cd8 597 ID(d);
598 case 'k': case 'K':
599 SNARFWORD;
a687059c 600 if (strEQ(d,"keys"))
3f939f22 601 *d = toUPPER(*d);
a687059c 602 else if (strEQ(d,"kill"))
3f939f22 603 *d = toUPPER(*d);
8d063cd8 604 ID(d);
605 case 'l': case 'L':
606 SNARFWORD;
607 if (strEQ(d,"length")) {
608 yylval = OLENGTH;
609 XTERM(FUN1);
610 }
611 if (strEQ(d,"log")) {
612 yylval = OLOG;
613 XTERM(FUN1);
614 }
a687059c 615 if (strEQ(d,"last"))
3f939f22 616 *d = toUPPER(*d);
a687059c 617 else if (strEQ(d,"local"))
3f939f22 618 *d = toUPPER(*d);
a687059c 619 else if (strEQ(d,"lt"))
3f939f22 620 *d = toUPPER(*d);
a687059c 621 else if (strEQ(d,"le"))
3f939f22 622 *d = toUPPER(*d);
a687059c 623 else if (strEQ(d,"locatime"))
3f939f22 624 *d = toUPPER(*d);
a687059c 625 else if (strEQ(d,"link"))
3f939f22 626 *d = toUPPER(*d);
8d063cd8 627 ID(d);
628 case 'm': case 'M':
629 SNARFWORD;
a687059c 630 if (strEQ(d,"match")) {
631 set_array_base = TRUE;
632 XTERM(MATCH);
633 }
634 if (strEQ(d,"m"))
3f939f22 635 *d = toUPPER(*d);
8d063cd8 636 ID(d);
637 case 'n': case 'N':
638 SNARFWORD;
639 if (strEQ(d,"NF"))
87250799 640 do_chop = do_split = split_to_array = set_array_base = TRUE;
8d063cd8 641 if (strEQ(d,"next")) {
642 saw_line_op = TRUE;
643 XTERM(NEXT);
644 }
a687059c 645 if (strEQ(d,"ne"))
3f939f22 646 *d = toUPPER(*d);
8d063cd8 647 ID(d);
648 case 'o': case 'O':
649 SNARFWORD;
650 if (strEQ(d,"ORS")) {
651 saw_ORS = TRUE;
a687059c 652 d = "\\";
8d063cd8 653 }
654 if (strEQ(d,"OFS")) {
655 saw_OFS = TRUE;
a687059c 656 d = ",";
8d063cd8 657 }
658 if (strEQ(d,"OFMT")) {
a687059c 659 d = "#";
8d063cd8 660 }
a687059c 661 if (strEQ(d,"open"))
3f939f22 662 *d = toUPPER(*d);
a687059c 663 else if (strEQ(d,"ord"))
3f939f22 664 *d = toUPPER(*d);
a687059c 665 else if (strEQ(d,"oct"))
3f939f22 666 *d = toUPPER(*d);
8d063cd8 667 ID(d);
668 case 'p': case 'P':
669 SNARFWORD;
670 if (strEQ(d,"print")) {
671 XTERM(PRINT);
672 }
673 if (strEQ(d,"printf")) {
674 XTERM(PRINTF);
675 }
a687059c 676 if (strEQ(d,"push"))
3f939f22 677 *d = toUPPER(*d);
a687059c 678 else if (strEQ(d,"pop"))
3f939f22 679 *d = toUPPER(*d);
8d063cd8 680 ID(d);
681 case 'q': case 'Q':
682 SNARFWORD;
683 ID(d);
684 case 'r': case 'R':
685 SNARFWORD;
686 if (strEQ(d,"RS")) {
a687059c 687 d = "/";
8d063cd8 688 saw_RS = TRUE;
689 }
a687059c 690 if (strEQ(d,"rand")) {
691 yylval = ORAND;
692 XTERM(FUN1);
693 }
694 if (strEQ(d,"return"))
695 XTERM(RET);
696 if (strEQ(d,"reset"))
3f939f22 697 *d = toUPPER(*d);
a687059c 698 else if (strEQ(d,"redo"))
3f939f22 699 *d = toUPPER(*d);
a687059c 700 else if (strEQ(d,"rename"))
3f939f22 701 *d = toUPPER(*d);
8d063cd8 702 ID(d);
703 case 's': case 'S':
704 SNARFWORD;
705 if (strEQ(d,"split")) {
706 set_array_base = TRUE;
707 XOP(SPLIT);
708 }
709 if (strEQ(d,"substr")) {
710 set_array_base = TRUE;
711 XTERM(SUBSTR);
712 }
a687059c 713 if (strEQ(d,"sub"))
714 XTERM(SUB);
2efaeb47 715 if (strEQ(d,"sprintf")) {
716 /* In old awk, { print sprintf("str%sg"),"in" } prints
717 * "string"; in new awk, "in" is not considered an argument to
718 * sprintf, so the statement breaks. To support both, the
719 * grammar treats arguments to SPRINTF_OLD like old awk,
720 * SPRINTF_NEW like new. Here we return the appropriate one.
721 */
722 XTERM(old_awk ? SPRINTF_OLD : SPRINTF_NEW);
723 }
8d063cd8 724 if (strEQ(d,"sqrt")) {
725 yylval = OSQRT;
726 XTERM(FUN1);
727 }
a687059c 728 if (strEQ(d,"SUBSEP")) {
729 d = ";";
730 }
731 if (strEQ(d,"sin")) {
732 yylval = OSIN;
733 XTERM(FUN1);
734 }
735 if (strEQ(d,"srand")) {
736 yylval = OSRAND;
737 XTERM(FUN1);
738 }
739 if (strEQ(d,"system")) {
740 yylval = OSYSTEM;
741 XTERM(FUN1);
742 }
743 if (strEQ(d,"s"))
3f939f22 744 *d = toUPPER(*d);
a687059c 745 else if (strEQ(d,"shift"))
3f939f22 746 *d = toUPPER(*d);
a687059c 747 else if (strEQ(d,"select"))
3f939f22 748 *d = toUPPER(*d);
a687059c 749 else if (strEQ(d,"seek"))
3f939f22 750 *d = toUPPER(*d);
a687059c 751 else if (strEQ(d,"stat"))
3f939f22 752 *d = toUPPER(*d);
a687059c 753 else if (strEQ(d,"study"))
3f939f22 754 *d = toUPPER(*d);
a687059c 755 else if (strEQ(d,"sleep"))
3f939f22 756 *d = toUPPER(*d);
a687059c 757 else if (strEQ(d,"symlink"))
3f939f22 758 *d = toUPPER(*d);
a687059c 759 else if (strEQ(d,"sort"))
3f939f22 760 *d = toUPPER(*d);
8d063cd8 761 ID(d);
762 case 't': case 'T':
763 SNARFWORD;
a687059c 764 if (strEQ(d,"tr"))
3f939f22 765 *d = toUPPER(*d);
a687059c 766 else if (strEQ(d,"tell"))
3f939f22 767 *d = toUPPER(*d);
a687059c 768 else if (strEQ(d,"time"))
3f939f22 769 *d = toUPPER(*d);
a687059c 770 else if (strEQ(d,"times"))
3f939f22 771 *d = toUPPER(*d);
8d063cd8 772 ID(d);
773 case 'u': case 'U':
774 SNARFWORD;
a687059c 775 if (strEQ(d,"until"))
3f939f22 776 *d = toUPPER(*d);
a687059c 777 else if (strEQ(d,"unless"))
3f939f22 778 *d = toUPPER(*d);
a687059c 779 else if (strEQ(d,"umask"))
3f939f22 780 *d = toUPPER(*d);
a687059c 781 else if (strEQ(d,"unshift"))
3f939f22 782 *d = toUPPER(*d);
a687059c 783 else if (strEQ(d,"unlink"))
3f939f22 784 *d = toUPPER(*d);
a687059c 785 else if (strEQ(d,"utime"))
3f939f22 786 *d = toUPPER(*d);
8d063cd8 787 ID(d);
788 case 'v': case 'V':
789 SNARFWORD;
a687059c 790 if (strEQ(d,"values"))
3f939f22 791 *d = toUPPER(*d);
8d063cd8 792 ID(d);
793 case 'w': case 'W':
794 SNARFWORD;
795 if (strEQ(d,"while"))
796 XTERM(WHILE);
a687059c 797 if (strEQ(d,"write"))
3f939f22 798 *d = toUPPER(*d);
a687059c 799 else if (strEQ(d,"wait"))
3f939f22 800 *d = toUPPER(*d);
8d063cd8 801 ID(d);
802 case 'x': case 'X':
803 SNARFWORD;
a687059c 804 if (strEQ(d,"x"))
3f939f22 805 *d = toUPPER(*d);
8d063cd8 806 ID(d);
807 case 'y': case 'Y':
808 SNARFWORD;
a687059c 809 if (strEQ(d,"y"))
3f939f22 810 *d = toUPPER(*d);
8d063cd8 811 ID(d);
812 case 'z': case 'Z':
813 SNARFWORD;
814 ID(d);
815 }
816}
817
818char *
f0f333f4 819scanpat(register char *s)
8d063cd8 820{
821 register char *d;
822
823 switch (*s++) {
824 case '/':
825 break;
826 default:
827 fatal("Search pattern not found:\n%s",str_get(linestr));
828 }
378cc40b 829
830 d = tokenbuf;
831 for (; *s; s++,d++) {
832 if (*s == '\\') {
833 if (s[1] == '/')
834 *d++ = *s++;
835 else if (s[1] == '\\')
836 *d++ = *s++;
bf10efe7 837 else if (s[1] == '[')
838 *d++ = *s++;
378cc40b 839 }
840 else if (*s == '[') {
841 *d++ = *s++;
842 do {
843 if (*s == '\\' && s[1])
844 *d++ = *s++;
845 if (*s == '/' || (*s == '-' && s[1] == ']'))
846 *d++ = '\\';
847 *d++ = *s++;
848 } while (*s && *s != ']');
849 }
850 else if (*s == '/')
851 break;
852 *d = *s;
853 }
854 *d = '\0';
855
8d063cd8 856 if (!*s)
857 fatal("Search pattern not terminated:\n%s",str_get(linestr));
858 s++;
859 yylval = string(tokenbuf,0);
860 return s;
861}
862
75f92628 863void
f0f333f4 864yyerror(char *s)
8d063cd8 865{
866 fprintf(stderr,"%s in file %s at line %d\n",
867 s,filename,line);
868}
869
870char *
f0f333f4 871scannum(register char *s)
8d063cd8 872{
873 register char *d;
874
875 switch (*s) {
876 case '1': case '2': case '3': case '4': case '5':
877 case '6': case '7': case '8': case '9': case '0' : case '.':
878 d = tokenbuf;
3f939f22 879 while (isDIGIT(*s)) {
8d063cd8 880 *d++ = *s++;
378cc40b 881 }
bf10efe7 882 if (*s == '.') {
3f939f22 883 if (isDIGIT(s[1])) {
378cc40b 884 *d++ = *s++;
3f939f22 885 while (isDIGIT(*s)) {
bf10efe7 886 *d++ = *s++;
887 }
378cc40b 888 }
bf10efe7 889 else
890 s++;
378cc40b 891 }
a0d0e21e 892 if (strchr("eE",*s) && strchr("+-0123456789",s[1])) {
8d063cd8 893 *d++ = *s++;
378cc40b 894 if (*s == '+' || *s == '-')
895 *d++ = *s++;
3f939f22 896 while (isDIGIT(*s))
378cc40b 897 *d++ = *s++;
898 }
8d063cd8 899 *d = '\0';
900 yylval = string(tokenbuf,0);
901 break;
902 }
903 return s;
904}
905
748a9306 906int
f0f333f4 907string(char *ptr, int len)
8d063cd8 908{
909 int retval = mop;
910
911 ops[mop++].ival = OSTRING + (1<<8);
912 if (!len)
913 len = strlen(ptr);
f0f333f4 914 ops[mop].cval = (char *) safemalloc(len+1);
8d063cd8 915 strncpy(ops[mop].cval,ptr,len);
916 ops[mop++].cval[len] = '\0';
a687059c 917 if (mop >= OPSMAX)
918 fatal("Recompile a2p with larger OPSMAX\n");
8d063cd8 919 return retval;
920}
921
748a9306 922int
f0f333f4 923oper0(int type)
8d063cd8 924{
925 int retval = mop;
926
927 if (type > 255)
928 fatal("type > 255 (%d)\n",type);
929 ops[mop++].ival = type;
a687059c 930 if (mop >= OPSMAX)
931 fatal("Recompile a2p with larger OPSMAX\n");
8d063cd8 932 return retval;
933}
934
748a9306 935int
f0f333f4 936oper1(int type, int arg1)
8d063cd8 937{
938 int retval = mop;
939
940 if (type > 255)
941 fatal("type > 255 (%d)\n",type);
942 ops[mop++].ival = type + (1<<8);
943 ops[mop++].ival = arg1;
a687059c 944 if (mop >= OPSMAX)
945 fatal("Recompile a2p with larger OPSMAX\n");
8d063cd8 946 return retval;
947}
948
748a9306 949int
f0f333f4 950oper2(int type, int arg1, int arg2)
8d063cd8 951{
952 int retval = mop;
953
954 if (type > 255)
955 fatal("type > 255 (%d)\n",type);
956 ops[mop++].ival = type + (2<<8);
957 ops[mop++].ival = arg1;
958 ops[mop++].ival = arg2;
a687059c 959 if (mop >= OPSMAX)
960 fatal("Recompile a2p with larger OPSMAX\n");
8d063cd8 961 return retval;
962}
963
748a9306 964int
f0f333f4 965oper3(int type, int arg1, int arg2, int arg3)
8d063cd8 966{
967 int retval = mop;
968
969 if (type > 255)
970 fatal("type > 255 (%d)\n",type);
971 ops[mop++].ival = type + (3<<8);
972 ops[mop++].ival = arg1;
973 ops[mop++].ival = arg2;
974 ops[mop++].ival = arg3;
a687059c 975 if (mop >= OPSMAX)
976 fatal("Recompile a2p with larger OPSMAX\n");
8d063cd8 977 return retval;
978}
979
748a9306 980int
f0f333f4 981oper4(int type, int arg1, int arg2, int arg3, int arg4)
8d063cd8 982{
983 int retval = mop;
984
985 if (type > 255)
986 fatal("type > 255 (%d)\n",type);
987 ops[mop++].ival = type + (4<<8);
988 ops[mop++].ival = arg1;
989 ops[mop++].ival = arg2;
990 ops[mop++].ival = arg3;
991 ops[mop++].ival = arg4;
a687059c 992 if (mop >= OPSMAX)
993 fatal("Recompile a2p with larger OPSMAX\n");
8d063cd8 994 return retval;
995}
996
748a9306 997int
f0f333f4 998oper5(int type, int arg1, int arg2, int arg3, int arg4, int arg5)
8d063cd8 999{
1000 int retval = mop;
1001
1002 if (type > 255)
1003 fatal("type > 255 (%d)\n",type);
1004 ops[mop++].ival = type + (5<<8);
1005 ops[mop++].ival = arg1;
1006 ops[mop++].ival = arg2;
1007 ops[mop++].ival = arg3;
1008 ops[mop++].ival = arg4;
1009 ops[mop++].ival = arg5;
a687059c 1010 if (mop >= OPSMAX)
1011 fatal("Recompile a2p with larger OPSMAX\n");
8d063cd8 1012 return retval;
1013}
1014
1015int depth = 0;
1016
75f92628 1017void
f0f333f4 1018dump(int branch)
8d063cd8 1019{
1020 register int type;
1021 register int len;
1022 register int i;
1023
1024 type = ops[branch].ival;
1025 len = type >> 8;
1026 type &= 255;
1027 for (i=depth; i; i--)
1028 printf(" ");
1029 if (type == OSTRING) {
1030 printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
1031 }
1032 else {
1033 printf("(%-5d%s %d\n",branch,opname[type],len);
1034 depth++;
1035 for (i=1; i<=len; i++)
1036 dump(ops[branch+i].ival);
1037 depth--;
1038 for (i=depth; i; i--)
1039 printf(" ");
1040 printf(")\n");
1041 }
1042}
1043
748a9306 1044int
f0f333f4 1045bl(int arg, int maybe)
8d063cd8 1046{
1047 if (!arg)
1048 return 0;
1049 else if ((ops[arg].ival & 255) != OBLOCK)
1050 return oper2(OBLOCK,arg,maybe);
378cc40b 1051 else if ((ops[arg].ival >> 8) < 2)
8d063cd8 1052 return oper2(OBLOCK,ops[arg+1].ival,maybe);
1053 else
1054 return arg;
1055}
1056
75f92628 1057void
f0f333f4 1058fixup(STR *str)
8d063cd8 1059{
1060 register char *s;
1061 register char *t;
1062
1063 for (s = str->str_ptr; *s; s++) {
1064 if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
1065 strcpy(s+1,s+2);
1066 s++;
1067 }
1068 else if (*s == '\n') {
3f939f22 1069 for (t = s+1; isSPACE(*t & 127); t++) ;
8d063cd8 1070 t--;
3f939f22 1071 while (isSPACE(*t & 127) && *t != '\n') t--;
8d063cd8 1072 if (*t == '\n' && t-s > 1) {
1073 if (s[-1] == '{')
1074 s--;
1075 strcpy(s+1,t);
1076 }
1077 s++;
1078 }
1079 }
1080}
1081
75f92628 1082void
f0f333f4 1083putlines(STR *str)
8d063cd8 1084{
1085 register char *d, *s, *t, *e;
1086 register int pos, newpos;
1087
1088 d = tokenbuf;
1089 pos = 0;
1090 for (s = str->str_ptr; *s; s++) {
1091 *d++ = *s;
1092 pos++;
1093 if (*s == '\n') {
1094 *d = '\0';
1095 d = tokenbuf;
1096 pos = 0;
1097 putone();
1098 }
1099 else if (*s == '\t')
1100 pos += 7;
1101 if (pos > 78) { /* split a long line? */
1102 *d-- = '\0';
1103 newpos = 0;
3f939f22 1104 for (t = tokenbuf; isSPACE(*t & 127); t++) {
8d063cd8 1105 if (*t == '\t')
1106 newpos += 8;
1107 else
1108 newpos += 1;
1109 }
1110 e = d;
1111 while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
1112 d--;
1113 if (d < t+10) {
1114 d = e;
1115 while (d > tokenbuf &&
1116 (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
1117 d--;
1118 }
1119 if (d < t+10) {
1120 d = e;
1121 while (d > tokenbuf &&
1122 (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
1123 d--;
1124 }
1125 if (d < t+10) {
1126 d = e;
1127 while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
1128 d--;
1129 }
1130 if (d < t+10) {
1131 d = e;
1132 while (d > tokenbuf && *d != ' ')
1133 d--;
1134 }
1135 if (d > t+3) {
fe14fcc3 1136 char save[2048];
1137 strcpy(save, d);
1138 *d = '\n';
1139 d[1] = '\0';
8d063cd8 1140 putone();
1141 putchar('\n');
1142 if (d[-1] != ';' && !(newpos % 4)) {
1143 *t++ = ' ';
1144 *t++ = ' ';
1145 newpos += 2;
1146 }
fe14fcc3 1147 strcpy(t,save+1);
8d063cd8 1148 newpos += strlen(t);
1149 d = t + strlen(t);
1150 pos = newpos;
1151 }
1152 else
1153 d = e + 1;
1154 }
1155 }
1156}
1157
75f92628 1158void
f0f333f4 1159putone(void)
8d063cd8 1160{
1161 register char *t;
1162
1163 for (t = tokenbuf; *t; t++) {
1164 *t &= 127;
1165 if (*t == 127) {
1166 *t = ' ';
1167 strcpy(t+strlen(t)-1, "\t#???\n");
378cc40b 1168 checkers++;
8d063cd8 1169 }
1170 }
1171 t = tokenbuf;
1172 if (*t == '#') {
1173 if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
1174 return;
378cc40b 1175 if (strnEQ(t,"#!/usr/bin/awk",14) || strnEQ(t,"#! /usr/bin/awk",15))
1176 return;
8d063cd8 1177 }
1178 fputs(tokenbuf,stdout);
1179}
1180
748a9306 1181int
f0f333f4 1182numary(int arg)
8d063cd8 1183{
1184 STR *key;
1185 int dummy;
1186
a687059c 1187 key = walk(0,0,arg,&dummy,P_MIN);
8d063cd8 1188 str_cat(key,"[]");
1189 hstore(symtab,key->str_ptr,str_make("1"));
1190 str_free(key);
1191 set_array_base = TRUE;
1192 return arg;
1193}
a687059c 1194
748a9306 1195int
f0f333f4 1196rememberargs(int arg)
a687059c 1197{
1198 int type;
1199 STR *str;
1200
1201 if (!arg)
1202 return arg;
1203 type = ops[arg].ival & 255;
1204 if (type == OCOMMA) {
1205 rememberargs(ops[arg+1].ival);
1206 rememberargs(ops[arg+3].ival);
1207 }
1208 else if (type == OVAR) {
1209 str = str_new(0);
1210 hstore(curarghash,ops[ops[arg+1].ival+1].cval,str);
1211 }
1212 else
1213 fatal("panic: unknown argument type %d, line %d\n",type,line);
1214 return arg;
1215}
1216
748a9306 1217int
f0f333f4 1218aryrefarg(int arg)
a687059c 1219{
1220 int type = ops[arg].ival & 255;
1221 STR *str;
1222
1223 if (type != OSTRING)
1224 fatal("panic: aryrefarg %d, line %d\n",type,line);
1225 str = hfetch(curarghash,ops[arg+1].cval);
1226 if (str)
1227 str_set(str,"*");
1228 return arg;
1229}
1230
748a9306 1231int
f0f333f4 1232fixfargs(int name, int arg, int prevargs)
a687059c 1233{
1234 int type;
1235 STR *str;
b7953727 1236 int numargs = 0;
a687059c 1237
1238 if (!arg)
1239 return prevargs;
1240 type = ops[arg].ival & 255;
1241 if (type == OCOMMA) {
1242 numargs = fixfargs(name,ops[arg+1].ival,prevargs);
1243 numargs = fixfargs(name,ops[arg+3].ival,numargs);
1244 }
1245 else if (type == OVAR) {
1246 str = hfetch(curarghash,ops[ops[arg+1].ival+1].cval);
1247 if (strEQ(str_get(str),"*")) {
1248 char tmpbuf[128];
1249
1250 str_set(str,""); /* in case another routine has this */
1251 ops[arg].ival &= ~255;
1252 ops[arg].ival |= OSTAR;
1253 sprintf(tmpbuf,"%s:%d",ops[name+1].cval,prevargs);
1254 fprintf(stderr,"Adding %s\n",tmpbuf);
1255 str = str_new(0);
1256 str_set(str,"*");
1257 hstore(curarghash,tmpbuf,str);
1258 }
1259 numargs = prevargs + 1;
1260 }
1261 else
1262 fatal("panic: unknown argument type %d, arg %d, line %d\n",
39c3038c 1263 type,prevargs+1,line);
a687059c 1264 return numargs;
1265}
1266
748a9306 1267int
f0f333f4 1268fixrargs(char *name, int arg, int prevargs)
a687059c 1269{
1270 int type;
1271 STR *str;
1272 int numargs;
1273
1274 if (!arg)
1275 return prevargs;
1276 type = ops[arg].ival & 255;
1277 if (type == OCOMMA) {
1278 numargs = fixrargs(name,ops[arg+1].ival,prevargs);
1279 numargs = fixrargs(name,ops[arg+3].ival,numargs);
1280 }
1281 else {
f0f333f4 1282 char *tmpbuf = (char *) safemalloc(strlen(name) + (sizeof(prevargs) * 3) + 5);
a687059c 1283 sprintf(tmpbuf,"%s:%d",name,prevargs);
1284 str = hfetch(curarghash,tmpbuf);
ece629c6 1285 safefree(tmpbuf);
a687059c 1286 if (str && strEQ(str->str_ptr,"*")) {
1287 if (type == OVAR || type == OSTAR) {
1288 ops[arg].ival &= ~255;
1289 ops[arg].ival |= OSTAR;
1290 }
1291 else
1292 fatal("Can't pass expression by reference as arg %d of %s\n",
1293 prevargs+1, name);
1294 }
1295 numargs = prevargs + 1;
1296 }
1297 return numargs;
1298}