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