1 /* $RCSfile: a2py.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 12:12:59 $
3 * Copyright (c) 1991, Larry Wall
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.
9 * Revision 4.0.1.1 91/06/07 12:12:59 lwall
10 * patch4: new copyright notice
12 * Revision 4.0 91/03/20 01:57:26 lwall
18 #include "../patchlev.h"
32 printf("\nThis is the AWK to PERL translator, version 3.0, patchlevel %d\n", PATCHLEVEL);
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"
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"
55 linestr = str_new(80);
56 str = str_new(0); /* first used for -I flags */
57 for (argc--,argv++; argc; argc--,argv++) {
58 if (argv[0][0] != '-' || !argv[0][1])
64 debug = atoi(argv[0]+2);
66 yydebug = (debug & 1);
70 case '0': case '1': case '2': case '3': case '4':
71 case '5': case '6': case '7': case '8': case '9':
72 maxfld = atoi(argv[0]+1);
79 namelist = savestr(argv[0]+2);
87 fatal("Unrecognized switch: %s\n",argv[0]);
97 if (argv[0] == Nullch) {
99 if ( isatty(fileno(stdin)) )
104 filename = savestr(argv[0]);
106 filename = savestr(argv[0]);
107 if (strEQ(filename,"-"))
112 rsfp = fopen(argv[0],"r");
114 fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
118 bufptr = str_get(linestr);
122 /* now parse the report spec */
125 fatal("Translation aborted due to syntax errors.\n");
135 printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
137 printf("\t\"%s\"\n",ops[i].cval),i++;
140 printf("\t%d",ops[i].ival),i++;
150 /* first pass to look for numeric variables */
152 prewalk(0,0,root,&i);
154 /* second pass to produce new program */
156 tmpstr = walk(0,0,root,&i,P_MIN);
157 str = str_make("#!");
159 str_cat(str, "/perl\neval \"exec ");
161 str_cat(str, "/perl -S $0 $*\"\n\
162 if $running_under_some_shell;\n\
163 # this emulates #! processing on NIH machines.\n\
164 # (remove #! line above if indigestible)\n\n");
166 "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;\n");
168 " # process any FOO=bar switches\n\n");
169 if (do_opens && opens) {
174 str_scat(str,tmpstr);
183 "Please check my work on the %d line%s I've marked with \"#???\".\n",
184 checkers, checkers == 1 ? "" : "s" );
186 "The operation I've selected may be wrong for the operand types.\n");
191 #define RETURN(retval) return (bufptr = s,retval)
192 #define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
193 #define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
194 #define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,idtype)
200 register char *s = bufptr;
208 fprintf(stderr,"Tokener at %s",s);
210 fprintf(stderr,"Tokener at %s\n",s);
215 "Unrecognized character %c in file %s line %d--ignoring.\n",
220 s = str_get(linestr);
225 if ((s = str_gets(linestr, rsfp)) == Nullch) {
229 s = str_get(linestr);
240 yylval = string(s,0);
265 for (d = s + 1; isspace(*d); d++) ;
275 yylval = string("~",1);
293 yylval = string("**=",3);
295 yylval = string(s-1,2);
313 while (*s == ' ' || *s == '\t')
315 if (strnEQ(s,"getline",7))
323 yylval = string("==",2);
327 yylval = string("=",1);
333 yylval = string("!=",2);
337 yylval = string("!~",2);
346 yylval = string("<=",2);
355 yylval = string(">>",2);
359 yylval = string(">=",2);
367 while (isalpha(*s) || isdigit(*s) || *s == '_') \
387 for (d = s; isdigit(*s); s++) ;
388 yylval = string(d,s-d);
394 split_to_array = set_array_base = TRUE;
397 case '/': /* may either be division or pattern */
404 yylval = string("/=",2);
410 case '0': case '1': case '2': case '3': case '4':
411 case '5': case '6': case '7': case '8': case '9': case '.':
416 s = cpy2(tokenbuf,s,s[-1]);
418 fatal("String not terminated:\n%s",str_get(linestr));
420 yylval = string(tokenbuf,0);
426 set_array_base = TRUE;
427 if (strEQ(d,"ARGV")) {
428 yylval=numary(string("ARGV",0));
431 if (strEQ(d,"atan2")) {
438 if (strEQ(d,"break"))
440 if (strEQ(d,"BEGIN"))
445 if (strEQ(d,"continue"))
447 if (strEQ(d,"cos")) {
451 if (strEQ(d,"close")) {
456 if (strEQ(d,"chdir"))
458 else if (strEQ(d,"crypt"))
460 else if (strEQ(d,"chop"))
462 else if (strEQ(d,"chmod"))
464 else if (strEQ(d,"chown"))
471 if (strEQ(d,"delete"))
482 if (strEQ(d,"exit")) {
486 if (strEQ(d,"exp")) {
490 if (strEQ(d,"elsif"))
492 else if (strEQ(d,"eq"))
494 else if (strEQ(d,"eval"))
496 else if (strEQ(d,"eof"))
498 else if (strEQ(d,"each"))
500 else if (strEQ(d,"exec"))
507 if (saw_FS == 1 && in_begin) {
508 for (d = s; *d && isspace(*d); d++) ;
510 for (d++; *d && isspace(*d); d++) ;
511 if (*d == '"' && d[2] == '"')
519 else if (strEQ(d,"function"))
521 if (strEQ(d,"FILENAME"))
523 if (strEQ(d,"foreach"))
525 else if (strEQ(d,"format"))
527 else if (strEQ(d,"fork"))
529 else if (strEQ(d,"fh"))
534 if (strEQ(d,"getline"))
540 else if (strEQ(d,"gt"))
542 else if (strEQ(d,"goto"))
544 else if (strEQ(d,"gmtime"))
558 if (strEQ(d,"index")) {
559 set_array_base = TRUE;
562 if (strEQ(d,"int")) {
576 else if (strEQ(d,"kill"))
581 if (strEQ(d,"length")) {
585 if (strEQ(d,"log")) {
591 else if (strEQ(d,"local"))
593 else if (strEQ(d,"lt"))
595 else if (strEQ(d,"le"))
597 else if (strEQ(d,"locatime"))
599 else if (strEQ(d,"link"))
604 if (strEQ(d,"match")) {
605 set_array_base = TRUE;
614 do_chop = do_split = split_to_array = set_array_base = TRUE;
615 if (strEQ(d,"next")) {
624 if (strEQ(d,"ORS")) {
628 if (strEQ(d,"OFS")) {
632 if (strEQ(d,"OFMT")) {
637 else if (strEQ(d,"ord"))
639 else if (strEQ(d,"oct"))
644 if (strEQ(d,"print")) {
647 if (strEQ(d,"printf")) {
652 else if (strEQ(d,"pop"))
664 if (strEQ(d,"rand")) {
668 if (strEQ(d,"return"))
670 if (strEQ(d,"reset"))
672 else if (strEQ(d,"redo"))
674 else if (strEQ(d,"rename"))
679 if (strEQ(d,"split")) {
680 set_array_base = TRUE;
683 if (strEQ(d,"substr")) {
684 set_array_base = TRUE;
689 if (strEQ(d,"sprintf"))
691 if (strEQ(d,"sqrt")) {
695 if (strEQ(d,"SUBSEP")) {
698 if (strEQ(d,"sin")) {
702 if (strEQ(d,"srand")) {
706 if (strEQ(d,"system")) {
712 else if (strEQ(d,"shift"))
714 else if (strEQ(d,"select"))
716 else if (strEQ(d,"seek"))
718 else if (strEQ(d,"stat"))
720 else if (strEQ(d,"study"))
722 else if (strEQ(d,"sleep"))
724 else if (strEQ(d,"symlink"))
726 else if (strEQ(d,"sort"))
733 else if (strEQ(d,"tell"))
735 else if (strEQ(d,"time"))
737 else if (strEQ(d,"times"))
742 if (strEQ(d,"until"))
744 else if (strEQ(d,"unless"))
746 else if (strEQ(d,"umask"))
748 else if (strEQ(d,"unshift"))
750 else if (strEQ(d,"unlink"))
752 else if (strEQ(d,"utime"))
757 if (strEQ(d,"values"))
762 if (strEQ(d,"while"))
764 if (strEQ(d,"write"))
766 else if (strEQ(d,"wait"))
795 fatal("Search pattern not found:\n%s",str_get(linestr));
799 for (; *s; s++,d++) {
803 else if (s[1] == '\\')
806 else if (*s == '[') {
809 if (*s == '\\' && s[1])
811 if (*s == '/' || (*s == '-' && s[1] == ']'))
814 } while (*s && *s != ']');
823 fatal("Search pattern not terminated:\n%s",str_get(linestr));
825 yylval = string(tokenbuf,0);
832 fprintf(stderr,"%s in file %s at line %d\n",
843 case '1': case '2': case '3': case '4': case '5':
844 case '6': case '7': case '8': case '9': case '0' : case '.':
846 while (isdigit(*s)) {
849 if (*s == '.' && index("0123456789eE",s[1])) {
851 while (isdigit(*s)) {
855 if (index("eE",*s) && index("+-0123456789",s[1])) {
857 if (*s == '+' || *s == '-')
863 yylval = string(tokenbuf,0);
874 ops[mop++].ival = OSTRING + (1<<8);
877 ops[mop].cval = safemalloc(len+1);
878 strncpy(ops[mop].cval,ptr,len);
879 ops[mop++].cval[len] = '\0';
881 fatal("Recompile a2p with larger OPSMAX\n");
891 fatal("type > 255 (%d)\n",type);
892 ops[mop++].ival = type;
894 fatal("Recompile a2p with larger OPSMAX\n");
905 fatal("type > 255 (%d)\n",type);
906 ops[mop++].ival = type + (1<<8);
907 ops[mop++].ival = arg1;
909 fatal("Recompile a2p with larger OPSMAX\n");
913 oper2(type,arg1,arg2)
921 fatal("type > 255 (%d)\n",type);
922 ops[mop++].ival = type + (2<<8);
923 ops[mop++].ival = arg1;
924 ops[mop++].ival = arg2;
926 fatal("Recompile a2p with larger OPSMAX\n");
930 oper3(type,arg1,arg2,arg3)
939 fatal("type > 255 (%d)\n",type);
940 ops[mop++].ival = type + (3<<8);
941 ops[mop++].ival = arg1;
942 ops[mop++].ival = arg2;
943 ops[mop++].ival = arg3;
945 fatal("Recompile a2p with larger OPSMAX\n");
949 oper4(type,arg1,arg2,arg3,arg4)
959 fatal("type > 255 (%d)\n",type);
960 ops[mop++].ival = type + (4<<8);
961 ops[mop++].ival = arg1;
962 ops[mop++].ival = arg2;
963 ops[mop++].ival = arg3;
964 ops[mop++].ival = arg4;
966 fatal("Recompile a2p with larger OPSMAX\n");
970 oper5(type,arg1,arg2,arg3,arg4,arg5)
981 fatal("type > 255 (%d)\n",type);
982 ops[mop++].ival = type + (5<<8);
983 ops[mop++].ival = arg1;
984 ops[mop++].ival = arg2;
985 ops[mop++].ival = arg3;
986 ops[mop++].ival = arg4;
987 ops[mop++].ival = arg5;
989 fatal("Recompile a2p with larger OPSMAX\n");
1002 type = ops[branch].ival;
1005 for (i=depth; i; i--)
1007 if (type == OSTRING) {
1008 printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
1011 printf("(%-5d%s %d\n",branch,opname[type],len);
1013 for (i=1; i<=len; i++)
1014 dump(ops[branch+i].ival);
1016 for (i=depth; i; i--)
1028 else if ((ops[arg].ival & 255) != OBLOCK)
1029 return oper2(OBLOCK,arg,maybe);
1030 else if ((ops[arg].ival >> 8) < 2)
1031 return oper2(OBLOCK,ops[arg+1].ival,maybe);
1042 for (s = str->str_ptr; *s; s++) {
1043 if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
1047 else if (*s == '\n') {
1048 for (t = s+1; isspace(*t & 127); t++) ;
1050 while (isspace(*t & 127) && *t != '\n') t--;
1051 if (*t == '\n' && t-s > 1) {
1064 register char *d, *s, *t, *e;
1065 register int pos, newpos;
1069 for (s = str->str_ptr; *s; s++) {
1078 else if (*s == '\t')
1080 if (pos > 78) { /* split a long line? */
1083 for (t = tokenbuf; isspace(*t & 127); t++) {
1090 while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
1094 while (d > tokenbuf &&
1095 (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
1100 while (d > tokenbuf &&
1101 (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
1106 while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
1111 while (d > tokenbuf && *d != ' ')
1121 if (d[-1] != ';' && !(newpos % 4)) {
1127 newpos += strlen(t);
1141 for (t = tokenbuf; *t; t++) {
1145 strcpy(t+strlen(t)-1, "\t#???\n");
1151 if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
1153 if (strnEQ(t,"#!/usr/bin/awk",14) || strnEQ(t,"#! /usr/bin/awk",15))
1156 fputs(tokenbuf,stdout);
1165 key = walk(0,0,arg,&dummy,P_MIN);
1167 hstore(symtab,key->str_ptr,str_make("1"));
1169 set_array_base = TRUE;
1181 type = ops[arg].ival & 255;
1182 if (type == OCOMMA) {
1183 rememberargs(ops[arg+1].ival);
1184 rememberargs(ops[arg+3].ival);
1186 else if (type == OVAR) {
1188 hstore(curarghash,ops[ops[arg+1].ival+1].cval,str);
1191 fatal("panic: unknown argument type %d, line %d\n",type,line);
1198 int type = ops[arg].ival & 255;
1201 if (type != OSTRING)
1202 fatal("panic: aryrefarg %d, line %d\n",type,line);
1203 str = hfetch(curarghash,ops[arg+1].cval);
1209 fixfargs(name,arg,prevargs)
1220 type = ops[arg].ival & 255;
1221 if (type == OCOMMA) {
1222 numargs = fixfargs(name,ops[arg+1].ival,prevargs);
1223 numargs = fixfargs(name,ops[arg+3].ival,numargs);
1225 else if (type == OVAR) {
1226 str = hfetch(curarghash,ops[ops[arg+1].ival+1].cval);
1227 if (strEQ(str_get(str),"*")) {
1230 str_set(str,""); /* in case another routine has this */
1231 ops[arg].ival &= ~255;
1232 ops[arg].ival |= OSTAR;
1233 sprintf(tmpbuf,"%s:%d",ops[name+1].cval,prevargs);
1234 fprintf(stderr,"Adding %s\n",tmpbuf);
1237 hstore(curarghash,tmpbuf,str);
1239 numargs = prevargs + 1;
1242 fatal("panic: unknown argument type %d, arg %d, line %d\n",
1243 type,prevargs+1,line);
1247 fixrargs(name,arg,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);
1266 sprintf(tmpbuf,"%s:%d",name,prevargs);
1267 str = hfetch(curarghash,tmpbuf);
1268 fprintf(stderr,"Looking for %s\n",tmpbuf);
1269 if (str && strEQ(str->str_ptr,"*")) {
1270 if (type == OVAR || type == OSTAR) {
1271 ops[arg].ival &= ~255;
1272 ops[arg].ival |= OSTAR;
1275 fatal("Can't pass expression by reference as arg %d of %s\n",
1278 numargs = prevargs + 1;