/* Copyright (c) 1982 Regents of the University of California */ static char sccsid[] = "@(#)fortran.c 1.4 08/16/83"; /* * FORTRAN dependent symbol routines. */ #include "defs.h" #include "symbols.h" #include "printsym.h" #include "languages.h" #include "fortran.h" #include "tree.h" #include "eval.h" #include "operators.h" #include "mappings.h" #include "process.h" #include "runtime.h" #include "machine.h" #define isfloat(range) ( \ range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \ ) #define isrange(t, name) (t->class == RANGE and istypename(t->type, name)) #define MAXDIM 20 /* * Initialize FORTRAN language information. */ public fortran_init() { Language lang; lang = language_define("fortran", ".f"); language_setop(lang, L_PRINTDECL, fortran_printdecl); language_setop(lang, L_PRINTVAL, fortran_printval); language_setop(lang, L_TYPEMATCH, fortran_typematch); language_setop(lang, L_BUILDAREF, fortran_buildaref); language_setop(lang, L_EVALAREF, fortran_evalaref); } /* * Test if two types are compatible. * * Integers and reals are not compatible since they cannot always be mixed. */ public Boolean fortran_typematch(type1, type2) Symbol type1, type2; { /* only does integer for now; may need to add others */ Boolean b; register Symbol t1, t2, tmp; t1 = rtype(type1); t2 = rtype(type2); if(t1 == nil or t1->type == nil or t2 == nil or t2->type == nil ) b = false; else { b = (Boolean) ( (t1 == t2) or (t1->type == t_int and (istypename(t2->type, "integer") or istypename(t2->type, "integer*2")) ) or (t2->type == t_int and (istypename(t1->type, "integer") or istypename(t1->type, "integer*2")) ) ); } /*OUT fprintf(stderr," %d compat %s %s \n", b, (t1 == nil or t1->type == nil ) ? "nil" : symname(t1->type), (t2 == nil or t2->type == nil ) ? "nil" : symname(t2->type) );*/ return b; } private String typename(s) Symbol s; { int ub; static char buf[20]; char *pbuf; Symbol st,sc; if(s->type->class == TYPE) return(symname(s->type)); for(st = s->type; st->type->class != TYPE; st = st->type); pbuf=buf; if(istypename(st->type,"char")) { sprintf(pbuf,"character*"); pbuf += strlen(pbuf); sc = st->chain; if(sc->symvalue.rangev.uppertype == R_ARG or sc->symvalue.rangev.uppertype == R_TEMP) { if( ! getbound(s,sc->symvalue.rangev.upper, sc->symvalue.rangev.uppertype, &ub) ) sprintf(pbuf,"(*)"); else sprintf(pbuf,"%d",ub); } else sprintf(pbuf,"%d",sc->symvalue.rangev.upper); } else { sprintf(pbuf,"%s ",symname(st->type)); } return(buf); } private Symbol mksubs(pbuf,st) Symbol st; char **pbuf; { int lb, ub; Symbol r, eltype; if(st->class != ARRAY or (istypename(st->type, "char")) ) return; else { mksubs(pbuf,st->type); assert( (r = st->chain)->class == RANGE); if(r->symvalue.rangev.lowertype == R_ARG or r->symvalue.rangev.lowertype == R_TEMP) { if( ! getbound(st,r->symvalue.rangev.lower, r->symvalue.rangev.lowertype, &lb) ) sprintf(*pbuf,"?:"); else sprintf(*pbuf,"%d:",lb); } else { lb = r->symvalue.rangev.lower; sprintf(*pbuf,"%d:",lb); } *pbuf += strlen(*pbuf); if(r->symvalue.rangev.uppertype == R_ARG or r->symvalue.rangev.uppertype == R_TEMP) { if( ! getbound(st,r->symvalue.rangev.upper, r->symvalue.rangev.uppertype, &ub) ) sprintf(*pbuf,"?,"); else sprintf(*pbuf,"%d,",ub); } else { ub = r->symvalue.rangev.upper; sprintf(*pbuf,"%d,",ub); } *pbuf += strlen(*pbuf); } } /* * Print out the declaration of a FORTRAN variable. */ public fortran_printdecl(s) Symbol s; { Symbol eltype; switch (s->class) { case CONST: printf("parameter %s = ", symname(s)); printval(s); break; case REF: printf(" (dummy argument) "); /* fall through */ case VAR: if (s->type->class == ARRAY and (not istypename(s->type->type, "char")) ) { char bounds[130], *p1, **p; p1 = bounds; p = &p1; mksubs(p, s->type); *p -= 1; **p = '\0'; /* get rid of trailing ',' */ printf(" %s %s[%s] ", typename(s), symname(s), bounds); } else { printf("%s %s", typename(s), symname(s)); } break; case FUNC: if (not istypename(s->type, "void")) { printf(" %s function ", typename(s) ); } else { printf(" subroutine"); } printf(" %s ", symname(s)); fortran_listparams(s); break; case MODULE: printf("source file \"%s.f\"", symname(s)); break; case PROG: printf("executable file \"%s\"", symname(s)); break; default: error("class %s in fortran_printdecl", classname(s)); } putchar('\n'); } /* * List the parameters of a procedure or function. * No attempt is made to combine like types. */ public fortran_listparams(s) Symbol s; { register Symbol t; putchar('('); for (t = s->chain; t != nil; t = t->chain) { printf("%s", symname(t)); if (t->chain != nil) { printf(", "); } } putchar(')'); if (s->chain != nil) { printf("\n"); for (t = s->chain; t != nil; t = t->chain) { if (t->class != REF) { panic("unexpected class %d for parameter", t->class); } printdecl(t, 0); } } else { putchar('\n'); } } /* * Print out the value on the top of the expression stack * in the format for the type of the given symbol. */ public fortran_printval(s) Symbol s; { register Symbol t; register Address a; register int i, len; /* printf("fortran_printval with class %s \n",classname(s)); OUT*/ switch (s->class) { case CONST: case TYPE: case VAR: case REF: case FVAR: case TAG: fortran_printval(s->type); break; case ARRAY: t = rtype(s->type); if (t->class == RANGE and istypename(t->type, "char")) { len = size(s); sp -= len; printf("\"%.*s\"", len, sp); } else { fortran_printarray(s); } break; case RANGE: if (isfloat(s)) { switch (s->symvalue.rangev.lower) { case sizeof(float): prtreal(pop(float)); break; case sizeof(double): if(istypename(s->type,"complex")) { printf("("); prtreal(pop(float)); printf(","); prtreal(pop(float)); printf(")"); } else prtreal(pop(double)); break; default: panic("bad size \"%d\" for real", t->symvalue.rangev.lower); break; } } else { printint(popsmall(s), s); } break; default: if (ord(s->class) > ord(TYPEREF)) { panic("printval: bad class %d", ord(s->class)); } error("don't know how to print a %s", fortran_classname(s)); /* NOTREACHED */ } } /* * Print out an int */ private printint(i, t) Integer i; register Symbol t; { if (istypename(t->type, "logical")) { printf(((Boolean) i) == true ? "true" : "false"); } else if ( (t->type == t_int) or istypename(t->type, "integer") or istypename(t->type,"integer*2") ) { printf("%ld", i); } else { error("unkown type in fortran printint"); } } /* * Print out a null-terminated string (pointer to char) * starting at the given address. */ private printstring(addr) Address addr; { register Address a; register Integer i, len; register Boolean endofstring; union { char ch[sizeof(Word)]; int word; } u; putchar('"'); a = addr; endofstring = false; while (not endofstring) { dread(&u, a, sizeof(u)); i = 0; do { if (u.ch[i] == '\0') { endofstring = true; } else { printchar(u.ch[i]); } ++i; } while (i < sizeof(Word) and not endofstring); a += sizeof(Word); } putchar('"'); } /* * Return the FORTRAN name for the particular class of a symbol. */ public String fortran_classname(s) Symbol s; { String str; switch (s->class) { case REF: str = "dummy argument"; break; case CONST: str = "parameter"; break; default: str = classname(s); } return str; } /* reverses the indices from the expr_list; should be folded into buildaref * and done as one recursive routine */ Node private rev_index(here,n) register Node here,n; { register Node i; if( here == nil or here == n) i=nil; else if( here->value.arg[1] == n) i = here; else i=rev_index(here->value.arg[1],n); return i; } public Node fortran_buildaref(a, slist) Node a, slist; { register Symbol as; /* array of array of .. cursor */ register Node en; /* Expr list cursor */ Symbol etype; /* Type of subscript expr */ Node esub, tree; /* Subscript expression ptr and tree to be built*/ tree=a; as = rtype(tree->nodetype); /* node->sym.type->array*/ if ( not ( (tree->nodetype->class == VAR or tree->nodetype->class == REF) and as->class == ARRAY ) ) { beginerrmsg(); prtree(stderr, a); fprintf(stderr, " is not an array"); /*fprintf(stderr, " a-> %x as %x ", tree->nodetype, as ); OUT*/ enderrmsg(); } else { for (en = rev_index(slist,nil); en != nil and as->class == ARRAY; en = rev_index(slist,en), as = as->type) { esub = en->value.arg[0]; etype = rtype(esub->nodetype); assert(as->chain->class == RANGE); if ( not compatible( t_int, etype) ) { beginerrmsg(); fprintf(stderr, "subscript "); prtree(stderr, esub); fprintf(stderr, " is type %s ",symname(etype->type) ); enderrmsg(); } tree = build(O_INDEX, tree, esub); tree->nodetype = as->type; } if (en != nil or (as->class == ARRAY && (not istypename(as->type,"char"))) ) { beginerrmsg(); if (en != nil) { fprintf(stderr, "too many subscripts for "); } else { fprintf(stderr, "not enough subscripts for "); } prtree(stderr, tree); enderrmsg(); } } return tree; } /* * Evaluate a subscript index. */ public int fortran_evalaref(s, i) Symbol s; long i; { Symbol r; long lb, ub; r = rtype(s)->chain; if(r->symvalue.rangev.lowertype == R_ARG or r->symvalue.rangev.lowertype == R_TEMP ) { if(! getbound(s,r->symvalue.rangev.lower, r->symvalue.rangev.lowertype,&lb)) error("dynamic bounds not currently available"); } else lb = r->symvalue.rangev.lower; if(r->symvalue.rangev.uppertype == R_ARG or r->symvalue.rangev.uppertype == R_TEMP ) { if(! getbound(s,r->symvalue.rangev.upper, r->symvalue.rangev.uppertype,&ub)) error("dynamic bounds not currently available"); } else ub = r->symvalue.rangev.upper; if (i < lb or i > ub) { error("subscript out of range"); } return (i - lb); } private fortran_printarray(a) Symbol a; { struct Bounds { int lb, val, ub} dim[MAXDIM]; Symbol sc,st,eltype; char buf[50]; char *subscr; int i,ndim,elsize; Stack *savesp; Boolean done; st = a; savesp = sp; sp -= size(a); ndim=0; for(;;){ sc = st->chain; if(sc->symvalue.rangev.lowertype == R_ARG or sc->symvalue.rangev.lowertype == R_TEMP) { if( ! getbound(a,sc->symvalue.rangev.lower, sc->symvalue.rangev.lowertype, &dim[ndim].lb) ) error(" dynamic bounds not currently available"); } else dim[ndim].lb = sc->symvalue.rangev.lower; if(sc->symvalue.rangev.uppertype == R_ARG or sc->symvalue.rangev.uppertype == R_TEMP) { if( ! getbound(a,sc->symvalue.rangev.upper, sc->symvalue.rangev.uppertype, &dim[ndim].ub) ) error(" dynamic bounds not currently available"); } else dim[ndim].ub = sc->symvalue.rangev.upper; ndim ++; if (st->type->class == ARRAY) st=st->type; else break; } if(istypename(st->type,"char")) { eltype = st; ndim--; } else eltype=st->type; elsize=size(eltype); sp += elsize; /*printf("ndim %d elsize %lx in fortran_printarray\n",ndim,elsize);OUT*/ ndim--; for (i=0;i<=ndim;i++){ dim[i].val=dim[i].lb; /*OUT printf(" %d %d %d \n",i,dim[i].lb,dim[i].ub); fflush(stdout); OUT*/ } for(;;) { buf[0]=','; subscr = buf+1; for (i=ndim-1;i>=0;i--) { sprintf(subscr,"%d,",dim[i].val); subscr += strlen(subscr); } *--subscr = '\0'; for(i=dim[ndim].lb;i<=dim[ndim].ub;i++) { printf("[%d%s]\t",i,buf); printval(eltype); printf("\n"); sp += 2*elsize; } dim[ndim].val=dim[ndim].ub; i=ndim-1; if (i<0) break; done=false; do { dim[i].val++; if(dim[i].val > dim[i].ub) { dim[i].val = dim[i].lb; if(--i<0) done=true; } else done=true; } while (not done); if (i<0) break; } }