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