1 /* $Header: a2py.c,v 3.0.1.2 90/10/16 11:30:34 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.2 90/10/16 11:30:34 lwall
10 * patch29: various portability fixes
12 * Revision 3.0.1.1 90/08/09 05:48:53 lwall
13 * patch19: a2p didn't emit a chop when NF was referenced though split needs it
15 * Revision 3.0 89/10/18 15:34:35 lwall
21 #include "../patchlev.h"
35 printf("\nThis is the AWK to PERL translator, version 3.0, patchlevel %d\n", PATCHLEVEL);
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"
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"
58 linestr = str_new(80);
59 str = str_new(0); /* first used for -I flags */
60 for (argc--,argv++; argc; argc--,argv++) {
61 if (argv[0][0] != '-' || !argv[0][1])
67 debug = atoi(argv[0]+2);
69 yydebug = (debug & 1);
73 case '0': case '1': case '2': case '3': case '4':
74 case '5': case '6': case '7': case '8': case '9':
75 maxfld = atoi(argv[0]+1);
82 namelist = savestr(argv[0]+2);
90 fatal("Unrecognized switch: %s\n",argv[0]);
100 if (argv[0] == Nullch) {
102 if ( isatty(fileno(stdin)) )
107 filename = savestr(argv[0]);
109 filename = savestr(argv[0]);
110 if (strEQ(filename,"-"))
115 rsfp = fopen(argv[0],"r");
117 fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
121 bufptr = str_get(linestr);
125 /* now parse the report spec */
128 fatal("Translation aborted due to syntax errors.\n");
138 printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
140 printf("\t\"%s\"\n",ops[i].cval),i++;
143 printf("\t%d",ops[i].ival),i++;
153 /* first pass to look for numeric variables */
155 prewalk(0,0,root,&i);
157 /* second pass to produce new program */
159 tmpstr = walk(0,0,root,&i,P_MIN);
160 str = str_make("#!");
162 str_cat(str, "/perl\neval \"exec ");
164 str_cat(str, "/perl -S $0 $*\"\n\
165 if $running_under_some_shell;\n\
166 # this emulates #! processing on NIH machines.\n\
167 # (remove #! line above if indigestible)\n\n");
169 "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;\n");
171 " # process any FOO=bar switches\n\n");
172 if (do_opens && opens) {
177 str_scat(str,tmpstr);
186 "Please check my work on the %d line%s I've marked with \"#???\".\n",
187 checkers, checkers == 1 ? "" : "s" );
189 "The operation I've selected may be wrong for the operand types.\n");
194 #define RETURN(retval) return (bufptr = s,retval)
195 #define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
196 #define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
197 #define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,idtype)
203 register char *s = bufptr;
211 fprintf(stderr,"Tokener at %s",s);
213 fprintf(stderr,"Tokener at %s\n",s);
218 "Unrecognized character %c in file %s line %d--ignoring.\n",
223 s = str_get(linestr);
228 if ((s = str_gets(linestr, rsfp)) == Nullch) {
232 s = str_get(linestr);
243 yylval = string(s,0);
268 for (d = s + 1; isspace(*d); d++) ;
278 yylval = string("~",1);
296 yylval = string("**=",3);
298 yylval = string(s-1,2);
316 while (*s == ' ' || *s == '\t')
318 if (strnEQ(s,"getline",7))
326 yylval = string("==",2);
330 yylval = string("=",1);
336 yylval = string("!=",2);
340 yylval = string("!~",2);
349 yylval = string("<=",2);
358 yylval = string(">>",2);
362 yylval = string(">=",2);
370 while (isalpha(*s) || isdigit(*s) || *s == '_') \
390 for (d = s; isdigit(*s); s++) ;
391 yylval = string(d,s-d);
397 split_to_array = set_array_base = TRUE;
400 case '/': /* may either be division or pattern */
407 yylval = string("/=",2);
413 case '0': case '1': case '2': case '3': case '4':
414 case '5': case '6': case '7': case '8': case '9': case '.':
419 s = cpy2(tokenbuf,s,s[-1]);
421 fatal("String not terminated:\n%s",str_get(linestr));
423 yylval = string(tokenbuf,0);
429 set_array_base = TRUE;
430 if (strEQ(d,"ARGV")) {
431 yylval=numary(string("ARGV",0));
434 if (strEQ(d,"atan2")) {
441 if (strEQ(d,"break"))
443 if (strEQ(d,"BEGIN"))
448 if (strEQ(d,"continue"))
450 if (strEQ(d,"cos")) {
454 if (strEQ(d,"close")) {
459 if (strEQ(d,"chdir"))
461 else if (strEQ(d,"crypt"))
463 else if (strEQ(d,"chop"))
465 else if (strEQ(d,"chmod"))
467 else if (strEQ(d,"chown"))
474 if (strEQ(d,"delete"))
485 if (strEQ(d,"exit")) {
489 if (strEQ(d,"exp")) {
493 if (strEQ(d,"elsif"))
495 else if (strEQ(d,"eq"))
497 else if (strEQ(d,"eval"))
499 else if (strEQ(d,"eof"))
501 else if (strEQ(d,"each"))
503 else if (strEQ(d,"exec"))
510 if (saw_FS == 1 && in_begin) {
511 for (d = s; *d && isspace(*d); d++) ;
513 for (d++; *d && isspace(*d); d++) ;
514 if (*d == '"' && d[2] == '"')
522 else if (strEQ(d,"function"))
524 if (strEQ(d,"FILENAME"))
526 if (strEQ(d,"foreach"))
528 else if (strEQ(d,"format"))
530 else if (strEQ(d,"fork"))
532 else if (strEQ(d,"fh"))
537 if (strEQ(d,"getline"))
543 else if (strEQ(d,"gt"))
545 else if (strEQ(d,"goto"))
547 else if (strEQ(d,"gmtime"))
561 if (strEQ(d,"index")) {
562 set_array_base = TRUE;
565 if (strEQ(d,"int")) {
579 else if (strEQ(d,"kill"))
584 if (strEQ(d,"length")) {
588 if (strEQ(d,"log")) {
594 else if (strEQ(d,"local"))
596 else if (strEQ(d,"lt"))
598 else if (strEQ(d,"le"))
600 else if (strEQ(d,"locatime"))
602 else if (strEQ(d,"link"))
607 if (strEQ(d,"match")) {
608 set_array_base = TRUE;
617 do_chop = do_split = split_to_array = set_array_base = TRUE;
618 if (strEQ(d,"next")) {
627 if (strEQ(d,"ORS")) {
631 if (strEQ(d,"OFS")) {
635 if (strEQ(d,"OFMT")) {
640 else if (strEQ(d,"ord"))
642 else if (strEQ(d,"oct"))
647 if (strEQ(d,"print")) {
650 if (strEQ(d,"printf")) {
655 else if (strEQ(d,"pop"))
667 if (strEQ(d,"rand")) {
671 if (strEQ(d,"return"))
673 if (strEQ(d,"reset"))
675 else if (strEQ(d,"redo"))
677 else if (strEQ(d,"rename"))
682 if (strEQ(d,"split")) {
683 set_array_base = TRUE;
686 if (strEQ(d,"substr")) {
687 set_array_base = TRUE;
692 if (strEQ(d,"sprintf"))
694 if (strEQ(d,"sqrt")) {
698 if (strEQ(d,"SUBSEP")) {
701 if (strEQ(d,"sin")) {
705 if (strEQ(d,"srand")) {
709 if (strEQ(d,"system")) {
715 else if (strEQ(d,"shift"))
717 else if (strEQ(d,"select"))
719 else if (strEQ(d,"seek"))
721 else if (strEQ(d,"stat"))
723 else if (strEQ(d,"study"))
725 else if (strEQ(d,"sleep"))
727 else if (strEQ(d,"symlink"))
729 else if (strEQ(d,"sort"))
736 else if (strEQ(d,"tell"))
738 else if (strEQ(d,"time"))
740 else if (strEQ(d,"times"))
745 if (strEQ(d,"until"))
747 else if (strEQ(d,"unless"))
749 else if (strEQ(d,"umask"))
751 else if (strEQ(d,"unshift"))
753 else if (strEQ(d,"unlink"))
755 else if (strEQ(d,"utime"))
760 if (strEQ(d,"values"))
765 if (strEQ(d,"while"))
767 if (strEQ(d,"write"))
769 else if (strEQ(d,"wait"))
798 fatal("Search pattern not found:\n%s",str_get(linestr));
802 for (; *s; s++,d++) {
806 else if (s[1] == '\\')
809 else if (*s == '[') {
812 if (*s == '\\' && s[1])
814 if (*s == '/' || (*s == '-' && s[1] == ']'))
817 } while (*s && *s != ']');
826 fatal("Search pattern not terminated:\n%s",str_get(linestr));
828 yylval = string(tokenbuf,0);
835 fprintf(stderr,"%s in file %s at line %d\n",
846 case '1': case '2': case '3': case '4': case '5':
847 case '6': case '7': case '8': case '9': case '0' : case '.':
849 while (isdigit(*s)) {
852 if (*s == '.' && index("0123456789eE",s[1])) {
854 while (isdigit(*s)) {
858 if (index("eE",*s) && index("+-0123456789",s[1])) {
860 if (*s == '+' || *s == '-')
866 yylval = string(tokenbuf,0);
877 ops[mop++].ival = OSTRING + (1<<8);
880 ops[mop].cval = safemalloc(len+1);
881 strncpy(ops[mop].cval,ptr,len);
882 ops[mop++].cval[len] = '\0';
884 fatal("Recompile a2p with larger OPSMAX\n");
894 fatal("type > 255 (%d)\n",type);
895 ops[mop++].ival = type;
897 fatal("Recompile a2p with larger OPSMAX\n");
908 fatal("type > 255 (%d)\n",type);
909 ops[mop++].ival = type + (1<<8);
910 ops[mop++].ival = arg1;
912 fatal("Recompile a2p with larger OPSMAX\n");
916 oper2(type,arg1,arg2)
924 fatal("type > 255 (%d)\n",type);
925 ops[mop++].ival = type + (2<<8);
926 ops[mop++].ival = arg1;
927 ops[mop++].ival = arg2;
929 fatal("Recompile a2p with larger OPSMAX\n");
933 oper3(type,arg1,arg2,arg3)
942 fatal("type > 255 (%d)\n",type);
943 ops[mop++].ival = type + (3<<8);
944 ops[mop++].ival = arg1;
945 ops[mop++].ival = arg2;
946 ops[mop++].ival = arg3;
948 fatal("Recompile a2p with larger OPSMAX\n");
952 oper4(type,arg1,arg2,arg3,arg4)
962 fatal("type > 255 (%d)\n",type);
963 ops[mop++].ival = type + (4<<8);
964 ops[mop++].ival = arg1;
965 ops[mop++].ival = arg2;
966 ops[mop++].ival = arg3;
967 ops[mop++].ival = arg4;
969 fatal("Recompile a2p with larger OPSMAX\n");
973 oper5(type,arg1,arg2,arg3,arg4,arg5)
984 fatal("type > 255 (%d)\n",type);
985 ops[mop++].ival = type + (5<<8);
986 ops[mop++].ival = arg1;
987 ops[mop++].ival = arg2;
988 ops[mop++].ival = arg3;
989 ops[mop++].ival = arg4;
990 ops[mop++].ival = arg5;
992 fatal("Recompile a2p with larger OPSMAX\n");
1005 type = ops[branch].ival;
1008 for (i=depth; i; i--)
1010 if (type == OSTRING) {
1011 printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
1014 printf("(%-5d%s %d\n",branch,opname[type],len);
1016 for (i=1; i<=len; i++)
1017 dump(ops[branch+i].ival);
1019 for (i=depth; i; i--)
1031 else if ((ops[arg].ival & 255) != OBLOCK)
1032 return oper2(OBLOCK,arg,maybe);
1033 else if ((ops[arg].ival >> 8) < 2)
1034 return oper2(OBLOCK,ops[arg+1].ival,maybe);
1045 for (s = str->str_ptr; *s; s++) {
1046 if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
1050 else if (*s == '\n') {
1051 for (t = s+1; isspace(*t & 127); t++) ;
1053 while (isspace(*t & 127) && *t != '\n') t--;
1054 if (*t == '\n' && t-s > 1) {
1067 register char *d, *s, *t, *e;
1068 register int pos, newpos;
1072 for (s = str->str_ptr; *s; s++) {
1081 else if (*s == '\t')
1083 if (pos > 78) { /* split a long line? */
1086 for (t = tokenbuf; isspace(*t & 127); t++) {
1093 while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
1097 while (d > tokenbuf &&
1098 (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
1103 while (d > tokenbuf &&
1104 (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
1109 while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
1114 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;