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