1 /* $Header: a2py.c,v 3.0 89/10/18 15:34:35 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 89/10/18 15:34:35 lwall
32 linestr = str_new(80);
33 str = str_new(0); /* first used for -I flags */
34 for (argc--,argv++; argc; argc--,argv++) {
35 if (argv[0][0] != '-' || !argv[0][1])
41 debug = atoi(argv[0]+2);
43 yydebug = (debug & 1);
47 case '0': case '1': case '2': case '3': case '4':
48 case '5': case '6': case '7': case '8': case '9':
49 maxfld = atoi(argv[0]+1);
56 namelist = savestr(argv[0]+2);
64 fatal("Unrecognized switch: %s\n",argv[0]);
71 if (argv[0] == Nullch)
73 filename = savestr(argv[0]);
74 if (strEQ(filename,"-"))
79 rsfp = fopen(argv[0],"r");
81 fatal("Awk script \"%s\" doesn't seem to exist.\n",filename);
85 bufptr = str_get(linestr);
89 /* now parse the report spec */
92 fatal("Translation aborted due to syntax errors.\n");
102 printf("%d\t%d\t%d\t%-10s",i++,type,len,opname[type]);
104 printf("\t\"%s\"\n",ops[i].cval),i++;
107 printf("\t%d",ops[i].ival),i++;
117 /* first pass to look for numeric variables */
119 prewalk(0,0,root,&i);
121 /* second pass to produce new program */
123 tmpstr = walk(0,0,root,&i,P_MIN);
124 str = str_make("#!");
126 str_cat(str, "/perl\neval \"exec ");
128 str_cat(str, "/perl -S $0 $*\"\n\
129 if $running_under_some_shell;\n\
130 # this emulates #! processing on NIH machines.\n\
131 # (remove #! line above if indigestible)\n\n");
133 "eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;\n");
135 " # process any FOO=bar switches\n\n");
136 if (do_opens && opens) {
141 str_scat(str,tmpstr);
150 "Please check my work on the %d line%s I've marked with \"#???\".\n",
151 checkers, checkers == 1 ? "" : "s" );
153 "The operation I've selected may be wrong for the operand types.\n");
158 #define RETURN(retval) return (bufptr = s,retval)
159 #define XTERM(retval) return (expectterm = TRUE,bufptr = s,retval)
160 #define XOP(retval) return (expectterm = FALSE,bufptr = s,retval)
161 #define ID(x) return (yylval=string(x,0),expectterm = FALSE,bufptr = s,idtype)
167 register char *s = bufptr;
175 fprintf(stderr,"Tokener at %s",s);
177 fprintf(stderr,"Tokener at %s\n",s);
182 "Unrecognized character %c in file %s line %d--ignoring.\n",
187 s = str_get(linestr);
192 if ((s = str_gets(linestr, rsfp)) == Nullch) {
196 s = str_get(linestr);
207 yylval = string(s,0);
232 for (d = s + 1; isspace(*d); d++) ;
242 yylval = string("~",1);
260 yylval = string("**=",3);
262 yylval = string(s-1,2);
280 while (*s == ' ' || *s == '\t')
282 if (strnEQ(s,"getline",7))
290 yylval = string("==",2);
294 yylval = string("=",1);
300 yylval = string("!=",2);
304 yylval = string("!~",2);
313 yylval = string("<=",2);
322 yylval = string(">>",2);
326 yylval = string(">=",2);
334 while (isalpha(*s) || isdigit(*s) || *s == '_') \
354 for (d = s; isdigit(*s); s++) ;
355 yylval = string(d,s-d);
361 split_to_array = set_array_base = TRUE;
364 case '/': /* may either be division or pattern */
371 yylval = string("/=",2);
377 case '0': case '1': case '2': case '3': case '4':
378 case '5': case '6': case '7': case '8': case '9': case '.':
383 s = cpy2(tokenbuf,s,s[-1]);
385 fatal("String not terminated:\n%s",str_get(linestr));
387 yylval = string(tokenbuf,0);
393 set_array_base = TRUE;
394 if (strEQ(d,"ARGV")) {
395 yylval=numary(string("ARGV",0));
398 if (strEQ(d,"atan2")) {
405 if (strEQ(d,"break"))
407 if (strEQ(d,"BEGIN"))
412 if (strEQ(d,"continue"))
414 if (strEQ(d,"cos")) {
418 if (strEQ(d,"close")) {
423 if (strEQ(d,"chdir"))
425 else if (strEQ(d,"crypt"))
427 else if (strEQ(d,"chop"))
429 else if (strEQ(d,"chmod"))
431 else if (strEQ(d,"chown"))
438 if (strEQ(d,"delete"))
449 if (strEQ(d,"exit")) {
453 if (strEQ(d,"exp")) {
457 if (strEQ(d,"elsif"))
459 else if (strEQ(d,"eq"))
461 else if (strEQ(d,"eval"))
463 else if (strEQ(d,"eof"))
465 else if (strEQ(d,"each"))
467 else if (strEQ(d,"exec"))
474 if (saw_FS == 1 && in_begin) {
475 for (d = s; *d && isspace(*d); d++) ;
477 for (d++; *d && isspace(*d); d++) ;
478 if (*d == '"' && d[2] == '"')
486 else if (strEQ(d,"function"))
488 if (strEQ(d,"FILENAME"))
490 if (strEQ(d,"foreach"))
492 else if (strEQ(d,"format"))
494 else if (strEQ(d,"fork"))
496 else if (strEQ(d,"fh"))
501 if (strEQ(d,"getline"))
507 else if (strEQ(d,"gt"))
509 else if (strEQ(d,"goto"))
511 else if (strEQ(d,"gmtime"))
525 if (strEQ(d,"index")) {
526 set_array_base = TRUE;
529 if (strEQ(d,"int")) {
543 else if (strEQ(d,"kill"))
548 if (strEQ(d,"length")) {
552 if (strEQ(d,"log")) {
558 else if (strEQ(d,"local"))
560 else if (strEQ(d,"lt"))
562 else if (strEQ(d,"le"))
564 else if (strEQ(d,"locatime"))
566 else if (strEQ(d,"link"))
571 if (strEQ(d,"match")) {
572 set_array_base = TRUE;
581 do_split = split_to_array = set_array_base = TRUE;
582 if (strEQ(d,"next")) {
591 if (strEQ(d,"ORS")) {
595 if (strEQ(d,"OFS")) {
599 if (strEQ(d,"OFMT")) {
604 else if (strEQ(d,"ord"))
606 else if (strEQ(d,"oct"))
611 if (strEQ(d,"print")) {
614 if (strEQ(d,"printf")) {
619 else if (strEQ(d,"pop"))
631 if (strEQ(d,"rand")) {
635 if (strEQ(d,"return"))
637 if (strEQ(d,"reset"))
639 else if (strEQ(d,"redo"))
641 else if (strEQ(d,"rename"))
646 if (strEQ(d,"split")) {
647 set_array_base = TRUE;
650 if (strEQ(d,"substr")) {
651 set_array_base = TRUE;
656 if (strEQ(d,"sprintf"))
658 if (strEQ(d,"sqrt")) {
662 if (strEQ(d,"SUBSEP")) {
665 if (strEQ(d,"sin")) {
669 if (strEQ(d,"srand")) {
673 if (strEQ(d,"system")) {
679 else if (strEQ(d,"shift"))
681 else if (strEQ(d,"select"))
683 else if (strEQ(d,"seek"))
685 else if (strEQ(d,"stat"))
687 else if (strEQ(d,"study"))
689 else if (strEQ(d,"sleep"))
691 else if (strEQ(d,"symlink"))
693 else if (strEQ(d,"sort"))
700 else if (strEQ(d,"tell"))
702 else if (strEQ(d,"time"))
704 else if (strEQ(d,"times"))
709 if (strEQ(d,"until"))
711 else if (strEQ(d,"unless"))
713 else if (strEQ(d,"umask"))
715 else if (strEQ(d,"unshift"))
717 else if (strEQ(d,"unlink"))
719 else if (strEQ(d,"utime"))
724 if (strEQ(d,"values"))
729 if (strEQ(d,"while"))
731 if (strEQ(d,"write"))
733 else if (strEQ(d,"wait"))
762 fatal("Search pattern not found:\n%s",str_get(linestr));
766 for (; *s; s++,d++) {
770 else if (s[1] == '\\')
773 else if (*s == '[') {
776 if (*s == '\\' && s[1])
778 if (*s == '/' || (*s == '-' && s[1] == ']'))
781 } while (*s && *s != ']');
790 fatal("Search pattern not terminated:\n%s",str_get(linestr));
792 yylval = string(tokenbuf,0);
799 fprintf(stderr,"%s in file %s at line %d\n",
810 case '1': case '2': case '3': case '4': case '5':
811 case '6': case '7': case '8': case '9': case '0' : case '.':
813 while (isdigit(*s)) {
816 if (*s == '.' && index("0123456789eE",s[1])) {
818 while (isdigit(*s)) {
822 if (index("eE",*s) && index("+-0123456789",s[1])) {
824 if (*s == '+' || *s == '-')
830 yylval = string(tokenbuf,0);
841 ops[mop++].ival = OSTRING + (1<<8);
844 ops[mop].cval = safemalloc(len+1);
845 strncpy(ops[mop].cval,ptr,len);
846 ops[mop++].cval[len] = '\0';
848 fatal("Recompile a2p with larger OPSMAX\n");
858 fatal("type > 255 (%d)\n",type);
859 ops[mop++].ival = type;
861 fatal("Recompile a2p with larger OPSMAX\n");
872 fatal("type > 255 (%d)\n",type);
873 ops[mop++].ival = type + (1<<8);
874 ops[mop++].ival = arg1;
876 fatal("Recompile a2p with larger OPSMAX\n");
880 oper2(type,arg1,arg2)
888 fatal("type > 255 (%d)\n",type);
889 ops[mop++].ival = type + (2<<8);
890 ops[mop++].ival = arg1;
891 ops[mop++].ival = arg2;
893 fatal("Recompile a2p with larger OPSMAX\n");
897 oper3(type,arg1,arg2,arg3)
906 fatal("type > 255 (%d)\n",type);
907 ops[mop++].ival = type + (3<<8);
908 ops[mop++].ival = arg1;
909 ops[mop++].ival = arg2;
910 ops[mop++].ival = arg3;
912 fatal("Recompile a2p with larger OPSMAX\n");
916 oper4(type,arg1,arg2,arg3,arg4)
926 fatal("type > 255 (%d)\n",type);
927 ops[mop++].ival = type + (4<<8);
928 ops[mop++].ival = arg1;
929 ops[mop++].ival = arg2;
930 ops[mop++].ival = arg3;
931 ops[mop++].ival = arg4;
933 fatal("Recompile a2p with larger OPSMAX\n");
937 oper5(type,arg1,arg2,arg3,arg4,arg5)
948 fatal("type > 255 (%d)\n",type);
949 ops[mop++].ival = type + (5<<8);
950 ops[mop++].ival = arg1;
951 ops[mop++].ival = arg2;
952 ops[mop++].ival = arg3;
953 ops[mop++].ival = arg4;
954 ops[mop++].ival = arg5;
956 fatal("Recompile a2p with larger OPSMAX\n");
969 type = ops[branch].ival;
972 for (i=depth; i; i--)
974 if (type == OSTRING) {
975 printf("%-5d\"%s\"\n",branch,ops[branch+1].cval);
978 printf("(%-5d%s %d\n",branch,opname[type],len);
980 for (i=1; i<=len; i++)
981 dump(ops[branch+i].ival);
983 for (i=depth; i; i--)
995 else if ((ops[arg].ival & 255) != OBLOCK)
996 return oper2(OBLOCK,arg,maybe);
997 else if ((ops[arg].ival >> 8) < 2)
998 return oper2(OBLOCK,ops[arg+1].ival,maybe);
1009 for (s = str->str_ptr; *s; s++) {
1010 if (*s == ';' && s[1] == ' ' && s[2] == '\n') {
1014 else if (*s == '\n') {
1015 for (t = s+1; isspace(*t & 127); t++) ;
1017 while (isspace(*t & 127) && *t != '\n') t--;
1018 if (*t == '\n' && t-s > 1) {
1031 register char *d, *s, *t, *e;
1032 register int pos, newpos;
1036 for (s = str->str_ptr; *s; s++) {
1045 else if (*s == '\t')
1047 if (pos > 78) { /* split a long line? */
1050 for (t = tokenbuf; isspace(*t & 127); t++) {
1057 while (d > tokenbuf && (*d != ' ' || d[-1] != ';'))
1061 while (d > tokenbuf &&
1062 (*d != ' ' || d[-1] != '|' || d[-2] != '|') )
1067 while (d > tokenbuf &&
1068 (*d != ' ' || d[-1] != '&' || d[-2] != '&') )
1073 while (d > tokenbuf && (*d != ' ' || d[-1] != ','))
1078 while (d > tokenbuf && *d != ' ')
1085 if (d[-1] != ';' && !(newpos % 4)) {
1091 newpos += strlen(t);
1105 for (t = tokenbuf; *t; t++) {
1109 strcpy(t+strlen(t)-1, "\t#???\n");
1115 if (strnEQ(t,"#!/bin/awk",10) || strnEQ(t,"#! /bin/awk",11))
1117 if (strnEQ(t,"#!/usr/bin/awk",14) || strnEQ(t,"#! /usr/bin/awk",15))
1120 fputs(tokenbuf,stdout);
1129 key = walk(0,0,arg,&dummy,P_MIN);
1131 hstore(symtab,key->str_ptr,str_make("1"));
1133 set_array_base = TRUE;
1145 type = ops[arg].ival & 255;
1146 if (type == OCOMMA) {
1147 rememberargs(ops[arg+1].ival);
1148 rememberargs(ops[arg+3].ival);
1150 else if (type == OVAR) {
1152 hstore(curarghash,ops[ops[arg+1].ival+1].cval,str);
1155 fatal("panic: unknown argument type %d, line %d\n",type,line);
1162 int type = ops[arg].ival & 255;
1165 if (type != OSTRING)
1166 fatal("panic: aryrefarg %d, line %d\n",type,line);
1167 str = hfetch(curarghash,ops[arg+1].cval);
1173 fixfargs(name,arg,prevargs)
1184 type = ops[arg].ival & 255;
1185 if (type == OCOMMA) {
1186 numargs = fixfargs(name,ops[arg+1].ival,prevargs);
1187 numargs = fixfargs(name,ops[arg+3].ival,numargs);
1189 else if (type == OVAR) {
1190 str = hfetch(curarghash,ops[ops[arg+1].ival+1].cval);
1191 if (strEQ(str_get(str),"*")) {
1194 str_set(str,""); /* in case another routine has this */
1195 ops[arg].ival &= ~255;
1196 ops[arg].ival |= OSTAR;
1197 sprintf(tmpbuf,"%s:%d",ops[name+1].cval,prevargs);
1198 fprintf(stderr,"Adding %s\n",tmpbuf);
1201 hstore(curarghash,tmpbuf,str);
1203 numargs = prevargs + 1;
1206 fatal("panic: unknown argument type %d, arg %d, line %d\n",
1207 type,numargs+1,line);
1211 fixrargs(name,arg,prevargs)
1222 type = ops[arg].ival & 255;
1223 if (type == OCOMMA) {
1224 numargs = fixrargs(name,ops[arg+1].ival,prevargs);
1225 numargs = fixrargs(name,ops[arg+3].ival,numargs);
1230 sprintf(tmpbuf,"%s:%d",name,prevargs);
1231 str = hfetch(curarghash,tmpbuf);
1232 fprintf(stderr,"Looking for %s\n",tmpbuf);
1233 if (str && strEQ(str->str_ptr,"*")) {
1234 if (type == OVAR || type == OSTAR) {
1235 ops[arg].ival &= ~255;
1236 ops[arg].ival |= OSTAR;
1239 fatal("Can't pass expression by reference as arg %d of %s\n",
1242 numargs = prevargs + 1;