1 /* $Header: a2py.c,v 3.0.1.1 90/08/09 05:48:53 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.1 90/08/09 05:48:53 lwall
10 * patch19: a2p didn't emit a chop when NF was referenced though split needs it
12 * Revision 3.0 89/10/18 15:34:35 lwall
35 linestr = str_new(80);
36 str = str_new(0); /* first used for -I flags */
37 for (argc--,argv++; argc; argc--,argv++) {
38 if (argv[0][0] != '-' || !argv[0][1])
44 debug = atoi(argv[0]+2);
46 yydebug = (debug & 1);
50 case '0': case '1': case '2': case '3': case '4':
51 case '5': case '6': case '7': case '8': case '9':
52 maxfld = atoi(argv[0]+1);
59 namelist = savestr(argv[0]+2);
67 fatal("Unrecognized switch: %s\n",argv[0]);
74 if (argv[0] == Nullch)
76 filename = savestr(argv[0]);
77 if (strEQ(filename,"-"))
82 rsfp = fopen(argv[0],"r");
84 fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
88 bufptr = str_get(linestr);
92 /* now parse the report spec */
95 fatal("Translation aborted due to syntax errors.\n");
105 printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
107 printf("\t\"%s\"\n",ops[i].cval),i++;
110 printf("\t%d",ops[i].ival),i++;
120 /* first pass to look for numeric variables */
122 prewalk(0,0,root,&i);
124 /* second pass to produce new program */
126 tmpstr = walk(0,0,root,&i,P_MIN);
127 str = str_make("#!");
129 str_cat(str, "/perl\neval \"exec ");
131 str_cat(str, "/perl -S $0 $*\"\n\
132 if $running_under_some_shell;\n\
133 # this emulates #! processing on NIH machines.\n\
134 # (remove #! line above if indigestible)\n\n");
136 "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;\n");
138 " # process any FOO=bar switches\n\n");
139 if (do_opens && opens) {
144 str_scat(str,tmpstr);
153 "Please check my work on the %d line%s I've marked with \"#???\".\n",
154 checkers, checkers == 1 ? "" : "s" );
156 "The operation I've selected may be wrong for the operand types.\n");
161 #define RETURN(retval) return (bufptr = s,retval)
162 #define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
163 #define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
164 #define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,idtype)
170 register char *s = bufptr;
178 fprintf(stderr,"Tokener at %s",s);
180 fprintf(stderr,"Tokener at %s\n",s);
185 "Unrecognized character %c in file %s line %d--ignoring.\n",
190 s = str_get(linestr);
195 if ((s = str_gets(linestr, rsfp)) == Nullch) {
199 s = str_get(linestr);
210 yylval = string(s,0);
235 for (d = s + 1; isspace(*d); d++) ;
245 yylval = string("~",1);
263 yylval = string("**=",3);
265 yylval = string(s-1,2);
283 while (*s == ' ' || *s == '\t')
285 if (strnEQ(s,"getline",7))
293 yylval = string("==",2);
297 yylval = string("=",1);
303 yylval = string("!=",2);
307 yylval = string("!~",2);
316 yylval = string("<=",2);
325 yylval = string(">>",2);
329 yylval = string(">=",2);
337 while (isalpha(*s) || isdigit(*s) || *s == '_') \
357 for (d = s; isdigit(*s); s++) ;
358 yylval = string(d,s-d);
364 split_to_array = set_array_base = TRUE;
367 case '/': /* may either be division or pattern */
374 yylval = string("/=",2);
380 case '0': case '1': case '2': case '3': case '4':
381 case '5': case '6': case '7': case '8': case '9': case '.':
386 s = cpy2(tokenbuf,s,s[-1]);
388 fatal("String not terminated:\n%s",str_get(linestr));
390 yylval = string(tokenbuf,0);
396 set_array_base = TRUE;
397 if (strEQ(d,"ARGV")) {
398 yylval=numary(string("ARGV",0));
401 if (strEQ(d,"atan2")) {
408 if (strEQ(d,"break"))
410 if (strEQ(d,"BEGIN"))
415 if (strEQ(d,"continue"))
417 if (strEQ(d,"cos")) {
421 if (strEQ(d,"close")) {
426 if (strEQ(d,"chdir"))
428 else if (strEQ(d,"crypt"))
430 else if (strEQ(d,"chop"))
432 else if (strEQ(d,"chmod"))
434 else if (strEQ(d,"chown"))
441 if (strEQ(d,"delete"))
452 if (strEQ(d,"exit")) {
456 if (strEQ(d,"exp")) {
460 if (strEQ(d,"elsif"))
462 else if (strEQ(d,"eq"))
464 else if (strEQ(d,"eval"))
466 else if (strEQ(d,"eof"))
468 else if (strEQ(d,"each"))
470 else if (strEQ(d,"exec"))
477 if (saw_FS == 1 && in_begin) {
478 for (d = s; *d && isspace(*d); d++) ;
480 for (d++; *d && isspace(*d); d++) ;
481 if (*d == '"' && d[2] == '"')
489 else if (strEQ(d,"function"))
491 if (strEQ(d,"FILENAME"))
493 if (strEQ(d,"foreach"))
495 else if (strEQ(d,"format"))
497 else if (strEQ(d,"fork"))
499 else if (strEQ(d,"fh"))
504 if (strEQ(d,"getline"))
510 else if (strEQ(d,"gt"))
512 else if (strEQ(d,"goto"))
514 else if (strEQ(d,"gmtime"))
528 if (strEQ(d,"index")) {
529 set_array_base = TRUE;
532 if (strEQ(d,"int")) {
546 else if (strEQ(d,"kill"))
551 if (strEQ(d,"length")) {
555 if (strEQ(d,"log")) {
561 else if (strEQ(d,"local"))
563 else if (strEQ(d,"lt"))
565 else if (strEQ(d,"le"))
567 else if (strEQ(d,"locatime"))
569 else if (strEQ(d,"link"))
574 if (strEQ(d,"match")) {
575 set_array_base = TRUE;
584 do_chop = do_split = split_to_array = set_array_base = TRUE;
585 if (strEQ(d,"next")) {
594 if (strEQ(d,"ORS")) {
598 if (strEQ(d,"OFS")) {
602 if (strEQ(d,"OFMT")) {
607 else if (strEQ(d,"ord"))
609 else if (strEQ(d,"oct"))
614 if (strEQ(d,"print")) {
617 if (strEQ(d,"printf")) {
622 else if (strEQ(d,"pop"))
634 if (strEQ(d,"rand")) {
638 if (strEQ(d,"return"))
640 if (strEQ(d,"reset"))
642 else if (strEQ(d,"redo"))
644 else if (strEQ(d,"rename"))
649 if (strEQ(d,"split")) {
650 set_array_base = TRUE;
653 if (strEQ(d,"substr")) {
654 set_array_base = TRUE;
659 if (strEQ(d,"sprintf"))
661 if (strEQ(d,"sqrt")) {
665 if (strEQ(d,"SUBSEP")) {
668 if (strEQ(d,"sin")) {
672 if (strEQ(d,"srand")) {
676 if (strEQ(d,"system")) {
682 else if (strEQ(d,"shift"))
684 else if (strEQ(d,"select"))
686 else if (strEQ(d,"seek"))
688 else if (strEQ(d,"stat"))
690 else if (strEQ(d,"study"))
692 else if (strEQ(d,"sleep"))
694 else if (strEQ(d,"symlink"))
696 else if (strEQ(d,"sort"))
703 else if (strEQ(d,"tell"))
705 else if (strEQ(d,"time"))
707 else if (strEQ(d,"times"))
712 if (strEQ(d,"until"))
714 else if (strEQ(d,"unless"))
716 else if (strEQ(d,"umask"))
718 else if (strEQ(d,"unshift"))
720 else if (strEQ(d,"unlink"))
722 else if (strEQ(d,"utime"))
727 if (strEQ(d,"values"))
732 if (strEQ(d,"while"))
734 if (strEQ(d,"write"))
736 else if (strEQ(d,"wait"))
765 fatal("Search pattern not found:\n%s",str_get(linestr));
769 for (; *s; s++,d++) {
773 else if (s[1] == '\\')
776 else if (*s == '[') {
779 if (*s == '\\' && s[1])
781 if (*s == '/' || (*s == '-' && s[1] == ']'))
784 } while (*s && *s != ']');
793 fatal("Search pattern not terminated:\n%s",str_get(linestr));
795 yylval = string(tokenbuf,0);
802 fprintf(stderr,"%s in file %s at line %d\n",
813 case '1': case '2': case '3': case '4': case '5':
814 case '6': case '7': case '8': case '9': case '0' : case '.':
816 while (isdigit(*s)) {
819 if (*s == '.' && index("0123456789eE",s[1])) {
821 while (isdigit(*s)) {
825 if (index("eE",*s) && index("+-0123456789",s[1])) {
827 if (*s == '+' || *s == '-')
833 yylval = string(tokenbuf,0);
844 ops[mop++].ival = OSTRING + (1<<8);
847 ops[mop].cval = safemalloc(len+1);
848 strncpy(ops[mop].cval,ptr,len);
849 ops[mop++].cval[len] = '\0';
851 fatal("Recompile a2p with larger OPSMAX\n");
861 fatal("type > 255 (%d)\n",type);
862 ops[mop++].ival = type;
864 fatal("Recompile a2p with larger OPSMAX\n");
875 fatal("type > 255 (%d)\n",type);
876 ops[mop++].ival = type + (1<<8);
877 ops[mop++].ival = arg1;
879 fatal("Recompile a2p with larger OPSMAX\n");
883 oper2(type,arg1,arg2)
891 fatal("type > 255 (%d)\n",type);
892 ops[mop++].ival = type + (2<<8);
893 ops[mop++].ival = arg1;
894 ops[mop++].ival = arg2;
896 fatal("Recompile a2p with larger OPSMAX\n");
900 oper3(type,arg1,arg2,arg3)
909 fatal("type > 255 (%d)\n",type);
910 ops[mop++].ival = type + (3<<8);
911 ops[mop++].ival = arg1;
912 ops[mop++].ival = arg2;
913 ops[mop++].ival = arg3;
915 fatal("Recompile a2p with larger OPSMAX\n");
919 oper4(type,arg1,arg2,arg3,arg4)
929 fatal("type > 255 (%d)\n",type);
930 ops[mop++].ival = type + (4<<8);
931 ops[mop++].ival = arg1;
932 ops[mop++].ival = arg2;
933 ops[mop++].ival = arg3;
934 ops[mop++].ival = arg4;
936 fatal("Recompile a2p with larger OPSMAX\n");
940 oper5(type,arg1,arg2,arg3,arg4,arg5)
951 fatal("type > 255 (%d)\n",type);
952 ops[mop++].ival = type + (5<<8);
953 ops[mop++].ival = arg1;
954 ops[mop++].ival = arg2;
955 ops[mop++].ival = arg3;
956 ops[mop++].ival = arg4;
957 ops[mop++].ival = arg5;
959 fatal("Recompile a2p with larger OPSMAX\n");
972 type = ops[branch].ival;
975 for (i=depth; i; i--)
977 if (type == OSTRING) {
978 printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
981 printf("(%-5d%s %d\n",branch,opname[type],len);
983 for (i=1; i<=len; i++)
984 dump(ops[branch+i].ival);
986 for (i=depth; i; i--)
998 else if ((ops[arg].ival & 255) != OBLOCK)
999 return oper2(OBLOCK,arg,maybe);
1000 else if ((ops[arg].ival >> 8) < 2)
1001 return oper2(OBLOCK,ops[arg+1].ival,maybe);
1012 for (s = str->str_ptr; *s; s++) {
1013 if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
1017 else if (*s == '\n') {
1018 for (t = s+1; isspace(*t & 127); t++) ;
1020 while (isspace(*t & 127) && *t != '\n') t--;
1021 if (*t == '\n' && t-s > 1) {
1034 register char *d, *s, *t, *e;
1035 register int pos, newpos;
1039 for (s = str->str_ptr; *s; s++) {
1048 else if (*s == '\t')
1050 if (pos > 78) { /* split a long line? */
1053 for (t = tokenbuf; isspace(*t & 127); t++) {
1060 while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
1064 while (d > tokenbuf &&
1065 (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
1070 while (d > tokenbuf &&
1071 (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
1076 while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
1081 while (d > tokenbuf && *d != ' ')
1088 if (d[-1] != ';' && !(newpos % 4)) {
1094 newpos += strlen(t);
1108 for (t = tokenbuf; *t; t++) {
1112 strcpy(t+strlen(t)-1, "\t#???\n");
1118 if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
1120 if (strnEQ(t,"#!/usr/bin/awk",14) || strnEQ(t,"#! /usr/bin/awk",15))
1123 fputs(tokenbuf,stdout);
1132 key = walk(0,0,arg,&dummy,P_MIN);
1134 hstore(symtab,key->str_ptr,str_make("1"));
1136 set_array_base = TRUE;
1148 type = ops[arg].ival & 255;
1149 if (type == OCOMMA) {
1150 rememberargs(ops[arg+1].ival);
1151 rememberargs(ops[arg+3].ival);
1153 else if (type == OVAR) {
1155 hstore(curarghash,ops[ops[arg+1].ival+1].cval,str);
1158 fatal("panic: unknown argument type %d, line %d\n",type,line);
1165 int type = ops[arg].ival & 255;
1168 if (type != OSTRING)
1169 fatal("panic: aryrefarg %d, line %d\n",type,line);
1170 str = hfetch(curarghash,ops[arg+1].cval);
1176 fixfargs(name,arg,prevargs)
1187 type = ops[arg].ival & 255;
1188 if (type == OCOMMA) {
1189 numargs = fixfargs(name,ops[arg+1].ival,prevargs);
1190 numargs = fixfargs(name,ops[arg+3].ival,numargs);
1192 else if (type == OVAR) {
1193 str = hfetch(curarghash,ops[ops[arg+1].ival+1].cval);
1194 if (strEQ(str_get(str),"*")) {
1197 str_set(str,""); /* in case another routine has this */
1198 ops[arg].ival &= ~255;
1199 ops[arg].ival |= OSTAR;
1200 sprintf(tmpbuf,"%s:%d",ops[name+1].cval,prevargs);
1201 fprintf(stderr,"Adding %s\n",tmpbuf);
1204 hstore(curarghash,tmpbuf,str);
1206 numargs = prevargs + 1;
1209 fatal("panic: unknown argument type %d, arg %d, line %d\n",
1210 type,numargs+1,line);
1214 fixrargs(name,arg,prevargs)
1225 type = ops[arg].ival & 255;
1226 if (type == OCOMMA) {
1227 numargs = fixrargs(name,ops[arg+1].ival,prevargs);
1228 numargs = fixrargs(name,ops[arg+3].ival,numargs);
1233 sprintf(tmpbuf,"%s:%d",name,prevargs);
1234 str = hfetch(curarghash,tmpbuf);
1235 fprintf(stderr,"Looking for %s\n",tmpbuf);
1236 if (str && strEQ(str->str_ptr,"*")) {
1237 if (type == OVAR || type == OSTAR) {
1238 ops[arg].ival &= ~255;
1239 ops[arg].ival |= OSTAR;
1242 fatal("Can't pass expression by reference as arg %d of %s\n",
1245 numargs = prevargs + 1;