xref: /original-bsd/old/dbx/fortran.c (revision 4d1ce0b0)
1 /*
2  * Copyright (c) 1983 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)fortran.c	5.7 (Berkeley) 06/01/90";
10 #endif /* not lint */
11 
12 /*
13  * FORTRAN dependent symbol routines.
14  */
15 
16 #include "defs.h"
17 #include "symbols.h"
18 #include "printsym.h"
19 #include "languages.h"
20 #include "fortran.h"
21 #include "tree.h"
22 #include "eval.h"
23 #include "operators.h"
24 #include "mappings.h"
25 #include "process.h"
26 #include "runtime.h"
27 #include "machine.h"
28 
29 #define isspecial(range) ( \
30     range->symvalue.rangev.upper == 0 and range->symvalue.rangev.lower > 0 \
31 )
32 
33 #define isrange(t, name) (t->class == RANGE and istypename(t->type, name))
34 
35 #define MAXDIM  20
36 
37 private Language fort;
38 
39 /*
40  * Initialize FORTRAN language information.
41  */
42 
43 public fortran_init()
44 {
45     fort = language_define("fortran", ".f");
46     language_setop(fort, L_PRINTDECL, fortran_printdecl);
47     language_setop(fort, L_PRINTVAL, fortran_printval);
48     language_setop(fort, L_TYPEMATCH, fortran_typematch);
49     language_setop(fort, L_BUILDAREF, fortran_buildaref);
50     language_setop(fort, L_EVALAREF, fortran_evalaref);
51     language_setop(fort, L_MODINIT, fortran_modinit);
52     language_setop(fort, L_HASMODULES, fortran_hasmodules);
53     language_setop(fort, L_PASSADDR, fortran_passaddr);
54 }
55 
56 /*
57  * Test if two types are compatible.
58  *
59  * Integers and reals are not compatible since they cannot always be mixed.
60  */
61 
62 public Boolean fortran_typematch(type1, type2)
63 Symbol type1, type2;
64 {
65 
66 /* only does integer for now; may need to add others
67 */
68 
69     Boolean b;
70     register Symbol t1, t2, tmp;
71 
72     t1 = rtype(type1);
73     t2 = rtype(type2);
74     if(t1 == nil or t1->type == nil or t2 == nil or t2->type == nil ) b = false;
75     else { b = (Boolean)   (
76             (t1 == t2)  or
77 	    (t1->type == t_int and (istypename(t2->type, "integer") or
78                                     istypename(t2->type, "integer*2"))  ) or
79 	    (t2->type == t_int and (istypename(t1->type, "integer") or
80                                     istypename(t1->type, "integer*2"))  )
81                     );
82          }
83     /*OUT fprintf(stderr," %d compat %s %s \n", b,
84       (t1 == nil or t1->type == nil ) ? "nil" : symname(t1->type),
85       (t2 == nil or t2->type == nil ) ? "nil" : symname(t2->type)  );*/
86     return b;
87 }
88 
89 private String typename(s)
90 Symbol s;
91 {
92 int ub;
93 static char buf[20];
94 char *pbuf;
95 Symbol st,sc;
96 
97      if(s->type->class == TYPE) return(symname(s->type));
98 
99      for(st = s->type; st->type->class != TYPE; st = st->type);
100 
101      pbuf=buf;
102 
103      if(istypename(st->type,"char"))  {
104 	  sprintf(pbuf,"character*");
105           pbuf += strlen(pbuf);
106 	  sc = st->chain;
107           if(sc->symvalue.rangev.uppertype == R_ARG or
108              sc->symvalue.rangev.uppertype == R_TEMP) {
109 	      if( ! getbound(s,sc->symvalue.rangev.upper,
110                     sc->symvalue.rangev.uppertype, &ub) )
111 		sprintf(pbuf,"(*)");
112 	      else
113 		sprintf(pbuf,"%d",ub);
114           }
115  	  else sprintf(pbuf,"%d",sc->symvalue.rangev.upper);
116      }
117      else {
118           sprintf(pbuf,"%s ",symname(st->type));
119      }
120      return(buf);
121 }
122 
123 private Symbol mksubs(pbuf,st)
124 Symbol st;
125 char  **pbuf;
126 {
127    int lb, ub;
128    Symbol r, eltype;
129 
130    if(st->class != ARRAY or (istypename(st->type, "char")) ) return;
131    else {
132           mksubs(pbuf,st->type);
133           assert( (r = st->chain)->class == RANGE);
134 
135           if(r->symvalue.rangev.lowertype == R_ARG or
136              r->symvalue.rangev.lowertype == R_TEMP) {
137 	      if( ! getbound(st,r->symvalue.rangev.lower,
138                     r->symvalue.rangev.lowertype, &lb) )
139 		sprintf(*pbuf,"?:");
140 	      else
141 		sprintf(*pbuf,"%d:",lb);
142 	  }
143           else {
144 		lb = r->symvalue.rangev.lower;
145 		sprintf(*pbuf,"%d:",lb);
146 		}
147     	  *pbuf += strlen(*pbuf);
148 
149           if(r->symvalue.rangev.uppertype == R_ARG or
150              r->symvalue.rangev.uppertype == R_TEMP) {
151 	      if( ! getbound(st,r->symvalue.rangev.upper,
152                     r->symvalue.rangev.uppertype, &ub) )
153 		sprintf(*pbuf,"?,");
154 	      else
155 		sprintf(*pbuf,"%d,",ub);
156 	  }
157           else {
158 		ub = r->symvalue.rangev.upper;
159 		sprintf(*pbuf,"%d,",ub);
160 		}
161     	  *pbuf += strlen(*pbuf);
162 
163        }
164 }
165 
166 /*
167  * Print out the declaration of a FORTRAN variable.
168  */
169 
170 public fortran_printdecl(s)
171 Symbol s;
172 {
173     Symbol eltype;
174 
175     switch (s->class) {
176 	case CONST:
177 	    printf("parameter %s = ", symname(s));
178 	    eval(s->symvalue.constval);
179             printval(s);
180 	    break;
181 
182         case REF:
183             printf(" (dummy argument) ");
184 
185 	case VAR:
186 	    if (s->type->class == ARRAY &&
187 		 (not istypename(s->type->type,"char")) ) {
188                 char bounds[130], *p1, **p;
189 		p1 = bounds;
190                 p = &p1;
191                 mksubs(p,s->type);
192                 *p -= 1;
193                 **p = '\0';   /* get rid of trailing ',' */
194 		printf(" %s %s[%s] ",typename(s), symname(s), bounds);
195 	    } else {
196 		printf("%s %s", typename(s), symname(s));
197 	    }
198 	    break;
199 
200 	case FUNC:
201 	    if (not istypename(s->type, "void")) {
202                 printf(" %s function ", typename(s) );
203 	    }
204 	    else printf(" subroutine");
205 	    printf(" %s ", symname(s));
206 	    fortran_listparams(s);
207 	    break;
208 
209 	case MODULE:
210 	    printf("source file \"%s.c\"", symname(s));
211 	    break;
212 
213 	case PROG:
214 	    printf("executable file \"%s\"", symname(s));
215 	    break;
216 
217 	default:
218 	    error("class %s in fortran_printdecl", classname(s));
219     }
220     putchar('\n');
221 }
222 
223 /*
224  * List the parameters of a procedure or function.
225  * No attempt is made to combine like types.
226  */
227 
228 public fortran_listparams(s)
229 Symbol s;
230 {
231     register Symbol t;
232 
233     putchar('(');
234     for (t = s->chain; t != nil; t = t->chain) {
235 	printf("%s", symname(t));
236 	if (t->chain != nil) {
237 	    printf(", ");
238 	}
239     }
240     putchar(')');
241     if (s->chain != nil) {
242 	printf("\n");
243 	for (t = s->chain; t != nil; t = t->chain) {
244 	    if (t->class != REF) {
245 		panic("unexpected class %d for parameter", t->class);
246 	    }
247 	    printdecl(t, 0);
248 	}
249     } else {
250 	putchar('\n');
251     }
252 }
253 
254 /*
255  * Print out the value on the top of the expression stack
256  * in the format for the type of the given symbol.
257  */
258 
259 public fortran_printval(s)
260 Symbol s;
261 {
262     register Symbol t;
263     register Address a;
264     register int i, len;
265     double d1, d2;
266 
267     switch (s->class) {
268 	case CONST:
269 	case TYPE:
270 	case VAR:
271 	case REF:
272 	case FVAR:
273 	case TAG:
274 	    fortran_printval(s->type);
275 	    break;
276 
277 	case ARRAY:
278 	    t = rtype(s->type);
279 	    if (t->class == RANGE and istypename(t->type, "char")) {
280 		len = size(s);
281 		sp -= len;
282 		printf("\"%.*s\"", len, sp);
283 	    } else {
284 		fortran_printarray(s);
285 	    }
286 	    break;
287 
288 	case RANGE:
289 	     if (isspecial(s)) {
290 		switch (s->symvalue.rangev.lower) {
291 		    case sizeof(short):
292 			if (istypename(s->type, "logical*2")) {
293 			    printlogical(pop(short));
294 			}
295 			break;
296 
297 		    case sizeof(float):
298 			if (istypename(s->type, "logical")) {
299 			    printlogical(pop(long));
300 			} else {
301 			    prtreal(pop(float));
302 			}
303 			break;
304 
305 		    case sizeof(double):
306 			if (istypename(s->type,"complex")) {
307 			    d2 = pop(float);
308 			    d1 = pop(float);
309 			    printf("(");
310 			    prtreal(d1);
311 			    printf(",");
312 			    prtreal(d2);
313 			    printf(")");
314 			} else {
315 			    prtreal(pop(double));
316 			}
317 			break;
318 
319 		    case 2*sizeof(double):
320 			d2 = pop(double);
321 			d1 = pop(double);
322 			printf("(");
323 			prtreal(d1);
324 			printf(",");
325 			prtreal(d2);
326 			printf(")");
327 			break;
328 
329 		    default:
330 			panic("bad size \"%d\" for special",
331                                   s->symvalue.rangev.lower);
332 			break;
333 		}
334 	    } else {
335 		printint(popsmall(s), s);
336 	    }
337 	    break;
338 
339 	default:
340 	    if (ord(s->class) > ord(TYPEREF)) {
341 		panic("printval: bad class %d", ord(s->class));
342 	    }
343 	    error("don't know how to print a %s", fortran_classname(s));
344 	    /* NOTREACHED */
345     }
346 }
347 
348 /*
349  * Print out a logical
350  */
351 
352 private printlogical (i)
353 integer i;
354 {
355     if (i == 0) {
356 	printf(".false.");
357     } else {
358 	printf(".true.");
359     }
360 }
361 
362 /*
363  * Print out an int
364  */
365 
366 private printint(i, t)
367 Integer i;
368 register Symbol t;
369 {
370     if (t->type == t_int or istypename(t->type, "integer") or
371 	istypename(t->type,"integer*2")
372     ) {
373 	printf("%ld", i);
374     } else if (istypename(t->type, "addr")) {
375 	printf("0x%lx", i);
376     } else {
377 	error("unknown type in fortran printint");
378     }
379 }
380 
381 /*
382  * Print out a null-terminated string (pointer to char)
383  * starting at the given address.
384  */
385 
386 private printstring(addr)
387 Address addr;
388 {
389     register Address a;
390     register Integer i, len;
391     register Boolean endofstring;
392     union {
393 	char ch[sizeof(Word)];
394 	int word;
395     } u;
396 
397     putchar('"');
398     a = addr;
399     endofstring = false;
400     while (not endofstring) {
401 	dread(&u, a, sizeof(u));
402 	i = 0;
403 	do {
404 	    if (u.ch[i] == '\0') {
405 		endofstring = true;
406 	    } else {
407 		printchar(u.ch[i]);
408 	    }
409 	    ++i;
410 	} while (i < sizeof(Word) and not endofstring);
411 	a += sizeof(Word);
412     }
413     putchar('"');
414 }
415 /*
416  * Return the FORTRAN name for the particular class of a symbol.
417  */
418 
419 public String fortran_classname(s)
420 Symbol s;
421 {
422     String str;
423 
424     switch (s->class) {
425 	case REF:
426 	    str = "dummy argument";
427 	    break;
428 
429 	case CONST:
430 	    str = "parameter";
431 	    break;
432 
433 	default:
434 	    str = classname(s);
435     }
436     return str;
437 }
438 
439 /* reverses the indices from the expr_list; should be folded into buildaref
440  * and done as one recursive routine
441  */
442 Node private rev_index(here,n)
443 register Node here,n;
444 {
445 
446   register Node i;
447 
448   if( here == nil  or  here == n) i=nil;
449   else if( here->value.arg[1] == n) i = here;
450   else i=rev_index(here->value.arg[1],n);
451   return i;
452 }
453 
454 public Node fortran_buildaref(a, slist)
455 Node a, slist;
456 {
457     register Symbol as;      /* array of array of .. cursor */
458     register Node en;        /* Expr list cursor */
459     Symbol etype;            /* Type of subscript expr */
460     Node esub, tree;         /* Subscript expression ptr and tree to be built*/
461 
462     tree=a;
463 
464     as = rtype(tree->nodetype);     /* node->sym.type->array*/
465     if ( not (
466                (tree->nodetype->class == VAR or tree->nodetype->class == REF)
467                 and as->class == ARRAY
468              ) ) {
469 	beginerrmsg();
470 	prtree(stderr, a);
471 	fprintf(stderr, " is not an array");
472 	/*fprintf(stderr, " a-> %x as %x ", tree->nodetype, as ); OUT*/
473 	enderrmsg();
474     } else {
475 	for (en = rev_index(slist,nil); en != nil and as->class == ARRAY;
476                      en = rev_index(slist,en), as = as->type) {
477 	    esub = en->value.arg[0];
478 	    etype = rtype(esub->nodetype);
479             assert(as->chain->class == RANGE);
480 	    if ( not compatible( t_int, etype) ) {
481 		beginerrmsg();
482 		fprintf(stderr, "subscript ");
483 		prtree(stderr, esub);
484 		fprintf(stderr, " is type %s ",symname(etype->type) );
485 		enderrmsg();
486 	    }
487 	    tree = build(O_INDEX, tree, esub);
488 	    tree->nodetype = as->type;
489 	}
490 	if (en != nil or
491              (as->class == ARRAY && (not istypename(as->type,"char"))) ) {
492 	    beginerrmsg();
493 	    if (en != nil) {
494 		fprintf(stderr, "too many subscripts for ");
495 	    } else {
496 		fprintf(stderr, "not enough subscripts for ");
497 	    }
498 	    prtree(stderr, tree);
499 	    enderrmsg();
500 	}
501     }
502     return tree;
503 }
504 
505 /*
506  * Evaluate a subscript index.
507  */
508 
509 public fortran_evalaref(s, base, i)
510 Symbol s;
511 Address base;
512 long i;
513 {
514     Symbol r, t;
515     long lb, ub;
516 
517     t = rtype(s);
518     r = t->chain;
519     if (
520 	r->symvalue.rangev.lowertype == R_ARG or
521         r->symvalue.rangev.lowertype == R_TEMP
522     ) {
523 	if (not getbound(
524 	    s, r->symvalue.rangev.lower, r->symvalue.rangev.lowertype, &lb
525 	)) {
526           error("dynamic bounds not currently available");
527 	}
528     } else {
529 	lb = r->symvalue.rangev.lower;
530     }
531     if (
532 	r->symvalue.rangev.uppertype == R_ARG or
533         r->symvalue.rangev.uppertype == R_TEMP
534     ) {
535 	if (not getbound(
536 	    s, r->symvalue.rangev.upper, r->symvalue.rangev.uppertype, &ub
537 	)) {
538           error("dynamic bounds not currently available");
539 	}
540     } else {
541 	ub = r->symvalue.rangev.upper;
542     }
543 
544     if (i < lb or i > ub) {
545 	error("subscript out of range");
546     }
547     push(long, base + (i - lb) * size(t->type));
548 }
549 
550 private fortran_printarray(a)
551 Symbol a;
552 {
553 struct Bounds { int lb, val, ub; } dim[MAXDIM];
554 
555 Symbol sc,st,eltype;
556 char buf[50];
557 char *subscr;
558 int i,ndim,elsize;
559 Stack *savesp;
560 Boolean done;
561 
562 st = a;
563 
564 savesp = sp;
565 sp -= size(a);
566 ndim=0;
567 
568 for(;;){
569           sc = st->chain;
570           if(sc->symvalue.rangev.lowertype == R_ARG or
571              sc->symvalue.rangev.lowertype == R_TEMP) {
572 	      if( ! getbound(a,sc->symvalue.rangev.lower,
573                     sc->symvalue.rangev.lowertype, &dim[ndim].lb) )
574 		error(" dynamic bounds not currently available");
575 	  }
576 	  else dim[ndim].lb = sc->symvalue.rangev.lower;
577 
578           if(sc->symvalue.rangev.uppertype == R_ARG or
579              sc->symvalue.rangev.uppertype == R_TEMP) {
580 	      if( ! getbound(a,sc->symvalue.rangev.upper,
581                     sc->symvalue.rangev.uppertype, &dim[ndim].ub) )
582 		error(" dynamic bounds not currently available");
583 	  }
584 	  else dim[ndim].ub = sc->symvalue.rangev.upper;
585 
586           ndim ++;
587           if (st->type->class == ARRAY) st=st->type;
588 	  else break;
589      }
590 
591 if(istypename(st->type,"char")) {
592 		eltype = st;
593 		ndim--;
594 	}
595 else eltype=st->type;
596 elsize=size(eltype);
597 sp += elsize;
598  /*printf("ndim %d elsize %lx in fortran_printarray\n",ndim,elsize);OUT*/
599 
600 ndim--;
601 for (i=0;i<=ndim;i++){
602 	  dim[i].val=dim[i].lb;
603 	  /*OUT printf(" %d %d %d \n",i,dim[i].lb,dim[i].ub);
604 	    fflush(stdout); OUT*/
605 }
606 
607 
608 for(;;) {
609 	buf[0]=',';
610 	subscr = buf+1;
611 
612 	for (i=ndim-1;i>=0;i--)  {
613 
614 		sprintf(subscr,"%d,",dim[i].val);
615         	subscr += strlen(subscr);
616 	}
617         *--subscr = '\0';
618 
619 	for(i=dim[ndim].lb;i<=dim[ndim].ub;i++) {
620 	      	printf("[%d%s]\t",i,buf);
621 		printval(eltype);
622 	      	printf("\n");
623 		sp += 2*elsize;
624 	}
625         dim[ndim].val=dim[ndim].ub;
626 
627         i=ndim-1;
628         if (i<0) break;
629 
630         done=false;
631         do {
632 		dim[i].val++;
633 		if(dim[i].val > dim[i].ub) {
634 			dim[i].val = dim[i].lb;
635 			if(--i<0) done=true;
636 		}
637 		else done=true;
638          }
639 	 while (not done);
640          if (i<0) break;
641      }
642 }
643 
644 /*
645  * Initialize typetable at beginning of a module.
646  */
647 
648 public fortran_modinit (typetable)
649 Symbol typetable[];
650 {
651     /* nothing for now */
652 }
653 
654 public boolean fortran_hasmodules ()
655 {
656     return false;
657 }
658 
659 public boolean fortran_passaddr (param, exprtype)
660 Symbol param, exprtype;
661 {
662     return false;
663 }
664