Pristine Ack-5.5
[Ack-5.5.git] / lang / fortran / comp / names.c
1 /****************************************************************
2 Copyright 1990 by AT&T Bell Laboratories and Bellcore.
3
4 Permission to use, copy, modify, and distribute this software
5 and its documentation for any purpose and without fee is hereby
6 granted, provided that the above copyright notice appear in all
7 copies and that both that the copyright notice and this
8 permission notice and warranty disclaimer appear in supporting
9 documentation, and that the names of AT&T Bell Laboratories or
10 Bellcore or any of their entities not be used in advertising or
11 publicity pertaining to distribution of the software without
12 specific, written prior permission.
13
14 AT&T and Bellcore disclaim all warranties with regard to this
15 software, including all implied warranties of merchantability
16 and fitness.  In no event shall AT&T or Bellcore be liable for
17 any special, indirect or consequential damages or any damages
18 whatsoever resulting from loss of use, data or profits, whether
19 in an action of contract, negligence or other tortious action,
20 arising out of or in connection with the use or performance of
21 this software.
22 ****************************************************************/
23
24 #include "defs.h"
25 #include "output.h"
26 #include "names.h"
27 #include "iob.h"
28
29
30 /* Names generated by the translator are guaranteed to be unique from the
31    Fortan names because Fortran does not allow underscores in identifiers,
32    and all of the system generated names do have underscores.  The various
33    naming conventions are outlined below:
34
35         FORMAT          APPLICATION
36    ----------------------------------------------------------------------
37         io_#            temporaries generated by IO calls; these will
38                         contain the device number (e.g. 5, 6, 0)
39         ret_val         function return value, required for complex and
40                         character functions.
41         ret_val_len     length of the return value in character functions
42
43         ssss_len        length of character argument "ssss"
44
45         c_#             member of the literal pool, where # is an
46                         arbitrary label assigned by the system
47         cs_#            short integer constant in the literal pool
48         t_#             expression temporary, # is the depth of arguments
49                         on the stack.
50         L#              label "#", given by user in the Fortran program.
51                         This is unique because Fortran labels are numeric
52         pad_#           label on an init field required for alignment
53         xxx_init        label on a common block union, if a block data
54                         requires a separate declaration
55 */
56
57 /* generate variable references */
58
59 char *c_type_decl (type, is_extern)
60 int type, is_extern;
61 {
62     static char buff[100];
63
64     switch (type) {
65         case TYADDR:    strcpy (buff, "address");       break;
66         case TYSHORT:   strcpy (buff, "shortint");      break;
67         case TYLONG:    strcpy (buff, "integer");       break;
68         case TYREAL:    if (!is_extern || !forcedouble)
69                                 { strcpy (buff, "real");break; }
70         case TYDREAL:   strcpy (buff, "doublereal");    break;
71         case TYCOMPLEX: if (is_extern)
72                             strcpy (buff, Ansi  ? "/* Complex */ VOID"
73                                                 : "/* Complex */ int");
74                         else
75                             strcpy (buff, "complex");
76                         break;
77         case TYDCOMPLEX:if (is_extern)
78                             strcpy (buff, Ansi  ? "/* Double Complex */ VOID"
79                                                 : "/* Double Complex */ int");
80                         else
81                             strcpy (buff, "doublecomplex");
82                         break;
83         case TYLOGICAL: strcpy(buff, typename[TYLOGICAL]);
84                         break;
85         case TYCHAR:    if (is_extern)
86                             strcpy (buff, Ansi  ? "/* Character */ VOID"
87                                                 : "/* Character */ int");
88                         else
89                             strcpy (buff, "char");
90                         break;
91
92         case TYUNKNOWN: strcpy (buff, "UNKNOWN");
93
94 /* If a procedure's type is unknown, assume it's a subroutine */
95
96                         if (!is_extern)
97                             break;
98
99 /* Subroutines must return an INT, because they might return a label
100    value.  Even if one doesn't, the caller will EXPECT it to. */
101
102         case TYSUBR:    strcpy (buff, "/* Subroutine */ int");
103                                                         break;
104         case TYERROR:   strcpy (buff, "ERROR");         break;
105         case TYVOID:    strcpy (buff, "void");          break;
106         case TYCILIST:  strcpy (buff, "cilist");        break;
107         case TYICILIST: strcpy (buff, "icilist");       break;
108         case TYOLIST:   strcpy (buff, "olist");         break;
109         case TYCLLIST:  strcpy (buff, "cllist");        break;
110         case TYALIST:   strcpy (buff, "alist");         break;
111         case TYINLIST:  strcpy (buff, "inlist");        break;
112         case TYFTNLEN:  strcpy (buff, "ftnlen");        break;
113         default:        sprintf (buff, "BAD DECL '%d'", type);
114                                                         break;
115     } /* switch */
116
117     return buff;
118 } /* c_type_decl */
119
120
121 char *new_func_length()
122 { return "ret_val_len"; }
123
124 char *new_arg_length(arg)
125  Namep arg;
126 {
127         static char buf[64];
128         sprintf (buf, "%s_len", arg->fvarname);
129
130         return buf;
131 } /* new_arg_length */
132
133
134 /* declare_new_addr -- Add a new local variable to the function, given a
135    pointer to an Addrblock structure (which must have the uname_tag set)
136    This list of idents will be printed in reverse (i.e., chronological)
137    order */
138
139  void
140 declare_new_addr (addrp)
141 struct Addrblock *addrp;
142 {
143     extern chainp new_vars;
144
145     new_vars = mkchain((char *)cpexpr((expptr)addrp), new_vars);
146 } /* declare_new_addr */
147
148
149 wr_nv_ident_help (outfile, addrp)
150 FILE *outfile;
151 struct Addrblock *addrp;
152 {
153     int eltcount = 0;
154
155     if (addrp == (struct Addrblock *) NULL)
156         return;
157
158     if (addrp -> isarray) {
159         frexpr (addrp -> memoffset);
160         addrp -> memoffset = ICON(0);
161         eltcount = addrp -> ntempelt;
162         addrp -> ntempelt = 0;
163         addrp -> isarray = 0;
164     } /* if */
165     out_addr (outfile, addrp);
166     if (eltcount)
167         nice_printf (outfile, "[%d]", eltcount);
168 } /* wr_nv_ident_help */
169
170 int nv_type_help (addrp)
171 struct Addrblock *addrp;
172 {
173     if (addrp == (struct Addrblock *) NULL)
174         return -1;
175
176     return addrp -> vtype;
177 } /* nv_type_help */
178
179
180 /* lit_name -- returns a unique identifier for the given literal.  Make
181    the label useful, when possible.  For example:
182
183         1 -> c_1                (constant 1)
184         2 -> c_2                (constant 2)
185         1000 -> c_1000          (constant 1000)
186         1000000 -> c_b<memno>   (big constant number)
187         1.2 -> c_1_2            (constant 1.2)
188         1.234345 -> c_b<memno>  (big constant number)
189         -1 -> c_n1              (constant -1)
190         -1.0 -> c_n1_0          (constant -1.0)
191         .true. -> c_true        (constant true)
192         .false. -> c_false      (constant false)
193         default -> c_b<memno>   (default label)
194 */
195
196 char *lit_name (litp)
197 struct Literal *litp;
198 {
199     static char buf[CONST_IDENT_MAX];
200
201     if (litp == (struct Literal *) NULL)
202         return NULL;
203
204     switch (litp -> littype) {
205         case TYSHORT:
206             if (litp -> litval.litival < 32768 &&
207                     litp -> litval.litival > -32769) {
208                 ftnint val = litp -> litval.litival;
209
210                 if (val < 0)
211                     sprintf (buf, "cs_n%ld", -val);
212                 else
213                     sprintf (buf, "cs__%ld", val);
214             } else
215                 sprintf (buf, "c_b%d", litp -> litnum);
216             break;
217         case TYLONG:
218             if (litp -> litval.litival < 100000 &&
219                     litp -> litval.litival > -10000) {
220                 ftnint val = litp -> litval.litival;
221
222                 if (val < 0)
223                     sprintf (buf, "c_n%ld", -val);
224                 else
225                     sprintf (buf, "c__%ld", val);
226             } else
227                 sprintf (buf, "c_b%d", litp -> litnum);
228             break;
229         case TYLOGICAL:
230             sprintf (buf, "c_%s", (litp -> litval.litival ? "true" : "false"));
231             break;
232         case TYREAL:
233         case TYDREAL:
234                 /* Given a limit of 6 or 8 character on external names, */
235                 /* few f.p. values can be meaningfully encoded in the   */
236                 /* constant name.  Just going with the default cb_#     */
237                 /* seems to be the best course for floating-point       */
238                 /* constants.   */
239         case TYCHAR:
240             /* Shouldn't be any of these */
241         case TYADDR:
242         case TYCOMPLEX:
243         case TYDCOMPLEX:
244         case TYSUBR:
245         default:
246             sprintf (buf, "c_b%d", litp -> litnum);
247             break;
248     } /* switch */
249     return buf;
250 } /* lit_name */
251
252
253
254  char *
255 comm_union_name(count)
256  int count;
257 {
258         static char buf[12];
259
260         sprintf(buf, "%d", count);
261         return buf;
262         }
263
264
265
266
267 /* wr_globals -- after every function has been translated, we need to
268    output the global declarations, such as the static table of constant
269    values */
270
271 wr_globals (outfile)
272 FILE *outfile;
273 {
274     struct Literal *litp, *lastlit;
275     extern int hsize;
276     extern char *lit_name();
277     char *litname;
278     int did_one, t;
279     struct Constblock cb;
280     ftnint x, y;
281
282     if (nliterals == 0)
283         return;
284
285     lastlit = litpool + nliterals;
286     did_one = 0;
287     for (litp = litpool; litp < lastlit; litp++) {
288         if (!litp->lituse)
289                 continue;
290         litname = lit_name(litp);
291         if (!did_one) {
292                 margin_printf(outfile, "/* Table of constant values */\n\n");
293                 did_one = 1;
294                 }
295         cb.vtype = litp->littype;
296         if (litp->littype == TYCHAR) {
297                 x = litp->litval.litival2[0] + litp->litval.litival2[1];
298                 y = x + 1;
299                 nice_printf(outfile,
300                         "static struct { %s fill; char val[%ld+1];", halign, x);
301                 if (y %= hsize)
302                         nice_printf(outfile, " char fill2[%ld];", hsize - y);
303                 nice_printf(outfile, " } %s_st = { 0,", litname);
304                 cb.vleng = ICON(litp->litval.litival2[0]);
305                 cb.Const.ccp = litp->cds[0];
306                 cb.Const.ccp1.blanks = litp->litval.litival2[1];
307                 cb.vtype = TYCHAR;
308                 out_const(outfile, &cb);
309                 frexpr(cb.vleng);
310                 nice_printf(outfile, " };\n");
311                 nice_printf(outfile, "#define %s %s_st.val\n", litname, litname);
312                 continue;
313                 }
314         nice_printf(outfile, "static %s %s = ",
315                 c_type_decl(litp->littype,0), litname);
316
317         t = litp->littype;
318         if (ONEOF(t, MSKREAL|MSKCOMPLEX)) {
319                 cb.vstg = 1;
320                 cb.Const.cds[0] = litp->cds[0];
321                 cb.Const.cds[1] = litp->cds[1];
322                 }
323         else {
324                 memcpy((char *)&cb.Const, (char *)&litp->litval,
325                         sizeof(cb.Const));
326                 cb.vstg = 0;
327                 }
328         out_const(outfile, &cb);
329
330         nice_printf (outfile, ";\n");
331     } /* for */
332     if (did_one)
333         nice_printf (outfile, "\n");
334 } /* wr_globals */
335
336  ftnint
337 commlen(vl)
338  register chainp vl;
339 {
340         ftnint size;
341         int type;
342         struct Dimblock *t;
343         Namep v;
344
345         while(vl->nextp)
346                 vl = vl->nextp;
347         v = (Namep)vl->datap;
348         type = v->vtype;
349         if (type == TYCHAR)
350                 size = v->vleng->constblock.Const.ci;
351         else
352                 size = typesize[type];
353         if ((t = v->vdim) && ISCONST(t->nelt))
354                 size *= t->nelt->constblock.Const.ci;
355         return size + v->voffset;
356         }
357
358  static void    /* Pad common block if an EQUIVALENCE extended it. */
359 pad_common(c)
360  Extsym *c;
361 {
362         register chainp cvl;
363         register Namep v;
364         long L = c->maxleng;
365         int type;
366         struct Dimblock *t;
367         int szshort = typesize[TYSHORT];
368
369         for(cvl = c->allextp; cvl; cvl = cvl->nextp)
370                 if (commlen((chainp)cvl->datap) >= L)
371                         return;
372         v = ALLOC(Nameblock);
373         v->vtype = type = L % szshort ? TYCHAR
374                                       : type_choice[L/szshort % 4];
375         v->vstg = STGCOMMON;
376         v->vclass = CLVAR;
377         v->tag = TNAME;
378         v->vdim = t = ALLOC(Dimblock);
379         t->ndim = 1;
380         t->dims[0].dimsize = ICON(L / typesize[type]);
381         v->fvarname = v->cvarname = "eqv_pad";
382         c->allextp = mkchain((char *)mkchain((char *)v, CHNULL), c->allextp);
383         }
384
385
386 /* wr_common_decls -- outputs the common declarations in one of three
387    formats.  If all references to a common block look the same (field
388    names and types agree), only one actual declaration will appear.
389    Otherwise, the same block will require many structs.  If there is no
390    block data, these structs will be union'ed together (so the linker
391    knows the size of the largest one).  If there IS a block data, only
392    that version will be associated with the variable, others will only be
393    defined as types, so the pointer can be cast to it.  e.g.
394
395         FORTRAN                         C
396 ----------------------------------------------------------------------
397         common /com1/ a, b, c           struct { real a, b, c; } com1_;
398
399         common /com1/ a, b, c           union {
400         common /com1/ i, j, k               struct { real a, b, c; } _1;
401                                             struct { integer i, j, k; } _2;
402                                         } com1_;
403
404         common /com1/ a, b, c           struct com1_1_ { real a, b, c; };
405         block data                      struct { integer i, j, k; } com1_ =
406         common /com1/ i, j, k             { 1, 2, 3 };
407         data i/1/, j/2/, k/3/
408
409
410    All of these versions will be followed by #defines, since the code in
411    the function bodies can't know ahead of time which of these options
412    will be taken */
413
414 /* Macros for deciding the output type */
415
416 #define ONE_STRUCT 1
417 #define UNION_STRUCT 2
418 #define INIT_STRUCT 3
419
420 wr_common_decls(outfile)
421  FILE *outfile;
422 {
423     Extsym *ext;
424     extern int extcomm;
425     static char *Extern[4] = {"", "Extern ", "extern "};
426     char *E, *E0 = Extern[extcomm];
427     int did_one = 0;
428
429     for (ext = extsymtab; ext < nextext; ext++) {
430         if (ext -> extstg == STGCOMMON && ext->allextp) {
431             chainp comm;
432             int count = 1;
433             int which;                  /* which display to use;
434                                            ONE_STRUCT, UNION or INIT */
435
436             if (!did_one)
437                 nice_printf (outfile, "/* Common Block Declarations */\n\n");
438
439             pad_common(ext);
440
441 /* Construct the proper, condensed list of structs; eliminate duplicates
442    from the initial list   ext -> allextp   */
443
444             comm = ext->allextp = revchain(ext->allextp);
445
446             if (ext -> extinit)
447                 which = INIT_STRUCT;
448             else if (comm->nextp) {
449                 which = UNION_STRUCT;
450                 nice_printf (outfile, "%sunion {\n", E0);
451                 next_tab (outfile);
452                 E = "";
453                 }
454             else {
455                 which = ONE_STRUCT;
456                 E = E0;
457                 }
458
459             for (; comm; comm = comm -> nextp, count++) {
460
461                 if (which == INIT_STRUCT)
462                     nice_printf (outfile, "struct %s%d_ {\n",
463                             ext->cextname, count);
464                 else
465                     nice_printf (outfile, "%sstruct {\n", E);
466
467                 next_tab (c_file);
468
469                 wr_struct (outfile, (chainp) comm -> datap);
470
471                 prev_tab (c_file);
472                 if (which == UNION_STRUCT)
473                     nice_printf (outfile, "} _%d;\n", count);
474                 else if (which == ONE_STRUCT)
475                     nice_printf (outfile, "} %s;\n", ext->cextname);
476                 else
477                     nice_printf (outfile, "};\n");
478             } /* for */
479
480             if (which == UNION_STRUCT) {
481                 prev_tab (c_file);
482                 nice_printf (outfile, "} %s;\n", ext->cextname);
483             } /* if */
484             did_one = 1;
485             nice_printf (outfile, "\n");
486
487             for (count = 1, comm = ext -> allextp; comm;
488                     comm = comm -> nextp, count++) {
489                 def_start(outfile, ext->cextname,
490                         comm_union_name(count), "");
491                 switch (which) {
492                     case ONE_STRUCT:
493                         extern_out (outfile, ext);
494                         break;
495                     case UNION_STRUCT:
496                         nice_printf (outfile, "(");
497                         extern_out (outfile, ext);
498                         nice_printf(outfile, "._%d)", count);
499                         break;
500                     case INIT_STRUCT:
501                         nice_printf (outfile, "(*(struct ");
502                         extern_out (outfile, ext);
503                         nice_printf (outfile, "%d_ *) &", count);
504                         extern_out (outfile, ext);
505                         nice_printf (outfile, ")");
506                         break;
507                 } /* switch */
508                 nice_printf (outfile, "\n");
509             } /* for count = 1, comm = ext -> allextp */
510             nice_printf (outfile, "\n");
511         } /* if ext -> extstg == STGCOMMON */
512     } /* for ext = extsymtab */
513 } /* wr_common_decls */
514
515
516 wr_struct (outfile, var_list)
517 FILE *outfile;
518 chainp var_list;
519 {
520     int last_type = -1;
521     int did_one = 0;
522     chainp this_var;
523
524     for (this_var = var_list; this_var; this_var = this_var -> nextp) {
525         Namep var = (Namep) this_var -> datap;
526         int type;
527         char *comment = NULL, *wr_ardecls ();
528
529         if (var == (Namep) NULL)
530             err ("wr_struct:  null variable");
531         else if (var -> tag != TNAME)
532             erri ("wr_struct:  bad tag on variable '%d'",
533                     var -> tag);
534
535         type = var -> vtype;
536
537         if (last_type == type && did_one)
538             nice_printf (outfile, ", ");
539         else {
540             if (did_one)
541                 nice_printf (outfile, ";\n");
542             nice_printf (outfile, "%s ",
543                     c_type_decl (type, var -> vclass == CLPROC));
544         } /* else */
545
546 /* Character type is really a string type.  Put out a '*' for parameters
547    with unknown length and functions returning character */
548
549         if (var -> vtype == TYCHAR && (!ISICON ((var -> vleng))
550                 || var -> vclass == CLPROC))
551             nice_printf (outfile, "*");
552
553         var -> vstg = STGAUTO;
554         out_name (outfile, var);
555         if (var -> vclass == CLPROC)
556             nice_printf (outfile, "()");
557         else if (var -> vdim)
558             comment = wr_ardecls(outfile, var->vdim,
559                                 var->vtype == TYCHAR && ISICON(var->vleng)
560                                 ? var->vleng->constblock.Const.ci : 1L);
561         else if (var -> vtype == TYCHAR && var -> vclass != CLPROC &&
562             ISICON ((var -> vleng)))
563             nice_printf (outfile, "[%ld]",
564                     var -> vleng -> constblock.Const.ci);
565
566         if (comment)
567             nice_printf (outfile, "%s", comment);
568         did_one = 1;
569         last_type = type;
570     } /* for this_var */
571
572     if (did_one)
573         nice_printf (outfile, ";\n");
574 } /* wr_struct */
575
576
577 char *user_label(stateno)
578 ftnint stateno;
579 {
580         static char buf[USER_LABEL_MAX + 1];
581         static char *Lfmt[2] = { "L_%ld", "L%ld" };
582
583         if (stateno >= 0)
584                 sprintf(buf, Lfmt[shiftcase], stateno);
585         else
586                 sprintf(buf, "L_%s", extsymtab[-1-stateno].fextname);
587         return buf;
588 } /* user_label */
589
590
591 char *temp_name (starter, num, storage)
592 char *starter;
593 int num;
594 char *storage;
595 {
596     static char buf[IDENT_LEN];
597     char *pointer = buf;
598     char *prefix = "t";
599
600     if (storage)
601         pointer = storage;
602
603     if (starter && *starter)
604         prefix = starter;
605
606     sprintf (pointer, "%s__%d", prefix, num);
607     return pointer;
608 } /* temp_name */
609
610
611 char *equiv_name (memno, store)
612 int memno;
613 char *store;
614 {
615     static char buf[IDENT_LEN];
616     char *pointer = buf;
617
618     if (store)
619         pointer = store;
620
621     sprintf (pointer, "%s_%d", EQUIV_INIT_NAME, memno);
622     return pointer;
623 } /* equiv_name */
624
625  void
626 def_commons(of)
627  FILE *of;
628 {
629         Extsym *ext;
630         int c, onefile, Union;
631         char buf[64];
632         chainp comm;
633         extern int ext1comm;
634
635         if (ext1comm == 1) {
636                 onefile = 1;
637                 c_file = of;
638                 fprintf(of, "/*>>>'/dev/null'<<<*/\n\
639 #ifdef Define_COMMONs\n\
640 /*<<</dev/null>>>*/\n");
641                 }
642         else
643                 onefile = 0;
644         for(ext = extsymtab; ext < nextext; ext++)
645                 if (ext->extstg == STGCOMMON
646                 && !ext->extinit && (comm = ext->allextp)) {
647                         sprintf(buf, "%scom.c", ext->cextname);
648                         if (onefile)
649                                 fprintf(of, "/*>>>'%s'<<<*/\n",
650                                         buf);
651                         else {
652                                 c_file = of = fopen(buf,textwrite);
653                                 if (!of)
654                                         fatalstr("can't open %s", buf);
655                                 }
656                         fprintf(of, "#include \"f2c.h\"\n");
657                         if (comm->nextp) {
658                                 Union = 1;
659                                 nice_printf(of, "union {\n");
660                                 next_tab(of);
661                                 }
662                         else
663                                 Union = 0;
664                         for(c = 1; comm; comm = comm->nextp) {
665                                 nice_printf(of, "struct {\n");
666                                 next_tab(of);
667                                 wr_struct(of, (chainp)comm->datap);
668                                 prev_tab(of);
669                                 if (Union)
670                                         nice_printf(of, "} _%d;\n", c++);
671                                 }
672                         if (Union)
673                                 prev_tab(of);
674                         nice_printf(of, "} %s;\n", ext->cextname);
675                         if (onefile)
676                                 fprintf(of, "/*<<<%s>>>*/\n", buf);
677                         else
678                                 fclose(of);
679                         }
680         if (onefile)
681                 fprintf(of, "/*>>>'/dev/null'<<<*/\n#endif\n\
682 /*<<</dev/null>>>*/\n");
683         }
684
685 /* C Language keywords.  Needed to filter unwanted fortran identifiers like
686  * "int", etc.  Source:  Kernighan & Ritchie, eds. 1 and 2; Stroustrup.
687  * Also includes C++ keywords and types used for I/O in f2c.h .
688  * These keywords must be in alphabetical order (as defined by strcmp()).
689  */
690
691 char *c_keywords[] = {
692         "Long", "Multitype", "Namelist", "Vardesc",
693         "abs", "acos", "address", "alist", "asin", "asm",
694         "atan", "atan2", "auto", "break",
695         "case", "catch", "char", "cilist", "class", "cllist",
696         "complex", "const", "continue", "cos", "cosh",
697         "dabs", "default", "defined", "delete",
698         "dmax", "dmin", "do", "double", "doublecomplex", "doublereal",
699         "else", "entry", "enum", "exp", "extern",
700         "flag", "float", "for", "friend", "ftnint", "ftnlen", "goto",
701         "icilist", "if", "include", "inline", "inlist", "int", "integer",
702         "log", "logical", "long", "max", "min", "new",
703         "olist", "operator", "overload", "private", "protected", "public",
704         "real", "register", "return",
705         "short", "shortint", "shortlogical", "signed", "sin", "sinh",
706         "sizeof", "sqrt", "static", "struct", "switch",
707         "tan", "tanh", "template", "this", "try", "typedef",
708         "union", "unsigned", "virtual", "void", "volatile", "while"
709 }; /* c_keywords */
710
711 int n_keywords = sizeof(c_keywords)/sizeof(char *);