1 /****************************************************************
2 Copyright 1990, 1991 by AT&T Bell Laboratories and Bellcore.
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.
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
22 ****************************************************************/
24 /* Format.c -- this file takes an intermediate file (generated by pass 1
25 of the translator) and some state information about the contents of that
26 file, and generates C program text. */
35 int c_output_line_length = DEF_C_LINE_LENGTH;
37 int last_was_label; /* Boolean used to generate semicolons
38 when a label terminates a block */
39 static char this_proc_name[52]; /* Name of the current procedure. This is
40 probably too simplistic to handle
41 multiple entry points */
43 static int p1getd(), p1gets(), p1getf(), get_p1_token();
44 static int p1get_const(), p1getn();
45 static expptr do_format(), do_p1_name_pointer(), do_p1_const();
46 static expptr do_p1_expr(), do_p1_ident(), do_p1_charp(), do_p1_extern();
47 static expptr do_p1_head(), do_p1_list(), do_p1_literal();
48 static void do_p1_label(), do_p1_asgoto(), do_p1_goto();
49 static void do_p1_if(), do_p1_else(), do_p1_elif(), do_p1_endif();
50 static void do_p1_endelse(), do_p1_subr_ret(), do_p1_comp_goto();
51 static void do_p1_for(), do_p1_end_for(), do_p1_fortran();
52 static void do_p1_1while(), do_p1_2while(), do_p1_elseifstart();
53 static void do_p1_comment(), do_p1_set_line();
54 static expptr do_p1_addr();
56 void list_arg_types();
59 extern chainp assigned_fmts;
60 static long old_lineno;
61 static char filename[P1_FILENAME_MAX];
68 static int wrote_one = 0;
69 extern int usedefsforcommon;
70 extern char *p1_file, *p1_bakfile;
72 this_proc_name[0] = '\0';
78 (void) fclose (pass1_file);
79 if ((infile = fopen (p1_file, binread)) == NULL)
80 Fatal("start_formatting: couldn't open the intermediate file\n");
83 nice_printf (c_file, "\n");
85 while (!feof (infile)) {
88 this_expr = do_format (infile, c_file);
90 out_and_free_statement (c_file, this_expr);
92 } /* while !feof infile */
94 (void) fclose (infile);
97 nice_printf (c_file, ";\n");
100 if (this_proc_name[0])
101 nice_printf (c_file, "} /* %s */\n", this_proc_name);
104 /* Write the #undefs for common variable reference */
106 if (usedefsforcommon) {
110 for (ext = extsymtab; ext < nextext; ext++)
111 if (ext -> extstg == STGCOMMON && ext -> used_here) {
112 ext -> used_here = 0;
114 nice_printf (c_file, "\n");
115 wr_abbrevs(c_file, 0, ext->extp);
117 ext -> extp = CHNULL;
121 nice_printf (c_file, "\n");
122 } /* if usedefsforcommon */
124 other_undefs(c_file);
128 /* For debugging only */
130 if (debugflag && (pass1_file = fopen (p1_bakfile, binwrite)))
131 if (infile = fopen (p1_file, binread)) {
132 ffilecopy (infile, pass1_file);
137 /* End of "debugging only" */
139 scrub(p1_file); /* optionally unlink */
141 if ((pass1_file = fopen (p1_file, binwrite)) == NULL)
142 err ("start_formatting: couldn't reopen the pass1 file");
144 } /* start_formatting */
151 nice_printf (outfile, ";\n");
155 #define SEM_CHECK(x) if (last_was_label) put_semi(x)
157 /* do_format -- takes an input stream (a file in pass1 format) and writes
158 the appropriate C code to outfile when possible. When reading an
159 expression, the expression tree is returned instead. */
161 static expptr do_format (infile, outfile)
162 FILE *infile, *outfile;
164 int gsave, token_type, was_c_token;
165 expptr retval = ENULL;
167 token_type = get_p1_token (infile);
169 switch (token_type) {
171 do_p1_comment (infile, outfile);
175 do_p1_set_line (infile);
179 p1gets(infile, filename, P1_FILENAME_MAX);
182 case P1_NAME_POINTER:
183 retval = do_p1_name_pointer (infile);
186 retval = do_p1_const (infile);
189 retval = do_p1_expr (infile, outfile);
192 retval = do_p1_ident(infile);
195 retval = do_p1_charp(infile);
198 retval = do_p1_extern (infile);
203 retval = do_p1_head (infile, outfile);
207 retval = do_p1_list (infile, outfile);
210 retval = do_p1_literal (infile);
213 do_p1_label (infile, outfile);
214 /* last_was_label = 1; -- now set in do_p1_label */
218 do_p1_asgoto (infile, outfile);
221 do_p1_goto (infile, outfile);
224 do_p1_if (infile, outfile);
228 do_p1_else (outfile);
232 do_p1_elif (infile, outfile);
236 do_p1_endif (outfile);
240 do_p1_endelse (outfile);
243 retval = do_p1_addr (infile, outfile);
246 do_p1_subr_ret (infile, outfile);
249 do_p1_comp_goto (infile, outfile);
252 do_p1_for (infile, outfile);
256 do_p1_end_for (outfile);
259 do_p1_1while(outfile);
262 do_p1_2while(infile, outfile);
269 do_p1_elseifstart(outfile);
272 do_p1_fortran(infile, outfile);
278 Fatal("do_format: Unknown token type in intermediate file");
281 Fatal("do_format: Bad token type in intermediate file");
292 do_p1_comment (infile, outfile)
293 FILE *infile, *outfile;
295 extern int c_output_line_length, in_comment;
297 char storage[COMMENT_BUFFER_SIZE + 1];
300 if (!p1gets(infile, storage, COMMENT_BUFFER_SIZE + 1))
303 length = strlen (storage);
306 if (length > c_output_line_length - 6)
307 margin_printf (outfile, "/*%s*/\n", storage);
309 margin_printf (outfile, length ? "/* %s */\n" : "\n", storage);
311 } /* do_p1_comment */
314 do_p1_set_line (infile)
318 long new_line_number = -1;
320 status = p1getd (infile, &new_line_number);
323 err ("do_p1_set_line: Missing line number at end of file\n");
324 else if (status == 0 || new_line_number == -1)
325 errl("do_p1_set_line: Illegal line number in intermediate file: %ld\n",
328 lineno = new_line_number;
330 fprintf(c_file, "/*# %ld \"%s\"*/\n", lineno, filename);
332 } /* do_p1_set_line */
335 static expptr do_p1_name_pointer (infile)
338 Namep namep = (Namep) NULL;
341 status = p1getd (infile, (long *) &namep);
344 err ("do_p1_name_pointer: Missing pointer at end of file\n");
345 else if (status == 0 || namep == (Namep) NULL)
346 erri ("do_p1_name_pointer: Illegal name pointer in p1 file: '%x'\n",
349 return (expptr) namep;
350 } /* do_p1_name_pointer */
354 static expptr do_p1_const (infile)
357 struct Constblock *c = (struct Constblock *) NULL;
361 status = p1getd (infile, &type);
364 err ("do_p1_const: Missing constant type at end of file\n");
365 else if (status == 0)
366 errl("do_p1_const: Illegal constant type in p1 file: %ld\n", type);
368 status = p1get_const (infile, (int)type, &c);
371 err ("do_p1_const: Missing constant value at end of file\n");
372 c = (struct Constblock *) NULL;
373 } else if (status == 0) {
374 err ("do_p1_const: Illegal constant value in p1 file\n");
375 c = (struct Constblock *) NULL;
382 static expptr do_p1_literal (infile)
389 status = p1getd (infile, &memno);
392 err ("do_p1_literal: Missing memno at end of file");
393 else if (status == 0)
394 err ("do_p1_literal: Missing memno in p1 file");
396 struct Literal *litp, *lastlit;
398 addrp = ALLOC (Addrblock);
399 addrp -> tag = TADDR;
400 addrp -> vtype = TYUNKNOWN;
401 addrp -> Field = NULL;
403 lastlit = litpool + nliterals;
404 for (litp = litpool; litp < lastlit; litp++)
405 if (litp -> litnum == memno) {
406 addrp -> vtype = litp -> littype;
407 *((union Constant *) &(addrp -> user)) =
408 *((union Constant *) &(litp -> litval));
410 } /* if litp -> litnum == memno */
412 addrp -> memno = memno;
413 addrp -> vstg = STGMEMNO;
414 addrp -> uname_tag = UNAM_CONST;
417 return (expptr) addrp;
418 } /* do_p1_literal */
421 static void do_p1_label (infile, outfile)
422 FILE *infile, *outfile;
427 struct Labelblock *L;
430 status = p1getd (infile, &stateno);
433 err ("do_p1_label: Missing label at end of file");
434 else if (status == 0)
435 err ("do_p1_label: Missing label in p1 file ");
436 else if (stateno < 0) { /* entry */
437 margin_printf(outfile, "\n%s:\n", user_label(stateno));
441 L = labeltab + stateno;
448 margin_printf(outfile, fmt, user_label(L->stateno));
454 static void do_p1_asgoto (infile, outfile)
455 FILE *infile, *outfile;
459 expr = do_format (infile, outfile);
460 out_asgoto (outfile, expr);
465 static void do_p1_goto (infile, outfile)
466 FILE *infile, *outfile;
472 status = p1getd (infile, &stateno);
475 err ("do_p1_goto: Missing goto label at end of file");
476 else if (status == 0)
477 err ("do_p1_goto: Missing goto label in p1 file");
479 nice_printf (outfile, "goto %s;\n", user_label (stateno));
484 static void do_p1_if (infile, outfile)
485 FILE *infile, *outfile;
490 cond = do_format (infile, outfile);
491 } while (cond == ENULL);
493 out_if (outfile, cond);
497 static void do_p1_else (outfile)
504 static void do_p1_elif (infile, outfile)
505 FILE *infile, *outfile;
510 cond = do_format (infile, outfile);
511 } while (cond == ENULL);
513 elif_out (outfile, cond);
516 static void do_p1_endif (outfile)
523 static void do_p1_endelse (outfile)
526 end_else_out (outfile);
527 } /* do_p1_endelse */
530 static expptr do_p1_addr (infile, outfile)
531 FILE *infile, *outfile;
533 Addrp addrp = (Addrp) NULL;
536 status = p1getn (infile, sizeof (struct Addrblock), (char **) &addrp);
539 err ("do_p1_addr: Missing Addrp at end of file");
540 else if (status == 0)
541 err ("do_p1_addr: Missing Addrp in p1 file");
542 else if (addrp == (Addrp) NULL)
543 err ("do_p1_addr: Null addrp in p1 file");
544 else if (addrp -> tag != TADDR)
545 erri ("do_p1_addr: bad tag in p1 file '%d'", addrp -> tag);
547 addrp -> vleng = do_format (infile, outfile);
548 addrp -> memoffset = do_format (infile, outfile);
551 return (expptr) addrp;
556 static void do_p1_subr_ret (infile, outfile)
557 FILE *infile, *outfile;
561 nice_printf (outfile, "return ");
562 retval = do_format (infile, outfile);
565 expr_out (outfile, retval);
567 nice_printf (outfile, ";\n");
568 } /* do_p1_subr_ret */
572 static void do_p1_comp_goto (infile, outfile)
573 FILE *infile, *outfile;
578 index = do_format (infile, outfile);
580 if (index == ENULL) {
581 err ("do_p1_comp_goto: no expression for computed goto");
583 } /* if index == ENULL */
585 labels = do_format (infile, outfile);
587 if (labels && labels -> tag != TLIST)
588 erri ("do_p1_comp_goto: expected list, got tag '%d'", labels -> tag);
590 compgoto_out (outfile, index, labels);
591 } /* do_p1_comp_goto */
594 static void do_p1_for (infile, outfile)
595 FILE *infile, *outfile;
597 expptr init, test, inc;
599 init = do_format (infile, outfile);
600 test = do_format (infile, outfile);
601 inc = do_format (infile, outfile);
603 out_for (outfile, init, test, inc);
606 static void do_p1_end_for (outfile)
609 out_end_for (outfile);
610 } /* do_p1_end_for */
614 do_p1_fortran(infile, outfile)
615 FILE *infile, *outfile;
617 char buf[P1_STMTBUFSIZE];
618 if (!p1gets(infile, buf, P1_STMTBUFSIZE))
620 /* bypass nice_printf nonsense */
621 fprintf(outfile, "/*< %s >*/\n", buf+1); /* + 1 to skip by '$' */
625 static expptr do_p1_expr (infile, outfile)
626 FILE *infile, *outfile;
630 struct Exprblock *result = (struct Exprblock *) NULL;
632 status = p1getd (infile, &opcode);
635 err ("do_p1_expr: Missing expr opcode at end of file");
636 else if (status == 0)
637 err ("do_p1_expr: Missing expr opcode in p1 file");
640 status = p1getd (infile, &type);
643 err ("do_p1_expr: Missing expr type at end of file");
644 else if (status == 0)
645 err ("do_p1_expr: Missing expr type in p1 file");
646 else if (opcode == 0)
649 result = ALLOC (Exprblock);
651 result -> tag = TEXPR;
652 result -> vtype = type;
653 result -> opcode = opcode;
654 result -> vleng = do_format (infile, outfile);
656 if (is_unary_op (opcode))
657 result -> leftp = do_format (infile, outfile);
658 else if (is_binary_op (opcode)) {
659 result -> leftp = do_format (infile, outfile);
660 result -> rightp = do_format (infile, outfile);
662 errl("do_p1_expr: Illegal opcode %ld", opcode);
666 return (expptr) result;
670 static expptr do_p1_ident(infile)
677 addrp = ALLOC (Addrblock);
678 addrp -> tag = TADDR;
680 status = p1getd (infile, &vtype);
682 err ("do_p1_ident: Missing identifier type at end of file\n");
683 else if (status == 0 || vtype < 0 || vtype >= NTYPES)
684 errl("do_p1_ident: Bad type in intermediate file: %ld\n", vtype);
686 addrp -> vtype = vtype;
688 status = p1getd (infile, &vstg);
690 err ("do_p1_ident: Missing identifier storage at end of file\n");
691 else if (status == 0 || vstg < 0 || vstg > STGNULL)
692 errl("do_p1_ident: Bad storage in intermediate file: %ld\n", vtype);
694 addrp -> vstg = vstg;
696 status = p1gets(infile, addrp->user.ident, IDENT_LEN);
699 err ("do_p1_ident: Missing ident string at end of file");
700 else if (status == 0)
701 err ("do_p1_ident: Missing ident string in intermediate file");
702 addrp->uname_tag = UNAM_IDENT;
703 return (expptr) addrp;
706 static expptr do_p1_charp(infile)
714 addrp = ALLOC (Addrblock);
715 addrp -> tag = TADDR;
717 status = p1getd (infile, &vtype);
719 err ("do_p1_ident: Missing identifier type at end of file\n");
720 else if (status == 0 || vtype < 0 || vtype >= NTYPES)
721 errl("do_p1_ident: Bad type in intermediate file: %ld\n", vtype);
723 addrp -> vtype = vtype;
725 status = p1getd (infile, &vstg);
727 err ("do_p1_ident: Missing identifier storage at end of file\n");
728 else if (status == 0 || vstg < 0 || vstg > STGNULL)
729 errl("do_p1_ident: Bad storage in intermediate file: %ld\n", vtype);
731 addrp -> vstg = vstg;
733 status = p1gets(infile, buf, (int)sizeof(buf));
736 err ("do_p1_ident: Missing charp ident string at end of file");
737 else if (status == 0)
738 err ("do_p1_ident: Missing charp ident string in intermediate file");
739 addrp->uname_tag = UNAM_CHARP;
740 addrp->user.Charp = strcpy(mem(strlen(buf)+1,0), buf);
741 return (expptr) addrp;
745 static expptr do_p1_extern (infile)
750 addrp = ALLOC (Addrblock);
755 addrp->vstg = STGEXT;
756 addrp->uname_tag = UNAM_EXTERN;
757 status = p1getd (infile, &(addrp -> memno));
759 err ("do_p1_extern: Missing memno at end of file");
760 else if (status == 0)
761 err ("do_p1_extern: Missing memno in intermediate file");
762 if (addrp->vtype = extsymtab[addrp->memno].extype)
763 addrp->vclass = CLPROC;
766 return (expptr) addrp;
771 static expptr do_p1_head (infile, outfile)
772 FILE *infile, *outfile;
779 status = p1getd (infile, &class);
781 err ("do_p1_head: missing header class at end of file");
782 else if (status == 0)
783 err ("do_p1_head: missing header class in p1 file");
785 status = p1gets (infile, storage, (int)sizeof(storage));
786 if (status == EOF || status == 0)
790 if (class == CLPROC || class == CLMAIN) {
794 lengths = length_comp(entries, add_n_);
796 if (!add_n_ && protofile && class != CLMAIN)
797 protowrite(protofile, proctype, storage, entries, lengths);
800 nice_printf (outfile, "/* Main program */ ");
802 nice_printf(outfile, "%s ", multitype ? "VOID"
803 : c_type_decl(proctype, 1));
805 nice_printf(outfile, add_n_ ? "%s0_" : "%s", storage);
807 listargs(outfile, entries, add_n_, lengths);
808 nice_printf (outfile, "\n");
810 list_arg_types (outfile, entries, lengths, add_n_, "\n");
811 nice_printf (outfile, "{\n");
814 strcpy(this_proc_name, storage);
815 list_decls (outfile);
817 } else if (class == CLBLOCK)
820 errl("do_p1_head: got class %ld", class);
826 static expptr do_p1_list (infile, outfile)
827 FILE *infile, *outfile;
829 long tag, type, count;
833 status = p1getd (infile, &tag);
835 err ("do_p1_list: missing list tag at end of file");
836 else if (status == 0)
837 err ("do_p1_list: missing list tag in p1 file");
839 status = p1getd (infile, &type);
841 err ("do_p1_list: missing list type at end of file");
842 else if (status == 0)
843 err ("do_p1_list: missing list type in p1 file");
845 status = p1getd (infile, &count);
847 err ("do_p1_list: missing count at end of file");
848 else if (status == 0)
849 err ("do_p1_list: missing count in p1 file");
853 result = (expptr) ALLOC (Listblock);
858 result -> listblock.vtype = type;
860 /* Assume there will be enough data */
863 pointer = result->listblock.listp =
864 mkchain((char *)do_format(infile, outfile), CHNULL);
867 mkchain((char *)do_format(infile, outfile), CHNULL);
868 pointer = pointer -> nextp;
869 } /* while (count--) */
877 chainp length_comp(e, add_n) /* get lengths of characters args */
878 struct Entrypoint *e;
887 extern int init_ac[TYSUBR+1];
889 args = args1 = add_n ? allargs : e->arglist;
891 for (lengths = NULL; args; args = args -> nextp)
892 if (arg = (Namep)args->datap) {
893 if (arg->vclass == CLUNKNOWN)
895 if (arg->vtype == TYCHAR && arg->vclass != CLPROC) {
896 lengths = mkchain((char *)arg, lengths);
900 if (!add_n && (np = e->enamep)) {
901 /* one last check -- by now we know all we ever will
902 * about external args...
904 save_argtypes(e->arglist, &e->entryname->arginfo,
905 &np->arginfo, 0, np->fvarname, STGEXT, nchargs,
907 at = e->entryname->arginfo;
908 a = at->atypes + init_ac[np->vtype];
909 for(; args1; a++, args1 = args1->nextp) {
911 if (arg = (Namep)args1->datap)
912 switch(arg->vclass) {
916 a->type = TYUNKNOWN + 200;
923 return revchain(lengths);
926 void listargs(outfile, entryp, add_n_, lengths)
928 struct Entrypoint *entryp;
937 nice_printf (outfile, "(");
940 nice_printf(outfile, "n__");
945 args = entryp->arglist;
949 nice_printf(outfile, ", ret_val");
953 else if (ONEOF(proctype, MSKCOMPLEX|MSKCHAR))
955 s = xretslot[proctype]->user.ident;
956 nice_printf(outfile, did_one ? ", %s" : "%s",
957 *s == '(' /*)*/ ? "r_v" : s);
959 if (proctype == TYCHAR)
960 nice_printf (outfile, ", ret_val_len");
962 for (; args; args = args -> nextp)
963 if (arg = (Namep)args->datap) {
964 nice_printf (outfile, "%s", did_one ? ", " : "");
965 out_name (outfile, arg);
969 for (args = lengths; args; args = args -> nextp)
970 nice_printf(outfile, ", %s",
971 new_arg_length((Namep)args->datap));
972 nice_printf (outfile, ")");
976 void list_arg_types(outfile, entryp, lengths, add_n_, finalnl)
978 struct Entrypoint *entryp;
984 int last_type = -1, last_class = -1;
985 int did_one = 0, done_one, is_ext;
986 char *s, *sep = "", *sep1;
988 if (outfile == (FILE *) NULL) {
989 err ("list_arg_types: null output file");
991 } else if (entryp == (struct Entrypoint *) NULL) {
992 err ("list_arg_types: null procedure entry pointer");
999 nice_printf(outfile, "(" /*)*/);
1005 args = entryp->arglist;
1007 nice_printf(outfile, "int n__");
1013 nice_printf(outfile, "%sMultitype *ret_val", sep);
1017 else if (ONEOF (proctype, MSKCOMPLEX|MSKCHAR)) {
1018 s = xretslot[proctype]->user.ident;
1019 nice_printf(outfile, "%s%s *%s", sep, c_type_decl(proctype, 0),
1020 *s == '(' /*)*/ ? "r_v" : s);
1023 if (proctype == TYCHAR)
1024 nice_printf (outfile, "%sftnlen ret_val_len", sep);
1025 } /* if ONEOF proctype */
1026 for (; args; args = args -> nextp) {
1027 Namep arg = (Namep) args->datap;
1029 /* Scalars are passed by reference, and arrays will have their lower bound
1030 adjusted, so nearly everything is printed with a star in front. The
1031 exception is character lengths, which are passed by value. */
1034 int type = arg -> vtype, class = arg -> vclass;
1036 if (class == CLPROC)
1038 type = Castargs ? TYUNKNOWN : TYSUBR;
1039 else if (type == TYREAL && forcedouble && !Castargs)
1042 if (type == last_type && class == last_class && did_one)
1043 nice_printf (outfile, ", ");
1045 if ((is_ext = class == CLPROC) && Castargs)
1046 nice_printf(outfile, "%s%s ", sep,
1047 usedcasts[type] = casttypes[type]);
1049 nice_printf(outfile, "%s%s ", sep,
1050 c_type_decl(type, is_ext));
1051 if (class == CLPROC)
1053 out_name(outfile, arg);
1055 nice_printf(outfile, "(*");
1056 out_name(outfile, arg);
1057 nice_printf(outfile, ") %s", parens);
1060 nice_printf (outfile, "*");
1061 out_name (outfile, arg);
1069 } /* for args = entryp -> arglist */
1071 for (args = lengths; args; args = args -> nextp)
1072 nice_printf(outfile, "%sftnlen %s", sep,
1073 new_arg_length((Namep)args->datap));
1075 nice_printf (outfile, ";\n");
1077 nice_printf(outfile,
1078 /*((*/ sep != sep1 && Ansi == 1 ? "void)%s" : ")%s",
1080 } /* list_arg_types */
1083 write_formats(outfile)
1086 register struct Labelblock *lp;
1090 for(lp = labeltab ; lp < highlabtab ; ++lp)
1091 if (lp->fmtlabused) {
1094 nice_printf(outfile, "/* Format strings */\n");
1096 nice_printf(outfile, "static char fmt_%ld[] = \"",
1098 if (!(fs = lp->fmtstring))
1100 nice_printf(outfile, "%s\";\n", fs);
1103 nice_printf(outfile, "\n");
1107 write_ioblocks(outfile)
1110 register iob_data *L;
1111 register char *f, **s, *sep;
1113 nice_printf(outfile, "/* Fortran I/O blocks */\n");
1114 L = iob_list = (iob_data *)revchain((chainp)iob_list);
1116 nice_printf(outfile, "static %s %s = { ",
1119 for(s = L->fields; f = *s; s++) {
1121 nice_printf(outfile, sep);
1123 if (*f == '"') { /* kludge */
1124 nice_printf(outfile, "\"");
1125 nice_printf(outfile, "%s\"", f+1);
1128 nice_printf(outfile, "%s", f);
1130 nice_printf(outfile, " };\n");
1133 nice_printf(outfile, "\n\n");
1137 write_assigned_fmts(outfile)
1144 cp = assigned_fmts = revchain(assigned_fmts);
1145 nice_printf(outfile, "/* Assigned format variables */\nchar ");
1147 np = (Namep)cp->datap;
1149 nice_printf(outfile, ", ");
1151 nice_printf(outfile, "*%s_fmt", np->fvarname);
1153 while(cp = cp->nextp);
1154 nice_printf(outfile, ";\n\n");
1161 static char buf[64];
1162 register char *t = buf;
1164 while(*t++ = (c = *s++) >= 'a' && c <= 'z' ? c + 'A' - 'a' : c);
1169 /* This routine creates static structures representing a namelist.
1170 Declarations of the namelist and related structures are:
1175 ftnlen *dims; /* laid out as struct dimensions below *//*
1178 typedef struct Vardesc Vardesc;
1188 ftnlen numberofdimensions;
1189 ftnlen numberofelements
1191 ftnlen span[numberofdimensions-1];
1194 If dims is not null, then the corner element of the array is at
1195 addr. However, the element with subscripts (i1,...,in) is at
1196 addr + sizeoftype * (i1+span[0]*(i2+span[1]*...) - dimp->baseoffset)
1200 write_namelists(nmch, outfile)
1205 struct Hashentry *entry;
1206 struct Dimblock *dimp;
1212 nice_printf(outfile, "/* Namelist stuff */\n\n");
1213 for (entry = hashtab; entry < lasthash; ++entry) {
1214 if (!(v = entry->varp) || !v->vnamelist)
1218 if (dimp = v->vdim) {
1220 nice_printf(outfile,
1221 "static ftnlen %s_dims[] = { %d, %ld, %ld",
1223 dimp->nelt->constblock.Const.ci,
1224 dimp->baseoffset->constblock.Const.ci);
1225 for(i = 0, --nd; i < nd; i++)
1226 nice_printf(outfile, ", %ld",
1227 dimp->dims[i].dimsize->constblock.Const.ci);
1228 nice_printf(outfile, " };\n");
1230 nice_printf(outfile, "static Vardesc %s_dv = { \"%s\", %s",
1231 name, to_upper(name),
1232 type == TYCHAR ? "" : dimp ? "(char *)" : "(char *)&");
1233 out_name(outfile, v);
1234 nice_printf(outfile, dimp ? ", %s_dims" : ", (ftnlen *)0", name);
1235 nice_printf(outfile, ", %ld };\n",
1236 type != TYCHAR ? (long)type
1237 : -v->vleng->constblock.Const.ci);
1241 var = (Namep)nmch->datap;
1242 name = var->cvarname;
1243 nice_printf(outfile, "\nstatic Vardesc *%s_vl[] = ", name);
1246 for(q = var->varxptr.namelist ; q ; q = q->nextp) {
1247 v = (Namep)q->datap;
1251 nice_printf(outfile, "%s &%s_dv", comma, v->cvarname);
1254 nice_printf(outfile, " };\n");
1255 nice_printf(outfile,
1256 "static Namelist %s = { \"%s\", %s_vl, %d };\n",
1257 name, to_upper(name), name, i);
1259 while(nmch = nmch->nextp);
1260 nice_printf(outfile, "\n");
1263 /* fixextype tries to infer from usage in previous procedures
1264 the type of an external procedure declared
1265 external and passed as an argument but never typed or invoked.
1274 extern void changedtype();
1277 e = &extsymtab[var->vardesc.varno];
1278 if ((type1 = e->extype) && type == TYUNKNOWN)
1279 return var->vtype = type1;
1281 if (e->exused && type != type1)
1289 list_decls (outfile)
1292 extern chainp used_builtins;
1293 extern struct Hashentry *hashtab;
1294 extern ftnint wr_char_len();
1295 struct Hashentry *entry;
1296 int write_header = 1;
1297 int last_class = -1, last_stg = -1;
1299 int Alias, Define, did_one, last_type, type;
1300 extern int def_equivs, useauto;
1301 extern chainp new_vars; /* Compiler-generated locals */
1302 chainp namelists = 0;
1304 long lineno_save = lineno;
1305 int useauto1 = useauto && !saveall;
1309 lineno = old_lineno;
1311 /* First write out the statically initialized data */
1314 list_init_data(&initfile, initfname, outfile);
1316 /* Next come formats */
1317 write_formats(outfile);
1319 /* Now write out the system-generated identifiers */
1321 if (new_vars || nequiv) {
1322 chainp args, next_var, this_var;
1323 chainp nv[TYVOID], nv1[TYVOID];
1328 /* zap unused dimension variables */
1330 for(args = allargs; args; args = args->nextp) {
1331 arg = (Namep)args->datap;
1332 if (this_var = arg->vlastdim) {
1333 frexpr((tagptr)this_var->datap);
1334 this_var->datap = 0;
1338 /* sort new_vars by type, skipping entries just zapped */
1340 for(i = TYADDR; i < TYVOID; i++)
1342 for(this_var = new_vars; this_var; this_var = next_var) {
1343 next_var = this_var->nextp;
1344 if (Var = (Addrp)this_var->datap) {
1345 if (!(this_var->nextp = nv[j = Var->vtype]))
1350 this_var->nextp = 0;
1355 for(i = TYVOID; --i >= TYADDR;)
1356 if (this_var = nv[i]) {
1357 nv1[i]->nextp = new_vars;
1358 new_vars = this_var;
1361 /* write the declarations */
1366 for (this_var = new_vars; this_var; this_var = this_var -> nextp) {
1367 Var = (Addrp) this_var->datap;
1369 if (Var == (Addrp) NULL)
1370 err ("list_decls: null variable");
1371 else if (Var -> tag != TADDR)
1372 erri ("list_decls: bad tag on new variable '%d'",
1375 type = nv_type (Var);
1376 if (Var->vstg == STGINIT
1377 || Var->uname_tag == UNAM_IDENT
1378 && *Var->user.ident == ' '
1382 nice_printf (outfile, "/* System generated locals */\n");
1384 if (last_type == type && did_one)
1385 nice_printf (outfile, ", ");
1388 nice_printf (outfile, ";\n");
1389 nice_printf (outfile, "%s ",
1390 c_type_decl (type, Var -> vclass == CLPROC));
1393 /* Character type is really a string type. Put out a '*' for parameters
1394 with unknown length and functions returning character */
1396 if (Var -> vtype == TYCHAR && (!ISICON ((Var -> vleng))
1397 || Var -> vclass == CLPROC))
1398 nice_printf (outfile, "*");
1400 write_nv_ident(outfile, (Addrp)this_var->datap);
1401 if (Var -> vtype == TYCHAR && Var->vclass != CLPROC &&
1402 ISICON((Var -> vleng))
1403 && (i = Var->vleng->constblock.Const.ci) > 0)
1404 nice_printf (outfile, "[%d]", i);
1407 last_type = nv_type (Var);
1408 } /* for this_var */
1410 /* Handle the uninitialized equivalences */
1412 do_uninit_equivs (outfile, &did_one);
1415 nice_printf (outfile, ";\n\n");
1418 /* Write out builtin declarations */
1420 if (used_builtins) {
1427 nice_printf (outfile, "/* Builtin functions */");
1429 for (cp = used_builtins; cp; cp = cp -> nextp) {
1430 Addrp e = (Addrp)cp->datap;
1432 switch(type = e->vtype) {
1435 /* if (forcedouble || e->dbl_builtin) */
1436 /* libF77 currently assumes everything double */
1445 ctype = c_type_decl(type, 0);
1448 if (did_one && last_type == type)
1449 nice_printf(outfile, ", ");
1451 nice_printf(outfile, "%s\n%s ", did_one ? ";" : "", ctype);
1453 extern_out(outfile, es = &extsymtab[e -> memno]);
1454 proto(outfile, es->arginfo, es->fextname);
1457 } /* for cp = used_builtins */
1459 nice_printf (outfile, ";\n\n");
1460 } /* if used_builtins */
1463 for (entry = hashtab; entry < lasthash; ++entry) {
1464 var = entry -> varp;
1467 int procclass = var -> vprocclass;
1468 char *comment = NULL;
1469 int stg = var -> vstg;
1470 int class = var -> vclass;
1471 type = var -> vtype;
1473 if (ONEOF(stg, M(STGARG)|M(STGLENG)|M(STGINIT)))
1476 if (useauto1 && stg == STGBSS && !var->vsave)
1485 extsymtab[var->vardesc.varno].extype = type;
1491 err ("list_decls: unknown procedure class");
1494 if (stg == STGUNKNOWN) {
1496 "%.64s declared EXTERNAL but never used.",
1498 /* to retain names declared EXTERNAL */
1499 /* but not referenced, change
1500 /* "continue" to "stg = STGEXT" */
1504 type = fixexttype(var);
1508 /* declared but never used */
1514 namelists = mkchain((char *)var, namelists);
1517 erri("list_decls: can't handle class '%d' yet",
1519 Fatal(var->fvarname);
1523 /* Might be equivalenced to a common. If not, don't process */
1524 if (stg == STGCOMMON && !var->vcommequiv)
1527 /* Only write the header if system-generated locals, builtins, or
1528 uninitialized equivs were already output */
1530 if (write_header == 1 && (new_vars || nequiv || used_builtins)
1531 && oneof_stg ( var, stg,
1532 M(STGBSS)|M(STGEXT)|M(STGAUTO)|M(STGCOMMON)|M(STGEQUIV))) {
1533 nice_printf (outfile, "/* Local variables */\n");
1538 Alias = oneof_stg(var, stg, M(STGEQUIV)|M(STGCOMMON));
1539 if (Define = (Alias && def_equivs)) {
1541 nice_printf(outfile, ";\n");
1542 def_start(outfile, var->cvarname, CNULL, "(");
1545 else if (type == last_type && class == last_class &&
1546 stg == last_stg && !write_header)
1547 nice_printf (outfile, ", ");
1549 if (!write_header && ONEOF(stg, M(STGBSS)|
1550 M(STGEXT)|M(STGAUTO)|M(STGEQUIV)|M(STGCOMMON)))
1551 nice_printf (outfile, ";\n");
1556 /* Part of the argument list, don't write them out
1558 continue; /* Go back to top of the loop */
1562 nice_printf (outfile, "static ");
1565 nice_printf (outfile, "extern ");
1571 /* Don't want to touch the initialized data, that will
1572 be handled elsewhere. Unknown data have
1573 already been complained about, so skip them */
1576 erri("list_decls: can't handle storage class %d",
1581 if (type == TYCHAR && halign && class != CLPROC
1582 && ISICON(var->vleng)) {
1583 nice_printf(outfile, "struct { %s fill; char val",
1585 x = wr_char_len(outfile, var->vdim,
1586 var->vleng->constblock.Const.ci, 1);
1588 nice_printf(outfile, "; char fill2[%ld]",
1590 nice_printf(outfile, "; } %s_st;\n", var->cvarname);
1591 def_start(outfile, var->cvarname, CNULL, var->cvarname);
1592 ind_printf(0, outfile, "_st.val\n");
1597 nice_printf(outfile, "%s ",
1598 c_type_decl(type, class == CLPROC));
1601 /* Character type is really a string type. Put out a '*' for variable
1602 length strings, and also for equivalences */
1604 if (type == TYCHAR && class != CLPROC
1605 && (!var->vleng || !ISICON (var -> vleng))
1606 || oneof_stg(var, stg, M(STGEQUIV)|M(STGCOMMON)))
1607 nice_printf (outfile, "*%s", var->cvarname);
1609 nice_printf (outfile, "%s", var->cvarname);
1610 if (class == CLPROC)
1611 proto(outfile, var->arginfo, var->fvarname);
1612 else if (type == TYCHAR && ISICON ((var -> vleng)))
1613 wr_char_len(outfile, var->vdim,
1614 (int)var->vleng->constblock.Const.ci, 0);
1615 else if (var -> vdim &&
1616 !oneof_stg (var, stg, M(STGEQUIV)|M(STGCOMMON)))
1617 comment = wr_ardecls(outfile, var->vdim, 1L);
1621 nice_printf (outfile, "%s", comment);
1624 char *amp, *lp, *name, *rp;
1625 char *equiv_name ();
1626 ftnint voff = var -> voffset;
1627 int et0, expr_type, k;
1629 struct Equivblock *eb;
1632 /* We DON'T want to use oneof_stg here, because we need to distinguish
1635 if (stg == STGEQUIV) {
1636 name = equiv_name(k = var->vardesc.varno, CNULL);
1649 E = &extsymtab[var->vardesc.varno];
1650 sprintf(name = buf, "%s%d", E->cextname, E->curno);
1657 nice_printf (outfile, " = ");
1660 switch((int)(voff % k)) {
1666 case SZSHORT+SZLONG:
1667 expr_type = TYSHORT;
1679 if (expr_type == type) {
1681 if (et0 == -1 && !voff)
1688 nice_printf(outfile, "(%s *)", c_type_decl(type, 0));
1691 /* Now worry about computing the offset */
1694 if (expr_type == et0)
1695 nice_printf (outfile, "%s%s + %ld%s",
1696 lp, name, voff, rp);
1698 nice_printf(outfile, "%s(%s *)%s%s + %ld%s", lp,
1699 c_type_decl (expr_type, 0), amp,
1702 nice_printf(outfile, "%s%s", amp, name);
1703 /* Always put these at the end of the line */
1704 last_type = last_class = last_stg = -1;
1707 ind_printf(0, outfile, ")\n");
1717 } /* for (entry = hashtab */
1720 nice_printf (outfile, ";\n\n");
1721 else if (write_header == 2)
1722 nice_printf(outfile, "\n");
1724 /* Next, namelists, which may reference equivs */
1727 write_namelists(namelists = revchain(namelists), outfile);
1728 frchain(&namelists);
1731 /* Finally, ioblocks (which may reference equivs and namelists) */
1733 write_ioblocks(outfile);
1735 write_assigned_fmts(outfile);
1736 lineno = lineno_save;
1739 do_uninit_equivs (outfile, did_one)
1744 struct Equivblock *eqv, *lasteqv = eqvclass + nequiv;
1745 int k, last_type = -1, t;
1747 for (eqv = eqvclass; eqv < lasteqv; eqv++)
1748 if (!eqv -> eqvinit && eqv -> eqvtop != eqv -> eqvbottom) {
1750 nice_printf (outfile, "/* System generated locals */\n");
1753 nice_printf (outfile, ", ");
1756 nice_printf (outfile, ";\n");
1757 nice_printf (outfile, "static %s ", c_type_decl(t, 0));
1760 nice_printf(outfile, "%s", equiv_name((int)(eqv - eqvclass), CNULL));
1761 nice_printf(outfile, "[%ld]",
1762 (eqv->eqvtop - eqv->eqvbottom + k - 1) / k);
1765 } /* if !eqv -> eqvinit */
1766 } /* do_uninit_equivs */
1769 /* wr_ardecls -- Writes the brackets and size for an array
1770 declaration. Because of the inner workings of the compiler,
1771 multi-dimensional arrays get mapped directly into a one-dimensional
1772 array, so we have to compute the size of the array here. When the
1773 dimension is greater than 1, a string comment about the original size
1776 char *wr_ardecls(outfile, dimp, size)
1778 struct Dimblock *dimp;
1782 static char buf[1000];
1784 if (dimp == (struct Dimblock *) NULL)
1787 sprintf(buf, "\t/* was "); /* would like to say k = sprintf(...), but */
1788 k = strlen(buf); /* BSD doesn't return char transmitted count */
1790 for (i = 0; i < dimp -> ndim; i++) {
1791 expptr this_size = dimp -> dims[i].dimsize;
1793 if (!ISICON (this_size))
1794 err ("wr_ardecls: nonconstant array size");
1796 size *= this_size -> constblock.Const.ci;
1797 sprintf(buf+k, "[%ld]", this_size -> constblock.Const.ci);
1798 k += strlen(buf+k); /* BSD prevents combining this with prev stmt */
1802 nice_printf (outfile, "[%ld]", size);
1803 strcat(buf+k, " */");
1805 return (i > 1) ? buf : NULL;
1810 /* ----------------------------------------------------------------------
1812 The following routines read from the p1 intermediate file. If
1813 that format changes, only these routines need be changed
1815 ---------------------------------------------------------------------- */
1817 static int get_p1_token (infile)
1820 int token = P1_UNKNOWN;
1822 /* NOT PORTABLE!! */
1824 if (fscanf (infile, "%d", &token) == EOF)
1827 /* Skip over the ": " */
1829 if (getc (infile) != '\n')
1833 } /* get_p1_token */
1837 /* Returns a (null terminated) string from the input file */
1839 static int p1gets (fp, str, size)
1850 if ((c = getc (fp)) != ' ')
1853 if (fgets (str, size, fp)) {
1856 str[size - 1] = '\0';
1857 length = strlen (str);
1859 /* Get rid of the newline */
1861 if (str[length - 1] == '\n')
1862 str[length - 1] = '\0';
1865 } else if (feof (fp))
1872 static int p1get_const (infile, type, resultp)
1875 struct Constblock **resultp;
1878 struct Constblock *result;
1880 if (type != TYCHAR) {
1881 *resultp = result = ALLOC(Constblock);
1882 result -> tag = TCONST;
1883 result -> vtype = type;
1890 status = p1getd (infile, &(result -> Const.ci));
1894 status = p1getf(infile, &result->Const.cds[0]);
1899 status = p1getf(infile, &result->Const.cds[0]);
1900 if (status && status != EOF)
1901 status = p1getf(infile, &result->Const.cds[1]);
1905 status = fscanf(infile, "%lx", resultp);
1908 erri ("p1get_const: bad constant type '%d'", type);
1916 static int p1getd (infile, result)
1920 return fscanf (infile, "%ld", result);
1924 p1getf(infile, result)
1932 k = fscanf (infile, "%s", buf);
1936 strcpy(*result = mem(strlen(buf)+1,0), buf);
1940 static int p1getn (infile, count, result)
1947 extern ptr ckalloc ();
1949 bufptr = (char *) ckalloc (count);
1954 for (; !feof (infile) && count > 0; count--)
1955 *bufptr++ = getc (infile);
1957 return feof (infile) ? EOF : 1;
1961 proto(outfile, at, fname)
1971 extern void bad_atypes();
1974 /* Correct types that we learn on the fly, e.g.
1975 subroutine gotcha(foo)
1977 call zap(...,foo,...)
1980 atypes = at->atypes;
1982 for(i = 0; i++ < n; atypes++) {
1983 if (!(cp = atypes->cp))
1987 np = (Namep)cp->datap;
1989 if (np->vclass == CLPROC) {
1990 if (!np->vimpltype && k)
1994 j = TYUNKNOWN + 200;
2001 || j == 200 && k >= 200)
2004 bad_atypes(at,fname,i,j,k,""," and");
2008 while(cp = cp->nextp);
2010 frchain(&atypes->cp);
2015 nice_printf(outfile, parens);
2019 if (!at || (n = at->nargs) < 0) {
2020 nice_printf(outfile, Ansi == 1 ? "()" : "(...)");
2025 nice_printf(outfile, Ansi == 1 ? "(void)" : "()");
2029 atypes = at->atypes;
2030 nice_printf(outfile, "(");
2032 for(; --n >= 0; atypes++) {
2035 nice_printf(outfile, "%schar **", comma);
2036 else if (k >= 200) {
2038 nice_printf(outfile, "%s%s", comma,
2039 usedcasts[k] = casttypes[k]);
2042 nice_printf(outfile,
2043 k == TYCHAR + 100 ? "%s%s *" : "%s%s",
2044 comma, c_type_decl(k-100, 0));
2046 nice_printf(outfile, "%s%s *", comma,
2050 nice_printf(outfile, ")");
2054 protowrite(protofile, type, name, e, lengths)
2057 struct Entrypoint *e;
2060 extern char used_rets[];
2062 nice_printf(protofile, "extern %s %s", protorettypes[type], name);
2063 list_arg_types(protofile, e, lengths, 0, ";\n");
2064 used_rets[type] = 1;
2068 do_p1_1while(outfile)
2072 nice_printf(outfile,
2073 "for(;;) { /* while(complicated condition) */\n" /*}*/ );
2077 nice_printf(outfile, "while(" /*)*/ );
2081 do_p1_2while(infile, outfile)
2082 FILE *infile, *outfile;
2086 test = do_format(infile, outfile);
2088 nice_printf(outfile, "if (!(");
2089 expr_out(outfile, test);
2091 nice_printf(outfile, "))\n\tbreak;\n");
2093 nice_printf(outfile, /*(*/ ") {\n");
2099 do_p1_elseifstart(outfile)
2104 nice_printf(outfile, /*{*/
2105 "} else /* if(complicated condition) */ {\n" /*}*/ );