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