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