|
|
1.1 root 1: /****************************************************************
2: Copyright 1990, 1991, 1992, 1993 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: /* 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. */
27:
28: #include "defs.h"
29: #include "p1defs.h"
30: #include "format.h"
31: #include "output.h"
32: #include "names.h"
33: #include "iob.h"
34:
35: int c_output_line_length = DEF_C_LINE_LENGTH;
36:
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 */
42:
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();
55: static void proto();
56: void list_arg_types();
57: chainp length_comp();
58: void listargs();
59: extern chainp assigned_fmts;
60: static char filename[P1_FILENAME_MAX];
61: extern int gflag;
62: int gflag1;
63: extern char *parens;
64:
65: start_formatting ()
66: {
67: FILE *infile;
68: static int wrote_one = 0;
69: extern int usedefsforcommon;
70: extern char *p1_file, *p1_bakfile;
71:
72: this_proc_name[0] = '\0';
73: last_was_label = 0;
74: ei_next = ei_first;
75: wh_next = wh_first;
76:
77: (void) fclose (pass1_file);
78: if ((infile = fopen (p1_file, binread)) == NULL)
79: Fatal("start_formatting: couldn't open the intermediate file\n");
80:
81: if (wrote_one)
82: nice_printf (c_file, "\n");
83:
84: while (!feof (infile)) {
85: expptr this_expr;
86:
87: this_expr = do_format (infile, c_file);
88: if (this_expr) {
89: out_and_free_statement (c_file, this_expr);
90: } /* if this_expr */
91: } /* while !feof infile */
92:
93: (void) fclose (infile);
94:
95: if (last_was_label)
96: nice_printf (c_file, ";\n");
97:
98: prev_tab (c_file);
99: gflag1 = 0;
100: if (this_proc_name[0])
101: nice_printf (c_file, "} /* %s */\n", this_proc_name);
102:
103:
104: /* Write the #undefs for common variable reference */
105:
106: if (usedefsforcommon) {
107: Extsym *ext;
108: int did_one = 0;
109:
110: for (ext = extsymtab; ext < nextext; ext++)
111: if (ext -> extstg == STGCOMMON && ext -> used_here) {
112: ext -> used_here = 0;
113: if (!did_one)
114: nice_printf (c_file, "\n");
115: wr_abbrevs(c_file, 0, ext->extp);
116: did_one = 1;
117: ext -> extp = CHNULL;
118: } /* if */
119:
120: if (did_one)
121: nice_printf (c_file, "\n");
122: } /* if usedefsforcommon */
123:
124: other_undefs(c_file);
125:
126: wrote_one = 1;
127:
128: /* For debugging only */
129:
130: if (debugflag && (pass1_file = fopen (p1_bakfile, binwrite)))
131: if (infile = fopen (p1_file, binread)) {
132: ffilecopy (infile, pass1_file);
133: fclose (infile);
134: fclose (pass1_file);
135: } /* if infile */
136:
137: /* End of "debugging only" */
138:
139: scrub(p1_file); /* optionally unlink */
140:
141: if ((pass1_file = fopen (p1_file, binwrite)) == NULL)
142: err ("start_formatting: couldn't reopen the pass1 file");
143:
144: } /* start_formatting */
145:
146:
147: static void
148: put_semi(outfile)
149: FILE *outfile;
150: {
151: nice_printf (outfile, ";\n");
152: last_was_label = 0;
153: }
154:
155: #define SEM_CHECK(x) if (last_was_label) put_semi(x)
156:
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. */
160:
161: static expptr do_format (infile, outfile)
162: FILE *infile, *outfile;
163: {
164: int token_type, was_c_token;
165: expptr retval = ENULL;
166:
167: token_type = get_p1_token (infile);
168: was_c_token = 1;
169: switch (token_type) {
170: case P1_COMMENT:
171: do_p1_comment (infile, outfile);
172: was_c_token = 0;
173: break;
174: case P1_SET_LINE:
175: do_p1_set_line (infile);
176: was_c_token = 0;
177: break;
178: case P1_FILENAME:
179: p1gets(infile, filename, P1_FILENAME_MAX);
180: was_c_token = 0;
181: break;
182: case P1_NAME_POINTER:
183: retval = do_p1_name_pointer (infile);
184: break;
185: case P1_CONST:
186: retval = do_p1_const (infile);
187: break;
188: case P1_EXPR:
189: retval = do_p1_expr (infile, outfile);
190: break;
191: case P1_IDENT:
192: retval = do_p1_ident(infile);
193: break;
194: case P1_CHARP:
195: retval = do_p1_charp(infile);
196: break;
197: case P1_EXTERN:
198: retval = do_p1_extern (infile);
199: break;
200: case P1_HEAD:
201: gflag1 = 0;
202: retval = do_p1_head (infile, outfile);
203: gflag1 = gflag;
204: break;
205: case P1_LIST:
206: retval = do_p1_list (infile, outfile);
207: break;
208: case P1_LITERAL:
209: retval = do_p1_literal (infile);
210: break;
211: case P1_LABEL:
212: do_p1_label (infile, outfile);
213: /* last_was_label = 1; -- now set in do_p1_label */
214: was_c_token = 0;
215: break;
216: case P1_ASGOTO:
217: do_p1_asgoto (infile, outfile);
218: break;
219: case P1_GOTO:
220: do_p1_goto (infile, outfile);
221: break;
222: case P1_IF:
223: do_p1_if (infile, outfile);
224: break;
225: case P1_ELSE:
226: SEM_CHECK(outfile);
227: do_p1_else (outfile);
228: break;
229: case P1_ELIF:
230: SEM_CHECK(outfile);
231: do_p1_elif (infile, outfile);
232: break;
233: case P1_ENDIF:
234: SEM_CHECK(outfile);
235: do_p1_endif (outfile);
236: break;
237: case P1_ENDELSE:
238: SEM_CHECK(outfile);
239: do_p1_endelse (outfile);
240: break;
241: case P1_ADDR:
242: retval = do_p1_addr (infile, outfile);
243: break;
244: case P1_SUBR_RET:
245: do_p1_subr_ret (infile, outfile);
246: break;
247: case P1_COMP_GOTO:
248: do_p1_comp_goto (infile, outfile);
249: break;
250: case P1_FOR:
251: do_p1_for (infile, outfile);
252: break;
253: case P1_ENDFOR:
254: SEM_CHECK(outfile);
255: do_p1_end_for (outfile);
256: break;
257: case P1_WHILE1START:
258: do_p1_1while(outfile);
259: break;
260: case P1_WHILE2START:
261: do_p1_2while(infile, outfile);
262: break;
263: case P1_PROCODE:
264: procode(outfile);
265: break;
266: case P1_ELSEIFSTART:
267: SEM_CHECK(outfile);
268: do_p1_elseifstart(outfile);
269: break;
270: case P1_FORTRAN:
271: do_p1_fortran(infile, outfile);
272: /* no break; */
273: case P1_EOF:
274: was_c_token = 0;
275: break;
276: case P1_UNKNOWN:
277: Fatal("do_format: Unknown token type in intermediate file");
278: break;
279: default:
280: Fatal("do_format: Bad token type in intermediate file");
281: break;
282: } /* switch */
283:
284: if (was_c_token)
285: last_was_label = 0;
286: return retval;
287: } /* do_format */
288:
289:
290: static void
291: do_p1_comment (infile, outfile)
292: FILE *infile, *outfile;
293: {
294: extern int c_output_line_length, in_comment;
295:
296: char storage[COMMENT_BUFFER_SIZE + 1];
297: int length;
298:
299: if (!p1gets(infile, storage, COMMENT_BUFFER_SIZE + 1))
300: return;
301:
302: length = strlen (storage);
303:
304: gflag1 = 0;
305: in_comment = 1;
306: if (length > c_output_line_length - 6)
307: margin_printf (outfile, "/*%s*/\n", storage);
308: else
309: margin_printf (outfile, length ? "/* %s */\n" : "\n", storage);
310: in_comment = 0;
311: gflag1 = gflag;
312: } /* do_p1_comment */
313:
314: static void
315: do_p1_set_line (infile)
316: FILE *infile;
317: {
318: int status;
319: long new_line_number = -1;
320:
321: status = p1getd (infile, &new_line_number);
322:
323: if (status == EOF)
324: err ("do_p1_set_line: Missing line number at end of file\n");
325: else if (status == 0 || new_line_number == -1)
326: errl("do_p1_set_line: Illegal line number in intermediate file: %ld\n",
327: new_line_number);
328: else {
329: lineno = new_line_number;
330: }
331: } /* do_p1_set_line */
332:
333:
334: static expptr do_p1_name_pointer (infile)
335: FILE *infile;
336: {
337: Namep namep = (Namep) NULL;
338: int status;
339:
340: status = p1getd (infile, (long *) &namep);
341:
342: if (status == EOF)
343: err ("do_p1_name_pointer: Missing pointer at end of file\n");
344: else if (status == 0 || namep == (Namep) NULL)
345: erri ("do_p1_name_pointer: Illegal name pointer in p1 file: '%x'\n",
346: (int) namep);
347:
348: return (expptr) namep;
349: } /* do_p1_name_pointer */
350:
351:
352:
353: static expptr do_p1_const (infile)
354: FILE *infile;
355: {
356: struct Constblock *c = (struct Constblock *) NULL;
357: long type = -1;
358: int status;
359:
360: status = p1getd (infile, &type);
361:
362: if (status == EOF)
363: err ("do_p1_const: Missing constant type at end of file\n");
364: else if (status == 0)
365: errl("do_p1_const: Illegal constant type in p1 file: %ld\n", type);
366: else {
367: status = p1get_const (infile, (int)type, &c);
368:
369: if (status == EOF) {
370: err ("do_p1_const: Missing constant value at end of file\n");
371: c = (struct Constblock *) NULL;
372: } else if (status == 0) {
373: err ("do_p1_const: Illegal constant value in p1 file\n");
374: c = (struct Constblock *) NULL;
375: } /* else */
376: } /* else */
377: return (expptr) c;
378: } /* do_p1_const */
379:
380:
381: static expptr do_p1_literal (infile)
382: FILE *infile;
383: {
384: int status;
385: long memno;
386: Addrp addrp;
387:
388: status = p1getd (infile, &memno);
389:
390: if (status == EOF)
391: err ("do_p1_literal: Missing memno at end of file");
392: else if (status == 0)
393: err ("do_p1_literal: Missing memno in p1 file");
394: else {
395: struct Literal *litp, *lastlit;
396:
397: addrp = ALLOC (Addrblock);
398: addrp -> tag = TADDR;
399: addrp -> vtype = TYUNKNOWN;
400: addrp -> Field = NULL;
401:
402: lastlit = litpool + nliterals;
403: for (litp = litpool; litp < lastlit; litp++)
404: if (litp -> litnum == memno) {
405: addrp -> vtype = litp -> littype;
406: *((union Constant *) &(addrp -> user)) =
407: *((union Constant *) &(litp -> litval));
408: break;
409: } /* if litp -> litnum == memno */
410:
411: addrp -> memno = memno;
412: addrp -> vstg = STGMEMNO;
413: addrp -> uname_tag = UNAM_CONST;
414: } /* else */
415:
416: return (expptr) addrp;
417: } /* do_p1_literal */
418:
419:
420: static void do_p1_label (infile, outfile)
421: FILE *infile, *outfile;
422: {
423: int status;
424: ftnint stateno;
425: char *user_label ();
426: struct Labelblock *L;
427: char *fmt;
428:
429: status = p1getd (infile, &stateno);
430:
431: if (status == EOF)
432: err ("do_p1_label: Missing label at end of file");
433: else if (status == 0)
434: err ("do_p1_label: Missing label in p1 file ");
435: else if (stateno < 0) { /* entry */
436: margin_printf(outfile, "\n%s:\n", user_label(stateno));
437: last_was_label = 1;
438: }
439: else {
440: L = labeltab + stateno;
441: if (L->labused) {
442: fmt = "%s:\n";
443: last_was_label = 1;
444: }
445: else
446: fmt = "/* %s: */\n";
447: margin_printf(outfile, fmt, user_label(L->stateno));
448: } /* else */
449: } /* do_p1_label */
450:
451:
452:
453: static void do_p1_asgoto (infile, outfile)
454: FILE *infile, *outfile;
455: {
456: expptr expr;
457:
458: expr = do_format (infile, outfile);
459: out_asgoto (outfile, expr);
460:
461: } /* do_p1_asgoto */
462:
463:
464: static void do_p1_goto (infile, outfile)
465: FILE *infile, *outfile;
466: {
467: int status;
468: long stateno;
469: char *user_label ();
470:
471: status = p1getd (infile, &stateno);
472:
473: if (status == EOF)
474: err ("do_p1_goto: Missing goto label at end of file");
475: else if (status == 0)
476: err ("do_p1_goto: Missing goto label in p1 file");
477: else {
478: nice_printf (outfile, "goto %s;\n", user_label (stateno));
479: } /* else */
480: } /* do_p1_goto */
481:
482:
483: static void do_p1_if (infile, outfile)
484: FILE *infile, *outfile;
485: {
486: expptr cond;
487:
488: do {
489: cond = do_format (infile, outfile);
490: } while (cond == ENULL);
491:
492: out_if (outfile, cond);
493: } /* do_p1_if */
494:
495:
496: static void do_p1_else (outfile)
497: FILE *outfile;
498: {
499: out_else (outfile);
500: } /* do_p1_else */
501:
502:
503: static void do_p1_elif (infile, outfile)
504: FILE *infile, *outfile;
505: {
506: expptr cond;
507:
508: do {
509: cond = do_format (infile, outfile);
510: } while (cond == ENULL);
511:
512: elif_out (outfile, cond);
513: } /* do_p1_elif */
514:
515: static void do_p1_endif (outfile)
516: FILE *outfile;
517: {
518: endif_out (outfile);
519: } /* do_p1_endif */
520:
521:
522: static void do_p1_endelse (outfile)
523: FILE *outfile;
524: {
525: end_else_out (outfile);
526: } /* do_p1_endelse */
527:
528:
529: static expptr do_p1_addr (infile, outfile)
530: FILE *infile, *outfile;
531: {
532: Addrp addrp = (Addrp) NULL;
533: int status;
534:
535: status = p1getn (infile, (int)sizeof(struct Addrblock), (char **) &addrp);
536:
537: if (status == EOF)
538: err ("do_p1_addr: Missing Addrp at end of file");
539: else if (status == 0)
540: err ("do_p1_addr: Missing Addrp in p1 file");
541: else if (addrp == (Addrp) NULL)
542: err ("do_p1_addr: Null addrp in p1 file");
543: else if (addrp -> tag != TADDR)
544: erri ("do_p1_addr: bad tag in p1 file '%d'", addrp -> tag);
545: else {
546: addrp -> vleng = do_format (infile, outfile);
547: addrp -> memoffset = do_format (infile, outfile);
548: }
549:
550: return (expptr) addrp;
551: } /* do_p1_addr */
552:
553:
554:
555: static void do_p1_subr_ret (infile, outfile)
556: FILE *infile, *outfile;
557: {
558: expptr retval;
559:
560: nice_printf (outfile, "return ");
561: retval = do_format (infile, outfile);
562: if (!multitype)
563: if (retval)
564: expr_out (outfile, retval);
565:
566: nice_printf (outfile, ";\n");
567: } /* do_p1_subr_ret */
568:
569:
570:
571: static void do_p1_comp_goto (infile, outfile)
572: FILE *infile, *outfile;
573: {
574: expptr index;
575: expptr labels;
576:
577: index = do_format (infile, outfile);
578:
579: if (index == ENULL) {
580: err ("do_p1_comp_goto: no expression for computed goto");
581: return;
582: } /* if index == ENULL */
583:
584: labels = do_format (infile, outfile);
585:
586: if (labels && labels -> tag != TLIST)
587: erri ("do_p1_comp_goto: expected list, got tag '%d'", labels -> tag);
588: else
589: compgoto_out (outfile, index, labels);
590: } /* do_p1_comp_goto */
591:
592:
593: static void do_p1_for (infile, outfile)
594: FILE *infile, *outfile;
595: {
596: expptr init, test, inc;
597:
598: init = do_format (infile, outfile);
599: test = do_format (infile, outfile);
600: inc = do_format (infile, outfile);
601:
602: out_for (outfile, init, test, inc);
603: } /* do_p1_for */
604:
605: static void do_p1_end_for (outfile)
606: FILE *outfile;
607: {
608: out_end_for (outfile);
609: } /* do_p1_end_for */
610:
611:
612: static void
613: do_p1_fortran(infile, outfile)
614: FILE *infile, *outfile;
615: {
616: char buf[P1_STMTBUFSIZE];
617: if (!p1gets(infile, buf, P1_STMTBUFSIZE))
618: return;
619: /* bypass nice_printf nonsense */
620: fprintf(outfile, "/*< %s >*/\n", buf+1); /* + 1 to skip by '$' */
621: }
622:
623:
624: static expptr do_p1_expr (infile, outfile)
625: FILE *infile, *outfile;
626: {
627: int status;
628: long opcode, type;
629: struct Exprblock *result = (struct Exprblock *) NULL;
630:
631: status = p1getd (infile, &opcode);
632:
633: if (status == EOF)
634: err ("do_p1_expr: Missing expr opcode at end of file");
635: else if (status == 0)
636: err ("do_p1_expr: Missing expr opcode in p1 file");
637: else {
638:
639: status = p1getd (infile, &type);
640:
641: if (status == EOF)
642: err ("do_p1_expr: Missing expr type at end of file");
643: else if (status == 0)
644: err ("do_p1_expr: Missing expr type in p1 file");
645: else if (opcode == 0)
646: return ENULL;
647: else {
648: result = ALLOC (Exprblock);
649:
650: result -> tag = TEXPR;
651: result -> vtype = type;
652: result -> opcode = opcode;
653: result -> vleng = do_format (infile, outfile);
654:
655: if (is_unary_op (opcode))
656: result -> leftp = do_format (infile, outfile);
657: else if (is_binary_op (opcode)) {
658: result -> leftp = do_format (infile, outfile);
659: result -> rightp = do_format (infile, outfile);
660: } else
661: errl("do_p1_expr: Illegal opcode %ld", opcode);
662: } /* else */
663: } /* else */
664:
665: return (expptr) result;
666: } /* do_p1_expr */
667:
668:
669: static expptr do_p1_ident(infile)
670: FILE *infile;
671: {
672: Addrp addrp;
673: int status;
674: long vtype, vstg;
675:
676: addrp = ALLOC (Addrblock);
677: addrp -> tag = TADDR;
678:
679: status = p1getd (infile, &vtype);
680: if (status == EOF)
681: err ("do_p1_ident: Missing identifier type at end of file\n");
682: else if (status == 0 || vtype < 0 || vtype >= NTYPES)
683: errl("do_p1_ident: Bad type in intermediate file: %ld\n", vtype);
684: else
685: addrp -> vtype = vtype;
686:
687: status = p1getd (infile, &vstg);
688: if (status == EOF)
689: err ("do_p1_ident: Missing identifier storage at end of file\n");
690: else if (status == 0 || vstg < 0 || vstg > STGNULL)
691: errl("do_p1_ident: Bad storage in intermediate file: %ld\n", vtype);
692: else
693: addrp -> vstg = vstg;
694:
695: status = p1gets(infile, addrp->user.ident, IDENT_LEN);
696:
697: if (status == EOF)
698: err ("do_p1_ident: Missing ident string at end of file");
699: else if (status == 0)
700: err ("do_p1_ident: Missing ident string in intermediate file");
701: addrp->uname_tag = UNAM_IDENT;
702: return (expptr) addrp;
703: } /* do_p1_ident */
704:
705: static expptr do_p1_charp(infile)
706: FILE *infile;
707: {
708: Addrp addrp;
709: int status;
710: long vtype, vstg;
711: char buf[64];
712:
713: addrp = ALLOC (Addrblock);
714: addrp -> tag = TADDR;
715:
716: status = p1getd (infile, &vtype);
717: if (status == EOF)
718: err ("do_p1_ident: Missing identifier type at end of file\n");
719: else if (status == 0 || vtype < 0 || vtype >= NTYPES)
720: errl("do_p1_ident: Bad type in intermediate file: %ld\n", vtype);
721: else
722: addrp -> vtype = vtype;
723:
724: status = p1getd (infile, &vstg);
725: if (status == EOF)
726: err ("do_p1_ident: Missing identifier storage at end of file\n");
727: else if (status == 0 || vstg < 0 || vstg > STGNULL)
728: errl("do_p1_ident: Bad storage in intermediate file: %ld\n", vtype);
729: else
730: addrp -> vstg = vstg;
731:
732: status = p1gets(infile, buf, (int)sizeof(buf));
733:
734: if (status == EOF)
735: err ("do_p1_ident: Missing charp ident string at end of file");
736: else if (status == 0)
737: err ("do_p1_ident: Missing charp ident string in intermediate file");
738: addrp->uname_tag = UNAM_CHARP;
739: addrp->user.Charp = strcpy(mem(strlen(buf)+1,0), buf);
740: return (expptr) addrp;
741: }
742:
743:
744: static expptr do_p1_extern (infile)
745: FILE *infile;
746: {
747: Addrp addrp;
748:
749: addrp = ALLOC (Addrblock);
750: if (addrp) {
751: int status;
752:
753: addrp->tag = TADDR;
754: addrp->vstg = STGEXT;
755: addrp->uname_tag = UNAM_EXTERN;
756: status = p1getd (infile, &(addrp -> memno));
757: if (status == EOF)
758: err ("do_p1_extern: Missing memno at end of file");
759: else if (status == 0)
760: err ("do_p1_extern: Missing memno in intermediate file");
761: if (addrp->vtype = extsymtab[addrp->memno].extype)
762: addrp->vclass = CLPROC;
763: } /* if addrp */
764:
765: return (expptr) addrp;
766: } /* do_p1_extern */
767:
768:
769:
770: static expptr do_p1_head (infile, outfile)
771: FILE *infile, *outfile;
772: {
773: int status;
774: int add_n_;
775: long class;
776: char storage[256];
777:
778: status = p1getd (infile, &class);
779: if (status == EOF)
780: err ("do_p1_head: missing header class at end of file");
781: else if (status == 0)
782: err ("do_p1_head: missing header class in p1 file");
783: else {
784: status = p1gets (infile, storage, (int)sizeof(storage));
785: if (status == EOF || status == 0)
786: storage[0] = '\0';
787: } /* else */
788:
789: if (class == CLPROC || class == CLMAIN) {
790: chainp lengths;
791:
792: add_n_ = nentry > 1;
793: lengths = length_comp(entries, add_n_);
794:
795: if (!add_n_ && protofile && class != CLMAIN)
796: protowrite(protofile, proctype, storage, entries, lengths);
797:
798: if (class == CLMAIN)
799: nice_printf (outfile, "/* Main program */ ");
800: else
801: nice_printf(outfile, "%s ", multitype ? "VOID"
802: : c_type_decl(proctype, 1));
803:
804: nice_printf(outfile, add_n_ ? "%s0_" : "%s", storage);
805: if (!Ansi) {
806: listargs(outfile, entries, add_n_, lengths);
807: nice_printf (outfile, "\n");
808: }
809: list_arg_types (outfile, entries, lengths, add_n_, "\n");
810: nice_printf (outfile, "{\n");
811: frchain(&lengths);
812: next_tab (outfile);
813: strcpy(this_proc_name, storage);
814: list_decls (outfile);
815:
816: } else if (class == CLBLOCK)
817: next_tab (outfile);
818: else
819: errl("do_p1_head: got class %ld", class);
820:
821: return NULL;
822: } /* do_p1_head */
823:
824:
825: static expptr do_p1_list (infile, outfile)
826: FILE *infile, *outfile;
827: {
828: long tag, type, count;
829: int status;
830: expptr result;
831:
832: status = p1getd (infile, &tag);
833: if (status == EOF)
834: err ("do_p1_list: missing list tag at end of file");
835: else if (status == 0)
836: err ("do_p1_list: missing list tag in p1 file");
837: else {
838: status = p1getd (infile, &type);
839: if (status == EOF)
840: err ("do_p1_list: missing list type at end of file");
841: else if (status == 0)
842: err ("do_p1_list: missing list type in p1 file");
843: else {
844: status = p1getd (infile, &count);
845: if (status == EOF)
846: err ("do_p1_list: missing count at end of file");
847: else if (status == 0)
848: err ("do_p1_list: missing count in p1 file");
849: } /* else */
850: } /* else */
851:
852: result = (expptr) ALLOC (Listblock);
853: if (result) {
854: chainp pointer;
855:
856: result -> tag = tag;
857: result -> listblock.vtype = type;
858:
859: /* Assume there will be enough data */
860:
861: if (count--) {
862: pointer = result->listblock.listp =
863: mkchain((char *)do_format(infile, outfile), CHNULL);
864: while (count--) {
865: pointer -> nextp =
866: mkchain((char *)do_format(infile, outfile), CHNULL);
867: pointer = pointer -> nextp;
868: } /* while (count--) */
869: } /* if (count) */
870: } /* if (result) */
871:
872: return result;
873: } /* do_p1_list */
874:
875:
876: chainp length_comp(e, add_n) /* get lengths of characters args */
877: struct Entrypoint *e;
878: int add_n;
879: {
880: chainp lengths;
881: chainp args, args1;
882: Namep arg, np;
883: int nchargs;
884: Argtypes *at;
885: Atype *a;
886: extern int init_ac[TYSUBR+1];
887:
888: if (!e)
889: return 0; /* possible only with errors */
890: args = args1 = add_n ? allargs : e->arglist;
891: nchargs = 0;
892: for (lengths = NULL; args; args = args -> nextp)
893: if (arg = (Namep)args->datap) {
894: if (arg->vclass == CLUNKNOWN)
895: arg->vclass = CLVAR;
896: if (arg->vtype == TYCHAR && arg->vclass != CLPROC) {
897: lengths = mkchain((char *)arg, lengths);
898: nchargs++;
899: }
900: }
901: if (!add_n && (np = e->enamep)) {
902: /* one last check -- by now we know all we ever will
903: * about external args...
904: */
905: save_argtypes(e->arglist, &e->entryname->arginfo,
906: &np->arginfo, 0, np->fvarname, STGEXT, nchargs,
907: np->vtype, 1);
908: at = e->entryname->arginfo;
909: a = at->atypes + init_ac[np->vtype];
910: for(; args1; a++, args1 = args1->nextp) {
911: frchain(&a->cp);
912: if (arg = (Namep)args1->datap)
913: switch(arg->vclass) {
914: case CLPROC:
915: if (arg->vimpltype
916: && a->type >= 300)
917: a->type = TYUNKNOWN + 200;
918: break;
919: case CLUNKNOWN:
920: a->type %= 100;
921: }
922: }
923: }
924: return revchain(lengths);
925: }
926:
927: void listargs(outfile, entryp, add_n_, lengths)
928: FILE *outfile;
929: struct Entrypoint *entryp;
930: int add_n_;
931: chainp lengths;
932: {
933: chainp args;
934: char *s;
935: Namep arg;
936: int did_one = 0;
937:
938: nice_printf (outfile, "(");
939:
940: if (add_n_) {
941: nice_printf(outfile, "n__");
942: did_one = 1;
943: args = allargs;
944: }
945: else {
946: if (!entryp)
947: return; /* possible only with errors */
948: args = entryp->arglist;
949: }
950:
951: if (multitype)
952: {
953: nice_printf(outfile, ", ret_val");
954: did_one = 1;
955: args = allargs;
956: }
957: else if (ONEOF(proctype, MSKCOMPLEX|MSKCHAR))
958: {
959: s = xretslot[proctype]->user.ident;
960: nice_printf(outfile, did_one ? ", %s" : "%s",
961: *s == '(' /*)*/ ? "r_v" : s);
962: did_one = 1;
963: if (proctype == TYCHAR)
964: nice_printf (outfile, ", ret_val_len");
965: }
966: for (; args; args = args -> nextp)
967: if (arg = (Namep)args->datap) {
968: nice_printf (outfile, "%s", did_one ? ", " : "");
969: out_name (outfile, arg);
970: did_one = 1;
971: }
972:
973: for (args = lengths; args; args = args -> nextp)
974: nice_printf(outfile, ", %s",
975: new_arg_length((Namep)args->datap));
976: nice_printf (outfile, ")");
977: } /* listargs */
978:
979:
980: void list_arg_types(outfile, entryp, lengths, add_n_, finalnl)
981: FILE *outfile;
982: struct Entrypoint *entryp;
983: chainp lengths;
984: int add_n_;
985: char *finalnl;
986: {
987: chainp args;
988: int last_type = -1, last_class = -1;
989: int did_one = 0, done_one, is_ext;
990: char *s, *sep = "", *sep1;
991:
992: if (outfile == (FILE *) NULL) {
993: err ("list_arg_types: null output file");
994: return;
995: } else if (entryp == (struct Entrypoint *) NULL) {
996: err ("list_arg_types: null procedure entry pointer");
997: return;
998: } /* else */
999:
1000: if (Ansi) {
1001: done_one = 0;
1002: sep1 = ", ";
1003: nice_printf(outfile, "(" /*)*/);
1004: }
1005: else {
1006: done_one = 1;
1007: sep1 = ";\n";
1008: }
1009: args = entryp->arglist;
1010: if (add_n_) {
1011: nice_printf(outfile, "int n__");
1012: did_one = done_one;
1013: sep = sep1;
1014: args = allargs;
1015: }
1016: if (multitype) {
1017: nice_printf(outfile, "%sMultitype *ret_val", sep);
1018: did_one = done_one;
1019: sep = sep1;
1020: }
1021: else if (ONEOF (proctype, MSKCOMPLEX|MSKCHAR)) {
1022: s = xretslot[proctype]->user.ident;
1023: nice_printf(outfile, "%s%s *%s", sep, c_type_decl(proctype, 0),
1024: *s == '(' /*)*/ ? "r_v" : s);
1025: did_one = done_one;
1026: sep = sep1;
1027: if (proctype == TYCHAR)
1028: nice_printf (outfile, "%sftnlen ret_val_len", sep);
1029: } /* if ONEOF proctype */
1030: for (; args; args = args -> nextp) {
1031: Namep arg = (Namep) args->datap;
1032:
1033: /* Scalars are passed by reference, and arrays will have their lower bound
1034: adjusted, so nearly everything is printed with a star in front. The
1035: exception is character lengths, which are passed by value. */
1036:
1037: if (arg) {
1038: int type = arg -> vtype, class = arg -> vclass;
1039:
1040: if (class == CLPROC)
1041: if (arg->vimpltype)
1042: type = Castargs ? TYUNKNOWN : TYSUBR;
1043: else if (type == TYREAL && forcedouble && !Castargs)
1044: type = TYDREAL;
1045:
1046: if (type == last_type && class == last_class && did_one)
1047: nice_printf (outfile, ", ");
1048: else
1049: if ((is_ext = class == CLPROC) && Castargs)
1050: nice_printf(outfile, "%s%s ", sep,
1051: usedcasts[type] = casttypes[type]);
1052: else
1053: nice_printf(outfile, "%s%s ", sep,
1054: c_type_decl(type, is_ext));
1055: if (class == CLPROC)
1056: if (Castargs)
1057: out_name(outfile, arg);
1058: else {
1059: nice_printf(outfile, "(*");
1060: out_name(outfile, arg);
1061: nice_printf(outfile, ") %s", parens);
1062: }
1063: else {
1064: nice_printf (outfile, "*");
1065: out_name (outfile, arg);
1066: }
1067:
1068: last_type = type;
1069: last_class = class;
1070: did_one = done_one;
1071: sep = sep1;
1072: } /* if (arg) */
1073: } /* for args = entryp -> arglist */
1074:
1075: for (args = lengths; args; args = args -> nextp)
1076: nice_printf(outfile, "%sftnlen %s", sep,
1077: new_arg_length((Namep)args->datap));
1078: if (did_one)
1079: nice_printf (outfile, ";\n");
1080: else if (Ansi)
1081: nice_printf(outfile,
1082: /*((*/ sep != sep1 && Ansi == 1 ? "void)%s" : ")%s",
1083: finalnl);
1084: } /* list_arg_types */
1085:
1086: static void
1087: write_formats(outfile)
1088: FILE *outfile;
1089: {
1090: register struct Labelblock *lp;
1091: int first = 1;
1092: char *fs;
1093:
1094: for(lp = labeltab ; lp < highlabtab ; ++lp)
1095: if (lp->fmtlabused) {
1096: if (first) {
1097: first = 0;
1098: nice_printf(outfile, "/* Format strings */\n");
1099: }
1100: nice_printf(outfile, "static char fmt_%ld[] = \"",
1101: lp->stateno);
1102: if (!(fs = lp->fmtstring))
1103: fs = "";
1104: nice_printf(outfile, "%s\";\n", fs);
1105: }
1106: if (!first)
1107: nice_printf(outfile, "\n");
1108: }
1109:
1110: static void
1111: write_ioblocks(outfile)
1112: FILE *outfile;
1113: {
1114: register iob_data *L;
1115: register char *f, **s, *sep;
1116:
1117: nice_printf(outfile, "/* Fortran I/O blocks */\n");
1118: L = iob_list = (iob_data *)revchain((chainp)iob_list);
1119: do {
1120: nice_printf(outfile, "static %s %s = { ",
1121: L->type, L->name);
1122: sep = 0;
1123: for(s = L->fields; f = *s; s++) {
1124: if (sep)
1125: nice_printf(outfile, sep);
1126: sep = ", ";
1127: if (*f == '"') { /* kludge */
1128: nice_printf(outfile, "\"");
1129: nice_printf(outfile, "%s\"", f+1);
1130: }
1131: else
1132: nice_printf(outfile, "%s", f);
1133: }
1134: nice_printf(outfile, " };\n");
1135: }
1136: while(L = L->next);
1137: nice_printf(outfile, "\n\n");
1138: }
1139:
1140: static void
1141: write_assigned_fmts(outfile)
1142: FILE *outfile;
1143: {
1144: register chainp cp;
1145: Namep np;
1146: int did_one = 0;
1147:
1148: cp = assigned_fmts = revchain(assigned_fmts);
1149: nice_printf(outfile, "/* Assigned format variables */\nchar ");
1150: do {
1151: np = (Namep)cp->datap;
1152: if (did_one)
1153: nice_printf(outfile, ", ");
1154: did_one = 1;
1155: nice_printf(outfile, "*%s_fmt", np->fvarname);
1156: }
1157: while(cp = cp->nextp);
1158: nice_printf(outfile, ";\n\n");
1159: }
1160:
1161: static char *
1162: to_upper(s)
1163: register char *s;
1164: {
1165: static char buf[64];
1166: register char *t = buf;
1167: register int c;
1168: while(*t++ = (c = *s++) >= 'a' && c <= 'z' ? c + 'A' - 'a' : c);
1169: return buf;
1170: }
1171:
1172:
1173: /* This routine creates static structures representing a namelist.
1174: Declarations of the namelist and related structures are:
1175:
1176: struct Vardesc {
1177: char *name;
1178: char *addr;
1179: ftnlen *dims; /* laid out as struct dimensions below *//*
1180: int type;
1181: };
1182: typedef struct Vardesc Vardesc;
1183:
1184: struct Namelist {
1185: char *name;
1186: Vardesc **vars;
1187: int nvars;
1188: };
1189:
1190: struct dimensions
1191: {
1192: ftnlen numberofdimensions;
1193: ftnlen numberofelements
1194: ftnlen baseoffset;
1195: ftnlen span[numberofdimensions-1];
1196: };
1197:
1198: If dims is not null, then the corner element of the array is at
1199: addr. However, the element with subscripts (i1,...,in) is at
1200: addr + sizeoftype * (i1+span[0]*(i2+span[1]*...) - dimp->baseoffset)
1201: */
1202:
1203: static void
1204: write_namelists(nmch, outfile)
1205: chainp nmch;
1206: FILE *outfile;
1207: {
1208: Namep var;
1209: struct Hashentry *entry;
1210: struct Dimblock *dimp;
1211: int i, nd, type;
1212: char *comma, *name;
1213: register chainp q;
1214: register Namep v;
1215: extern int typeconv[];
1216:
1217: nice_printf(outfile, "/* Namelist stuff */\n\n");
1218: for (entry = hashtab; entry < lasthash; ++entry) {
1219: if (!(v = entry->varp) || !v->vnamelist)
1220: continue;
1221: type = v->vtype;
1222: name = v->cvarname;
1223: if (dimp = v->vdim) {
1224: nd = dimp->ndim;
1225: nice_printf(outfile,
1226: "static ftnlen %s_dims[] = { %d, %ld, %ld",
1227: name, nd,
1228: dimp->nelt->constblock.Const.ci,
1229: dimp->baseoffset->constblock.Const.ci);
1230: for(i = 0, --nd; i < nd; i++)
1231: nice_printf(outfile, ", %ld",
1232: dimp->dims[i].dimsize->constblock.Const.ci);
1233: nice_printf(outfile, " };\n");
1234: }
1235: nice_printf(outfile, "static Vardesc %s_dv = { \"%s\", %s",
1236: name, to_upper(v->fvarname),
1237: type == TYCHAR ? ""
1238: : (dimp || oneof_stg(v,v->vstg,
1239: M(STGEQUIV)|M(STGCOMMON)))
1240: ? "(char *)" : "(char *)&");
1241: out_name(outfile, v);
1242: nice_printf(outfile, dimp ? ", %s_dims" : ", (ftnlen *)0", name);
1243: nice_printf(outfile, ", %ld };\n",
1244: type != TYCHAR ? (long)typeconv[type]
1245: : -v->vleng->constblock.Const.ci);
1246: }
1247:
1248: do {
1249: var = (Namep)nmch->datap;
1250: name = var->cvarname;
1251: nice_printf(outfile, "\nstatic Vardesc *%s_vl[] = ", name);
1252: comma = "{";
1253: i = 0;
1254: for(q = var->varxptr.namelist ; q ; q = q->nextp) {
1255: v = (Namep)q->datap;
1256: if (!v->vnamelist)
1257: continue;
1258: i++;
1259: nice_printf(outfile, "%s &%s_dv", comma, v->cvarname);
1260: comma = ",";
1261: }
1262: nice_printf(outfile, " };\n");
1263: nice_printf(outfile,
1264: "static Namelist %s = { \"%s\", %s_vl, %d };\n",
1265: name, to_upper(var->fvarname), name, i);
1266: }
1267: while(nmch = nmch->nextp);
1268: nice_printf(outfile, "\n");
1269: }
1270:
1271: /* fixextype tries to infer from usage in previous procedures
1272: the type of an external procedure declared
1273: external and passed as an argument but never typed or invoked.
1274: */
1275:
1276: static int
1277: fixexttype(var)
1278: Namep var;
1279: {
1280: Extsym *e;
1281: int type, type1;
1282: extern void changedtype();
1283:
1284: type = var->vtype;
1285: e = &extsymtab[var->vardesc.varno];
1286: if ((type1 = e->extype) && type == TYUNKNOWN)
1287: return var->vtype = type1;
1288: if (var->visused) {
1289: if (e->exused && type != type1)
1290: changedtype(var);
1291: e->exused = 1;
1292: e->extype = type;
1293: }
1294: return type;
1295: }
1296:
1297: static void
1298: ref_defs(outfile, refdefs) FILE *outfile; chainp refdefs;
1299: {
1300: chainp cp;
1301: int eb, i, j, n;
1302: struct Dimblock *dimp;
1303: long L;
1304: expptr b, vl;
1305: Namep var;
1306: char *amp, *comma;
1307:
1308: ind_printf(0, outfile, "\n");
1309: for(cp = refdefs = revchain(refdefs); cp; cp = cp->nextp) {
1310: var = (Namep)cp->datap;
1311: cp->datap = 0;
1312: amp = "_subscr";
1313: if (!(eb = var->vsubscrused)) {
1314: var->vrefused = 0;
1315: if (!ISCOMPLEX(var->vtype))
1316: amp = "_ref";
1317: }
1318: def_start(outfile, var->cvarname, amp, CNULL);
1319: dimp = var->vdim;
1320: vl = 0;
1321: comma = "(";
1322: amp = "";
1323: if (var->vtype == TYCHAR) {
1324: amp = "&";
1325: vl = var->vleng;
1326: if (ISCONST(vl) && vl->constblock.Const.ci == 1)
1327: vl = 0;
1328: nice_printf(outfile, "%sa_0", comma);
1329: comma = ",";
1330: }
1331: n = dimp->ndim;
1332: for(i = 1; i <= n; i++, comma = ",")
1333: nice_printf(outfile, "%sa_%d", comma, i);
1334: nice_printf(outfile, ") %s", amp);
1335: if (var->vsubscrused)
1336: var->vsubscrused = 0;
1337: else if (!ISCOMPLEX(var->vtype)) {
1338: out_name(outfile, var);
1339: nice_printf(outfile, "[%s", vl ? "(" : "");
1340: }
1341: for(j = 2; j < n; j++)
1342: nice_printf(outfile, "(");
1343: while(--i > 1) {
1344: nice_printf(outfile, "(a_%d)%s*", i, i == n ? "" : ")");
1345: expr_out(outfile, cpexpr(dimp->dims[i-2].dimsize));
1346: nice_printf(outfile, " + ");
1347: }
1348: nice_printf(outfile, "a_1");
1349: if (var->vtype == TYCHAR) {
1350: if (vl) {
1351: nice_printf(outfile, ")*");
1352: expr_out(outfile, cpexpr(vl));
1353: }
1354: nice_printf(outfile, " + a_0");
1355: }
1356: if (var->vstg != STGARG && (b = dimp->baseoffset)) {
1357: b = cpexpr(b);
1358: if (var->vtype == TYCHAR)
1359: b = mkexpr(OPSTAR, cpexpr(var->vleng), b);
1360: nice_printf(outfile, " - ");
1361: expr_out(outfile, b);
1362: }
1363: if (ISCOMPLEX(var->vtype)) {
1364: ind_printf(0, outfile, "\n");
1365: def_start(outfile, var->cvarname, "_ref", CNULL);
1366: comma = "(";
1367: for(i = 1; i <= n; i++, comma = ",")
1368: nice_printf(outfile, "%sa_%d", comma, i);
1369: nice_printf(outfile, ") %s[%s_subscr",
1370: var->cvarname, var->cvarname);
1371: comma = "(";
1372: for(i = 1; i <= n; i++, comma = ",")
1373: nice_printf(outfile, "%sa_%d", comma, i);
1374: nice_printf(outfile, ")");
1375: }
1376: ind_printf(0, outfile, "]\n" + eb);
1377: }
1378: nice_printf(outfile, "\n");
1379: frchain(refdefs);
1380: }
1381:
1382: list_decls (outfile)
1383: FILE *outfile;
1384: {
1385: extern chainp used_builtins;
1386: extern struct Hashentry *hashtab;
1387: extern ftnint wr_char_len();
1388: struct Hashentry *entry;
1389: int write_header = 1;
1390: int last_class = -1, last_stg = -1;
1391: Namep var;
1392: int Alias, Define, did_one, last_type, type;
1393: extern int def_equivs, useauto;
1394: extern chainp new_vars; /* Compiler-generated locals */
1395: chainp namelists = 0, refdefs = 0;
1396: char *ctype;
1397: int useauto1 = useauto && !saveall;
1398: long x;
1399: extern int hsize;
1400:
1401: /* First write out the statically initialized data */
1402:
1403: if (initfile)
1404: list_init_data(&initfile, initfname, outfile);
1405:
1406: /* Next come formats */
1407: write_formats(outfile);
1408:
1409: /* Now write out the system-generated identifiers */
1410:
1411: if (new_vars || nequiv) {
1412: chainp args, next_var, this_var;
1413: chainp nv[TYVOID], nv1[TYVOID];
1414: int i, j;
1415: Addrp Var;
1416: Namep arg;
1417:
1418: /* zap unused dimension variables */
1419:
1420: for(args = allargs; args; args = args->nextp) {
1421: arg = (Namep)args->datap;
1422: if (this_var = arg->vlastdim) {
1423: frexpr((tagptr)this_var->datap);
1424: this_var->datap = 0;
1425: }
1426: }
1427:
1428: /* sort new_vars by type, skipping entries just zapped */
1429:
1430: for(i = TYADDR; i < TYVOID; i++)
1431: nv[i] = 0;
1432: for(this_var = new_vars; this_var; this_var = next_var) {
1433: next_var = this_var->nextp;
1434: if (Var = (Addrp)this_var->datap) {
1435: if (!(this_var->nextp = nv[j = Var->vtype]))
1436: nv1[j] = this_var;
1437: nv[j] = this_var;
1438: }
1439: else {
1440: this_var->nextp = 0;
1441: frchain(&this_var);
1442: }
1443: }
1444: new_vars = 0;
1445: for(i = TYVOID; --i >= TYADDR;)
1446: if (this_var = nv[i]) {
1447: nv1[i]->nextp = new_vars;
1448: new_vars = this_var;
1449: }
1450:
1451: /* write the declarations */
1452:
1453: did_one = 0;
1454: last_type = -1;
1455:
1456: for (this_var = new_vars; this_var; this_var = this_var -> nextp) {
1457: Var = (Addrp) this_var->datap;
1458:
1459: if (Var == (Addrp) NULL)
1460: err ("list_decls: null variable");
1461: else if (Var -> tag != TADDR)
1462: erri ("list_decls: bad tag on new variable '%d'",
1463: Var -> tag);
1464:
1465: type = nv_type (Var);
1466: if (Var->vstg == STGINIT
1467: || Var->uname_tag == UNAM_IDENT
1468: && *Var->user.ident == ' '
1469: && multitype)
1470: continue;
1471: if (!did_one)
1472: nice_printf (outfile, "/* System generated locals */\n");
1473:
1474: if (last_type == type && did_one)
1475: nice_printf (outfile, ", ");
1476: else {
1477: if (did_one)
1478: nice_printf (outfile, ";\n");
1479: nice_printf (outfile, "%s ",
1480: c_type_decl (type, Var -> vclass == CLPROC));
1481: } /* else */
1482:
1483: /* Character type is really a string type. Put out a '*' for parameters
1484: with unknown length and functions returning character */
1485:
1486: if (Var -> vtype == TYCHAR && (!ISICON ((Var -> vleng))
1487: || Var -> vclass == CLPROC))
1488: nice_printf (outfile, "*");
1489:
1490: write_nv_ident(outfile, (Addrp)this_var->datap);
1491: if (Var -> vtype == TYCHAR && Var->vclass != CLPROC &&
1492: ISICON((Var -> vleng))
1493: && (i = Var->vleng->constblock.Const.ci) > 0)
1494: nice_printf (outfile, "[%d]", i);
1495:
1496: did_one = 1;
1497: last_type = nv_type (Var);
1498: } /* for this_var */
1499:
1500: /* Handle the uninitialized equivalences */
1501:
1502: do_uninit_equivs (outfile, &did_one);
1503:
1504: if (did_one)
1505: nice_printf (outfile, ";\n\n");
1506: } /* if new_vars */
1507:
1508: /* Write out builtin declarations */
1509:
1510: if (used_builtins) {
1511: chainp cp;
1512: Extsym *es;
1513:
1514: last_type = -1;
1515: did_one = 0;
1516:
1517: nice_printf (outfile, "/* Builtin functions */");
1518:
1519: for (cp = used_builtins; cp; cp = cp -> nextp) {
1520: Addrp e = (Addrp)cp->datap;
1521:
1522: switch(type = e->vtype) {
1523: case TYDREAL:
1524: case TYREAL:
1525: /* if (forcedouble || e->dbl_builtin) */
1526: /* libF77 currently assumes everything double */
1527: type = TYDREAL;
1528: ctype = "double";
1529: break;
1530: case TYCOMPLEX:
1531: case TYDCOMPLEX:
1532: type = TYVOID;
1533: /* no break */
1534: default:
1535: ctype = c_type_decl(type, 0);
1536: }
1537:
1538: if (did_one && last_type == type)
1539: nice_printf(outfile, ", ");
1540: else
1541: nice_printf(outfile, "%s\n%s ", did_one ? ";" : "", ctype);
1542:
1543: extern_out(outfile, es = &extsymtab[e -> memno]);
1544: proto(outfile, es->arginfo, es->fextname);
1545: last_type = type;
1546: did_one = 1;
1547: } /* for cp = used_builtins */
1548:
1549: nice_printf (outfile, ";\n\n");
1550: } /* if used_builtins */
1551:
1552: last_type = -1;
1553: for (entry = hashtab; entry < lasthash; ++entry) {
1554: var = entry -> varp;
1555:
1556: if (var) {
1557: int procclass = var -> vprocclass;
1558: char *comment = NULL;
1559: int stg = var -> vstg;
1560: int class = var -> vclass;
1561: type = var -> vtype;
1562:
1563: if (var->vrefused)
1564: refdefs = mkchain((char *)var, refdefs);
1565: if (var->vsubscrused)
1566: if (ISCOMPLEX(var->vtype))
1567: var->vsubscrused = 0;
1568: else
1569: refdefs = mkchain((char *)var, refdefs);
1570: if (ONEOF(stg, M(STGARG)|M(STGLENG)|M(STGINIT)))
1571: continue;
1572:
1573: if (useauto1 && stg == STGBSS && !var->vsave)
1574: stg = STGAUTO;
1575:
1576: switch (class) {
1577: case CLVAR:
1578: break;
1579: case CLPROC:
1580: switch(procclass) {
1581: case PTHISPROC:
1582: extsymtab[var->vardesc.varno].extype = type;
1583: continue;
1584: case PSTFUNCT:
1585: case PINTRINSIC:
1586: continue;
1587: case PUNKNOWN:
1588: err ("list_decls: unknown procedure class");
1589: continue;
1590: case PEXTERNAL:
1591: if (stg == STGUNKNOWN) {
1592: warn1(
1593: "%.64s declared EXTERNAL but never used.",
1594: var->fvarname);
1595: /* to retain names declared EXTERNAL */
1596: /* but not referenced, change
1597: /* "continue" to "stg = STGEXT" */
1598: continue;
1599: }
1600: else
1601: type = fixexttype(var);
1602: }
1603: break;
1604: case CLUNKNOWN:
1605: /* declared but never used */
1606: continue;
1607: case CLPARAM:
1608: continue;
1609: case CLNAMELIST:
1610: if (var->visused)
1611: namelists = mkchain((char *)var, namelists);
1612: continue;
1613: default:
1614: erri("list_decls: can't handle class '%d' yet",
1615: class);
1616: Fatal(var->fvarname);
1617: continue;
1618: } /* switch */
1619:
1620: /* Might be equivalenced to a common. If not, don't process */
1621: if (stg == STGCOMMON && !var->vcommequiv)
1622: continue;
1623:
1624: /* Only write the header if system-generated locals, builtins, or
1625: uninitialized equivs were already output */
1626:
1627: if (write_header == 1 && (new_vars || nequiv || used_builtins)
1628: && oneof_stg ( var, stg,
1629: M(STGBSS)|M(STGEXT)|M(STGAUTO)|M(STGCOMMON)|M(STGEQUIV))) {
1630: nice_printf (outfile, "/* Local variables */\n");
1631: write_header = 2;
1632: }
1633:
1634:
1635: Alias = oneof_stg(var, stg, M(STGEQUIV)|M(STGCOMMON));
1636: if (Define = (Alias && def_equivs)) {
1637: if (!write_header)
1638: nice_printf(outfile, ";\n");
1639: def_start(outfile, var->cvarname, CNULL, "(");
1640: goto Alias1;
1641: }
1642: else if (type == last_type && class == last_class &&
1643: stg == last_stg && !write_header)
1644: nice_printf (outfile, ", ");
1645: else {
1646: if (!write_header && ONEOF(stg, M(STGBSS)|
1647: M(STGEXT)|M(STGAUTO)|M(STGEQUIV)|M(STGCOMMON)))
1648: nice_printf (outfile, ";\n");
1649:
1650: switch (stg) {
1651: case STGARG:
1652: case STGLENG:
1653: /* Part of the argument list, don't write them out
1654: again */
1655: continue; /* Go back to top of the loop */
1656: case STGBSS:
1657: case STGEQUIV:
1658: case STGCOMMON:
1659: nice_printf (outfile, "static ");
1660: break;
1661: case STGEXT:
1662: nice_printf (outfile, "extern ");
1663: break;
1664: case STGAUTO:
1665: break;
1666: case STGINIT:
1667: case STGUNKNOWN:
1668: /* Don't want to touch the initialized data, that will
1669: be handled elsewhere. Unknown data have
1670: already been complained about, so skip them */
1671: continue;
1672: default:
1673: erri("list_decls: can't handle storage class %d",
1674: stg);
1675: continue;
1676: } /* switch */
1677:
1678: if (type == TYCHAR && halign && class != CLPROC
1679: && ISICON(var->vleng)) {
1680: nice_printf(outfile, "struct { %s fill; char val",
1681: halign);
1682: x = wr_char_len(outfile, var->vdim,
1683: var->vleng->constblock.Const.ci, 1);
1684: if (x %= hsize)
1685: nice_printf(outfile, "; char fill2[%ld]",
1686: hsize - x);
1687: nice_printf(outfile, "; } %s_st;\n", var->cvarname);
1688: def_start(outfile, var->cvarname, CNULL, var->cvarname);
1689: ind_printf(0, outfile, "_st.val\n");
1690: last_type = -1;
1691: write_header = 2;
1692: continue;
1693: }
1694: nice_printf(outfile, "%s ",
1695: c_type_decl(type, class == CLPROC));
1696: } /* else */
1697:
1698: /* Character type is really a string type. Put out a '*' for variable
1699: length strings, and also for equivalences */
1700:
1701: if (type == TYCHAR && class != CLPROC
1702: && (!var->vleng || !ISICON (var -> vleng))
1703: || oneof_stg(var, stg, M(STGEQUIV)|M(STGCOMMON)))
1704: nice_printf (outfile, "*%s", var->cvarname);
1705: else {
1706: nice_printf (outfile, "%s", var->cvarname);
1707: if (class == CLPROC) {
1708: Argtypes *at;
1709: if (!(at = var->arginfo)
1710: && var->vprocclass == PEXTERNAL)
1711: at = extsymtab[var->vardesc.varno].arginfo;
1712: proto(outfile, at, var->fvarname);
1713: }
1714: else if (type == TYCHAR && ISICON ((var -> vleng)))
1715: wr_char_len(outfile, var->vdim,
1716: (int)var->vleng->constblock.Const.ci, 0);
1717: else if (var -> vdim &&
1718: !oneof_stg (var, stg, M(STGEQUIV)|M(STGCOMMON)))
1719: comment = wr_ardecls(outfile, var->vdim, 1L);
1720: }
1721:
1722: if (comment)
1723: nice_printf (outfile, "%s", comment);
1724: Alias1:
1725: if (Alias) {
1726: char *amp, *lp, *name, *rp;
1727: char *equiv_name ();
1728: ftnint voff = var -> voffset;
1729: int et0, expr_type, k;
1730: Extsym *E;
1731: struct Equivblock *eb;
1732: char buf[16];
1733:
1734: /* We DON'T want to use oneof_stg here, because we need to distinguish
1735: between them */
1736:
1737: if (stg == STGEQUIV) {
1738: name = equiv_name(k = var->vardesc.varno, CNULL);
1739: eb = eqvclass + k;
1740: if (eb->eqvinit) {
1741: amp = "&";
1742: et0 = TYERROR;
1743: }
1744: else {
1745: amp = "";
1746: et0 = eb->eqvtype;
1747: }
1748: expr_type = et0;
1749: }
1750: else {
1751: E = &extsymtab[var->vardesc.varno];
1752: sprintf(name = buf, "%s%d", E->cextname, E->curno);
1753: expr_type = type;
1754: et0 = -1;
1755: amp = "&";
1756: } /* else */
1757:
1758: if (!Define)
1759: nice_printf (outfile, " = ");
1760: if (voff) {
1761: k = typesize[type];
1762: switch((int)(voff % k)) {
1763: case 0:
1764: voff /= k;
1765: expr_type = type;
1766: break;
1767: case SZSHORT:
1768: case SZSHORT+SZLONG:
1769: expr_type = TYSHORT;
1770: voff /= SZSHORT;
1771: break;
1772: case SZLONG:
1773: expr_type = TYLONG;
1774: voff /= SZLONG;
1775: break;
1776: default:
1777: expr_type = TYCHAR;
1778: }
1779: }
1780:
1781: if (expr_type == type) {
1782: lp = rp = "";
1783: if (et0 == -1 && !voff)
1784: goto cast;
1785: }
1786: else {
1787: lp = "(";
1788: rp = ")";
1789: cast:
1790: nice_printf(outfile, "(%s *)", c_type_decl(type, 0));
1791: }
1792:
1793: /* Now worry about computing the offset */
1794:
1795: if (voff) {
1796: if (expr_type == et0)
1797: nice_printf (outfile, "%s%s + %ld%s",
1798: lp, name, voff, rp);
1799: else
1800: nice_printf(outfile, "%s(%s *)%s%s + %ld%s", lp,
1801: c_type_decl (expr_type, 0), amp,
1802: name, voff, rp);
1803: } else
1804: nice_printf(outfile, "%s%s", amp, name);
1805: /* Always put these at the end of the line */
1806: last_type = last_class = last_stg = -1;
1807: write_header = 0;
1808: if (Define) {
1809: ind_printf(0, outfile, ")\n");
1810: write_header = 2;
1811: }
1812: continue;
1813: }
1814: write_header = 0;
1815: last_type = type;
1816: last_class = class;
1817: last_stg = stg;
1818: } /* if (var) */
1819: } /* for (entry = hashtab */
1820:
1821: if (!write_header)
1822: nice_printf (outfile, ";\n\n");
1823: else if (write_header == 2)
1824: nice_printf(outfile, "\n");
1825:
1826: /* Next, namelists, which may reference equivs */
1827:
1828: if (namelists) {
1829: write_namelists(namelists = revchain(namelists), outfile);
1830: frchain(&namelists);
1831: }
1832:
1833: /* Finally, ioblocks (which may reference equivs and namelists) */
1834: if (iob_list)
1835: write_ioblocks(outfile);
1836: if (assigned_fmts)
1837: write_assigned_fmts(outfile);
1838:
1839: if (refdefs)
1840: ref_defs(outfile, refdefs);
1841:
1842: } /* list_decls */
1843:
1844: do_uninit_equivs (outfile, did_one)
1845: FILE *outfile;
1846: int *did_one;
1847: {
1848: extern int nequiv;
1849: struct Equivblock *eqv, *lasteqv = eqvclass + nequiv;
1850: int k, last_type = -1, t;
1851:
1852: for (eqv = eqvclass; eqv < lasteqv; eqv++)
1853: if (!eqv -> eqvinit && eqv -> eqvtop != eqv -> eqvbottom) {
1854: if (!*did_one)
1855: nice_printf (outfile, "/* System generated locals */\n");
1856: t = eqv->eqvtype;
1857: if (last_type == t)
1858: nice_printf (outfile, ", ");
1859: else {
1860: if (*did_one)
1861: nice_printf (outfile, ";\n");
1862: nice_printf (outfile, "static %s ", c_type_decl(t, 0));
1863: k = typesize[t];
1864: } /* else */
1865: nice_printf(outfile, "%s", equiv_name((int)(eqv - eqvclass), CNULL));
1866: nice_printf(outfile, "[%ld]",
1867: (eqv->eqvtop - eqv->eqvbottom + k - 1) / k);
1868: last_type = t;
1869: *did_one = 1;
1870: } /* if !eqv -> eqvinit */
1871: } /* do_uninit_equivs */
1872:
1873:
1874: /* wr_ardecls -- Writes the brackets and size for an array
1875: declaration. Because of the inner workings of the compiler,
1876: multi-dimensional arrays get mapped directly into a one-dimensional
1877: array, so we have to compute the size of the array here. When the
1878: dimension is greater than 1, a string comment about the original size
1879: is returned */
1880:
1881: char *wr_ardecls(outfile, dimp, size)
1882: FILE *outfile;
1883: struct Dimblock *dimp;
1884: long size;
1885: {
1886: int i, k;
1887: static char buf[1000];
1888:
1889: if (dimp == (struct Dimblock *) NULL)
1890: return NULL;
1891:
1892: sprintf(buf, "\t/* was "); /* would like to say k = sprintf(...), but */
1893: k = strlen(buf); /* BSD doesn't return char transmitted count */
1894:
1895: for (i = 0; i < dimp -> ndim; i++) {
1896: expptr this_size = dimp -> dims[i].dimsize;
1897:
1898: if (!ISICON (this_size))
1899: err ("wr_ardecls: nonconstant array size");
1900: else {
1901: size *= this_size -> constblock.Const.ci;
1902: sprintf(buf+k, "[%ld]", this_size -> constblock.Const.ci);
1903: k += strlen(buf+k); /* BSD prevents combining this with prev stmt */
1904: } /* else */
1905: } /* for i = 0 */
1906:
1907: nice_printf (outfile, "[%ld]", size);
1908: strcat(buf+k, " */");
1909:
1910: return (i > 1) ? buf : NULL;
1911: } /* wr_ardecls */
1912:
1913:
1914:
1915: /* ----------------------------------------------------------------------
1916:
1917: The following routines read from the p1 intermediate file. If
1918: that format changes, only these routines need be changed
1919:
1920: ---------------------------------------------------------------------- */
1921:
1922: static int get_p1_token (infile)
1923: FILE *infile;
1924: {
1925: int token = P1_UNKNOWN;
1926:
1927: /* NOT PORTABLE!! */
1928:
1929: if (fscanf (infile, "%d", &token) == EOF)
1930: return P1_EOF;
1931:
1932: /* Skip over the ": " */
1933:
1934: if (getc (infile) != '\n')
1935: getc (infile);
1936:
1937: return token;
1938: } /* get_p1_token */
1939:
1940:
1941:
1942: /* Returns a (null terminated) string from the input file */
1943:
1944: static int p1gets (fp, str, size)
1945: FILE *fp;
1946: char *str;
1947: int size;
1948: {
1949: char *fgets ();
1950: char c;
1951:
1952: if (str == NULL)
1953: return 0;
1954:
1955: if ((c = getc (fp)) != ' ')
1956: ungetc (c, fp);
1957:
1958: if (fgets (str, size, fp)) {
1959: int length;
1960:
1961: str[size - 1] = '\0';
1962: length = strlen (str);
1963:
1964: /* Get rid of the newline */
1965:
1966: if (str[length - 1] == '\n')
1967: str[length - 1] = '\0';
1968: return 1;
1969:
1970: } else if (feof (fp))
1971: return EOF;
1972: else
1973: return 0;
1974: } /* p1gets */
1975:
1976:
1977: static int p1get_const (infile, type, resultp)
1978: FILE *infile;
1979: int type;
1980: struct Constblock **resultp;
1981: {
1982: int status;
1983: struct Constblock *result;
1984:
1985: if (type != TYCHAR) {
1986: *resultp = result = ALLOC(Constblock);
1987: result -> tag = TCONST;
1988: result -> vtype = type;
1989: }
1990:
1991: switch (type) {
1992: case TYINT1:
1993: case TYSHORT:
1994: case TYLONG:
1995: case TYLOGICAL:
1996: #ifdef TYQUAD
1997: case TYQUAD:
1998: #endif
1999: case TYLOGICAL1:
2000: case TYLOGICAL2:
2001: status = p1getd (infile, &(result -> Const.ci));
2002: break;
2003: case TYREAL:
2004: case TYDREAL:
2005: status = p1getf(infile, &result->Const.cds[0]);
2006: result->vstg = 1;
2007: break;
2008: case TYCOMPLEX:
2009: case TYDCOMPLEX:
2010: status = p1getf(infile, &result->Const.cds[0]);
2011: if (status && status != EOF)
2012: status = p1getf(infile, &result->Const.cds[1]);
2013: result->vstg = 1;
2014: break;
2015: case TYCHAR:
2016: status = fscanf(infile, "%lx", resultp);
2017: break;
2018: default:
2019: erri ("p1get_const: bad constant type '%d'", type);
2020: status = 0;
2021: break;
2022: } /* switch */
2023:
2024: return status;
2025: } /* p1get_const */
2026:
2027: static int p1getd (infile, result)
2028: FILE *infile;
2029: long *result;
2030: {
2031: return fscanf (infile, "%ld", result);
2032: } /* p1getd */
2033:
2034: static int
2035: p1getf(infile, result)
2036: FILE *infile;
2037: char **result;
2038: {
2039:
2040: char buf[1324];
2041: register int k;
2042:
2043: k = fscanf (infile, "%s", buf);
2044: if (k < 1)
2045: k = EOF;
2046: else
2047: strcpy(*result = mem(strlen(buf)+1,0), buf);
2048: return k;
2049: }
2050:
2051: static int p1getn (infile, count, result)
2052: FILE *infile;
2053: int count;
2054: char **result;
2055: {
2056:
2057: char *bufptr;
2058: extern ptr ckalloc ();
2059:
2060: bufptr = (char *) ckalloc (count);
2061:
2062: if (result)
2063: *result = bufptr;
2064:
2065: for (; !feof (infile) && count > 0; count--)
2066: *bufptr++ = getc (infile);
2067:
2068: return feof (infile) ? EOF : 1;
2069: } /* p1getn */
2070:
2071: static void
2072: proto(outfile, at, fname)
2073: FILE *outfile;
2074: Argtypes *at;
2075: char *fname;
2076: {
2077: int i, j, k, n;
2078: char *comma;
2079: Atype *atypes;
2080: Namep np;
2081: chainp cp;
2082: extern void bad_atypes();
2083:
2084: if (at) {
2085: /* Correct types that we learn on the fly, e.g.
2086: subroutine gotcha(foo)
2087: external foo
2088: call zap(...,foo,...)
2089: call foo(...)
2090: */
2091: atypes = at->atypes;
2092: n = at->defined ? at->dnargs : at->nargs;
2093: for(i = 0; i++ < n; atypes++) {
2094: if (!(cp = atypes->cp))
2095: continue;
2096: j = atypes->type;
2097: do {
2098: np = (Namep)cp->datap;
2099: k = np->vtype;
2100: if (np->vclass == CLPROC) {
2101: if (!np->vimpltype && k)
2102: k += 200;
2103: else {
2104: if (j >= 300)
2105: j = TYUNKNOWN + 200;
2106: continue;
2107: }
2108: }
2109: if (j == k)
2110: continue;
2111: if (j >= 300
2112: || j == 200 && k >= 200)
2113: j = k;
2114: else {
2115: if (at->nargs >= 0)
2116: bad_atypes(at,fname,i,j,k,""," and");
2117: goto break2;
2118: }
2119: }
2120: while(cp = cp->nextp);
2121: atypes->type = j;
2122: frchain(&atypes->cp);
2123: }
2124: }
2125: break2:
2126: if (parens) {
2127: nice_printf(outfile, parens);
2128: return;
2129: }
2130:
2131: if (!at || (n = at-> defined ? at->dnargs : at->nargs) < 0) {
2132: nice_printf(outfile, Ansi == 1 ? "()" : "(...)");
2133: return;
2134: }
2135:
2136: if (n == 0) {
2137: nice_printf(outfile, Ansi == 1 ? "(void)" : "()");
2138: return;
2139: }
2140:
2141: atypes = at->atypes;
2142: nice_printf(outfile, "(");
2143: comma = "";
2144: for(; --n >= 0; atypes++) {
2145: k = atypes->type;
2146: if (k == TYADDR)
2147: nice_printf(outfile, "%schar **", comma);
2148: else if (k >= 200) {
2149: k -= 200;
2150: nice_printf(outfile, "%s%s", comma,
2151: usedcasts[k] = casttypes[k]);
2152: }
2153: else if (k >= 100)
2154: nice_printf(outfile,
2155: k == TYCHAR + 100 ? "%s%s *" : "%s%s",
2156: comma, c_type_decl(k-100, 0));
2157: else
2158: nice_printf(outfile, "%s%s *", comma,
2159: c_type_decl(k, 0));
2160: comma = ", ";
2161: }
2162: nice_printf(outfile, ")");
2163: }
2164:
2165: void
2166: protowrite(protofile, type, name, e, lengths)
2167: FILE *protofile;
2168: char *name;
2169: struct Entrypoint *e;
2170: chainp lengths;
2171: {
2172: extern char used_rets[];
2173: int asave;
2174:
2175: if (!(asave = Ansi))
2176: Castargs = Ansi = 1;
2177: nice_printf(protofile, "extern %s %s", protorettypes[type], name);
2178: list_arg_types(protofile, e, lengths, 0, ";\n");
2179: used_rets[type] = 1;
2180: if (!(Ansi = asave))
2181: Castargs = 0;
2182: }
2183:
2184: static void
2185: do_p1_1while(outfile)
2186: FILE *outfile;
2187: {
2188: if (*wh_next) {
2189: nice_printf(outfile,
2190: "for(;;) { /* while(complicated condition) */\n" /*}*/ );
2191: next_tab(outfile);
2192: }
2193: else
2194: nice_printf(outfile, "while(" /*)*/ );
2195: }
2196:
2197: static void
2198: do_p1_2while(infile, outfile)
2199: FILE *infile, *outfile;
2200: {
2201: expptr test;
2202:
2203: test = do_format(infile, outfile);
2204: if (*wh_next)
2205: nice_printf(outfile, "if (!(");
2206: expr_out(outfile, test);
2207: if (*wh_next++)
2208: nice_printf(outfile, "))\n\tbreak;\n");
2209: else {
2210: nice_printf(outfile, /*(*/ ") {\n");
2211: next_tab(outfile);
2212: }
2213: }
2214:
2215: static void
2216: do_p1_elseifstart(outfile)
2217: FILE *outfile;
2218: {
2219: if (*ei_next++) {
2220: prev_tab(outfile);
2221: nice_printf(outfile, /*{*/
2222: "} else /* if(complicated condition) */ {\n" /*}*/ );
2223: next_tab(outfile);
2224: }
2225: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.