|
|
1.1 root 1: /*ident "@(#)ctrans:src/main.c 1.6.7.37" */
2: /***********************************************************************
3:
4: C++ source for cfront, the C++ compiler front-end
5: written in the computer science research center of Bell Labs
6:
7: Copyright (c) 1984 AT&T, Inc. All rigths Reserved
8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9:
10: main.c:
11:
12: Initialize global environment
13: Read argument line
14: Start compilation
15: Clean up and exit
16:
17: **************************************************************************/
18:
19: #ifdef __cplusplus
20: #include <stdlib.h>
21: #endif
22:
23: #include <ctype.h>
24: #include "cfront.h"
25: #include <string.h>
26: #include "dump_tree.H"
27: #include <libc.h>
28: #include <fstream.h>
29: #include "template.h"
30: #include <osfcn.h>
31: #include "hash.h"
32:
33: int zdebug = 0 ; // a debugging toggle
34: char* src_file_name;
35: char* line_format = "\n# %d \"%s\"\n";
36:
37: int dump_tree;
38: dcn_arg dump_tree_arg;
39: int tree_dump_brief = 0;
40: int catch_delete_bugs = 0;
41:
42:
43: char* prog_name = "<<PTcfront 2.00>>";
44: #ifdef unix
45: #include <signal.h>
46:
47: static void core_dump(int = 0)
48: {
49: if (error_count)
50: fprintf(stderr,"sorry, cannot recover from previous error\n");
51: else {
52: extern void print_loc();
53: print_loc();
54: error('i',"bus error (or something nasty like that)");
55: }
56: ext(99);
57: }
58: #endif
59:
60: Plist isf_list;
61: Pstmt st_ilist;
62: Pstmt st_dlist;
63: Ptable sti_tbl;
64: Ptable std_tbl;
65: Plist stat_mem_list;
66:
67: int Nfile;// = 1;
68: int vtbl_opt = -1; // how to deal with vtbls:
69: // -1 static and defined
70: // 0 external and supposed to be defined elsewhere
71: // 1 external and defined
72: int debug_opt;
73: bit limit_renaming = 0; /* rick, ODI, 3-23-89; used to switch off some
74: cfront renaming. */
75: bit capture_renaming = 0;/* Rick, ODI; used to switch off cfront renaming
76: capture. */
77:
78: int ansi_opt;
79: int strict_opt; // disallow features from the anachronism section
80: // of the manual
81: int warning_opt; // produce more warnings if set
82:
83: extern simpl_init();
84: extern typ_init();
85: extern syn_init();
86: extern lex_init();
87: extern error_init();
88:
89: static char *st_name(char*); // generates names of static ctor, dtor callers
90: static Pname def_name;
91:
92: Hash * dumper_node_hash_table;
93:
94: void static
95: clean_dumper_hash_table ()
96: {
97: if(!dumper_node_hash_table) return;
98: else {
99: HashWalker hi(*dumper_node_hash_table);
100:
101: while(hi.valid ()) {
102: struct node& n = *(struct node *) hi.key ();
103: if(n.permanent == 0 || n.permanent == 3) /* flush deleted nodes */
104: dumper_node_hash_table->del(hi.key());
105: hi.advance();
106: }
107: }
108: }
109:
110: int syn_count = 0; /* for ease of setting conditional breakpoints
111: to find particular expressions */
112:
113: void recycle_deleted_storage ();
114:
115: void run()
116: /*
117: run the appropriate stages
118: */
119: {
120: Pname n;
121: // Allocate the canonical templ_compilation instance
122: templp = new templ_compilation ;
123:
124:
125: if(dump_tree) {
126: dumper_node_hash_table =
127: dump_tree_arg.nodes_seen_hash = new pointer_hash (10000);
128: dump_tree_arg.verbose = dt_recursive_1;
129: }
130:
131: while (n=syn()) {
132: if (n == Pname(1)) continue;
133: if (n->n_list) PERM(n->tp);
134:
135: //printf( "\nrun: syn(): %s", n->string );
136: templp->instantiate_ref_templ() ;
137:
138: for (Pname nx, nn=n; nn; nn=nx) {
139: Pname rr;
140:
141: syn_count ++;
142:
143: nx = nn->n_list;
144: nn->n_list = 0;
145:
146:
147: //error('d',"run: dcl(): %s",nn->string);
148:
149: rr=nn->dcl(gtbl,EXTERN);
150:
151: if(rr == 0 || nn->base==0 || error_count) goto NEXT_DEFINITION;
152:
153:
154: //error('d',"run: simpl(): %n",nn);
155:
156: nn->simpl();
157:
158: if (error_count) {
159: if(dump_tree) {
160: display_cfront_node (dump_tree_arg, nn);
161: *dump_tree_arg.output_stream << "---------------------------\n\n";
162: }
163: goto NEXT_DEFINITION;
164: }
165:
166: //error('d',"run:print(): %n (%k) tp %t",nn,nn->base,nn->tp);
167:
168: if (nn->base == TNAME)
169: nn->dcl_print(0);
170: else {
171: Ptype t = nn->tp;
172: llxx:
173: switch (t->base) {
174: case TYPE:
175: t = Pbase(t)->b_name->tp; goto llxx;
176: case CLASS:
177: if (vtbl_opt==1) n->dcl_print(0);
178: break;
179: case ENUM:
180: Penum(n->tp)->dcl_print(0);
181: break;
182: case FCT:
183: //error('d',"fct%n inline %d body %d",nn,Pfct(t)->f_inline,Pfct(t)->body);
184: if (Pfct(t)->body==0
185: || (debug_opt==0 && Pfct(t)->f_inline)
186: || Pfct(t)->f_imeasure && Pfct(t)->f_inline==0) break;
187: //error('d',"rr %n inline %d body %d",rr,Pfct(rr->tp)->f_inline,Pfct(rr->tp)->body);
188: rr->dcl_print(0);
189: break;
190:
191: default:
192: nn->dcl_print(0);
193: }
194: }
195:
196:
197:
198: if(dump_tree) {
199: display_cfront_node (dump_tree_arg, nn);
200: *dump_tree_arg.output_stream << "---------------------------\n\n";
201: }
202:
203: if (error_count) goto NEXT_DEFINITION;
204:
205: switch (nn->tp->base) { // clean up
206: default:
207: { Pexpr i = nn->n_initializer;
208: //error('d',"default nn %n i %d",nn,i);
209: if (i && i!=Pexpr(1)) {
210: DEL(i);
211: nn->n_initializer = 0;
212: if (def_name==0) def_name = rr;
213: }
214: break;
215: }
216:
217: case FCT:
218: {
219: Pfct f = Pfct(nn->tp);
220: if (f->body
221: && f->f_inline==0
222: && f->f_imeasure==0) {
223: extern void delete_local();
224: // error('d', "main() nn: %n local_class: %d %d", nn, local_class, f->local_class );
225: // modification for local classes defined within inline functions
226: if ( local_class = f->local_class ) {
227: delete_local();
228: local_class = 0;
229: }
230: DEL(f->body);
231: if (def_name==0) def_name = rr;
232: }
233: break;
234: }
235:
236: case CLASS:
237: { Pclass cl = Pclass(nn->tp);
238: for (Pname px, p=cl->mem_list; p; p=px) {
239: px = p->n_list;
240: if (p->tp)
241: switch (p->tp->base) {
242: case FCT:
243: { Pfct f = (Pfct)p->tp;
244: if (f->body) {
245: if (f->f_inline==0
246: && f->f_imeasure==0) {
247: extern void delete_local();
248: // error('d', "main() member_fct nn: %n local_class: %d", nn, f->local_class );
249: // modification for local classes defined within inline functions
250: if ( local_class = f->local_class ) {
251: delete_local();
252: local_class = 0;
253: }
254: DEL(f->body);
255: f->body = 0;
256: }
257: }
258: }
259: case CLASS:
260: case ENUM:
261: break;
262: case COBJ:
263: case EOBJ:
264: DEL(p);
265: break;
266: default:
267: delete p;
268: }
269: else {
270: delete p;
271: }
272: }
273: cl->mem_list = 0;
274: /* This makes the classdef officially "deleted", which is lunacy. */
275: /* permanent == 1 is already on, perm == 2 is "expanded" to simpl,
276: and perm == 3 is never tested in at&t code. -benson */
277: #if 0
278: cl->permanent = 3;
279: #endif
280: break;
281: }
282: }
283: DEL(nn);
284: NEXT_DEFINITION:
285: recycle_deleted_storage ();
286: }
287:
288: lex_clear();
289: if(dump_tree)clean_dumper_hash_table ();
290:
291: }
292:
293: templp->end_of_compilation() ;
294:
295: switch (no_of_undcl) {
296: case 1: {error('w',"undeclaredF%n called",undcl);}
297: case 0: break;
298: default: {error('w',"%d undeclaredFs called; for example%n",no_of_undcl,undcl);}
299: }
300:
301: switch (no_of_badcall) {
302: case 1: {error('w',"%n declaredWoutAs calledWAs",badcall);}
303: case 0: break;
304: default: {error('w',"%d Fs declaredWoutAs calledWAs; for example%n",no_of_badcall,badcall);}
305: }
306:
307: if (error_count) return;
308:
309: int i = 1;
310: for (Pname m=gtbl->get_mem(i); m; m=gtbl->get_mem(++i)) {
311: if (m->base==TNAME
312: || m->n_sto==EXTERN
313: || m->n_stclass == ENUM) continue;
314:
315: Ptype t = m->tp;
316: if (t == 0) continue;
317: ll:
318: switch (t->base) {
319: case TYPE: t=Pbase(t)->b_name->tp; goto ll;
320: case CLASS:
321: case ANON:
322: case ENUM:
323: case COBJ:
324: case OVERLOAD:
325: case VEC: continue;
326: case FCT:
327: if (Pfct(t)->f_inline || Pfct(t)->body==0) continue;
328: }
329:
330: if (m->n_addr_taken==0
331: && m->n_used==0
332: && m->tp->tconst()==0
333: && m->n_sto == STATIC)
334: error('w',&m->where,"%n defined but not used",m);
335: }
336:
337: Pname ctor = 0;
338: Pname dtor = 0;
339: --curloc.line;
340:
341: if (st_ilist) { // make an "init" function;
342: // it calls all constructors for static objects
343: Pname n = new name( st_name("__sti__") );
344: Pfct f = new fct(void_type,0,1);
345: n->tp = f;
346: f->body = new block(st_ilist->where,0,st_ilist);
347: // f->body->s = st_ilist;
348: f->body->memtbl = sti_tbl;
349: n->n_sto = EXTERN;
350: // assignments here are really initializations:
351: extern int ignore_const;
352: ignore_const++;
353: set_linkage("C");
354: (void) n->dcl(gtbl,EXTERN);
355: set_linkage(0);
356: ignore_const--;
357: n->simpl();
358: n->dcl_print(0);
359: ctor = n;
360: }
361:
362: if (st_dlist) { // make a "done" function;
363: // it calls all destructors for static objects
364: Pname n = new name( st_name("__std__") );
365: Pfct f = new fct(void_type,0,1);
366: n->tp = f;
367: f->body = new block(st_dlist->where,0,st_dlist);
368: // f->body->s = st_dlist;
369: f->body->memtbl = std_tbl;
370: n->n_sto = EXTERN;
371: set_linkage("C");
372: (void) n->dcl(gtbl,EXTERN);
373: set_linkage(0);
374: n->simpl();
375: n->dcl_print(0);
376: dtor = n;
377: }
378:
379:
380: #ifdef PATCH
381: /*For fast load: make a static "__link" */
382: if (ctor || dtor)
383: {
384: fprintf(out_file, "static struct __linkl { struct __linkl * next;\n");
385: #ifdef sun
386: fprintf(out_file, "void (*ctor)(); void (*dtor)(); } __link = \n");
387: #else
388: fprintf(out_file, "char (*ctor)(); char (*dtor)(); } __link = \n");
389: #endif
390: // fprintf(out_file, "{ (struct __linkl *)0, %s, %s };\n",
391: // ctor_name ? ctor_name : "0",
392: // dtor_name ? dtor_name : "0");
393: putstring("{ (struct __linkl *)0, ");
394: if (ctor) ctor->print(); else putch('0');
395: putch(',');
396: if (dtor) dtor->print(); else putch('0');
397: putstring("};\n");
398: }
399: #endif
400:
401: // error( 'd', "run: vlist: %d", vlist );
402: do {
403: for (vl* v = vlist; v; v = v->next) v->cl->really_print(v->vt);
404: vlist = 0;
405:
406: for (Plist l=isf_list; l; l=l->l) {
407: Pname n = l->f;
408: Pfct f = Pfct(n->tp);
409: //error('d',"isf %n %t f %d addr %d",n,f,f,n->n_addr_taken);
410: if (f->base == OVERLOAD) {
411: n = Pgen(f)->fct_list->f; // first fct
412: f = Pfct(n->tp);
413: }
414:
415: if (debug_opt==0 && n->n_addr_taken) {
416: f->f_inline = 0;
417: if (n->n_dcl_printed<2) n->dcl_print(0);
418: }
419: }
420: } while (vlist);
421:
422: if (strict_opt == 0) { // define static members
423: // patch for SysV VAX -g linkage botch
424: for (Plist l=stat_mem_list; l; l=l->l) {
425: Pname n = l->f;
426: //error('d',"stat mem %n %d %d ",n,n->n_initializer,n->n_evaluated);
427: if (n->n_initializer==0 && n->n_evaluated==0) {
428: Ptype t = n->tp;
429: n->n_sto = 0;
430: Pname cn = t->is_cl_obj();
431: if (cn) (void) t->tsizeof(); // be sure to print class
432: if ((cn && Pclass(cn->tp)->has_ctor())
433: || t->is_ref())
434: ; // force explicit definition
435: else
436: n->dcl_print(0);
437: }
438: }
439: }
440:
441: curloc.putline();
442: fprintf(out_file,"\n/* the end */\n");
443: }
444:
445: char* afile = "";
446:
447: int no_of_undcl, no_of_badcall;
448: Pname undcl, badcall;
449:
450: extern int list_queries;
451: ofstream query_list_stream;
452:
453: void
454: odi_option(char * ostr)
455: {
456: ostr ++; /* skip the O */
457: switch(*ostr) {
458: default:
459: fprintf(stderr, "cfront: argument syntax: invalid ODI option.");
460: exit(11);
461: case 'D':
462: catch_delete_bugs = 1;
463: /* +DD checks for double deletion */
464: ostr ++;
465: if(*ostr && *ostr == 'D')catch_delete_bugs ++;
466:
467: case 'B':
468: tree_dump_brief = 1;
469: case 'T':
470: dump_tree = 1;
471: if(0 == *(ostr + 1) || strcmp (ostr, "T-") == 0)
472: dump_tree_arg.output_stream
473: = (ostream *)&cout;
474: else {
475: dump_tree_arg.output_stream
476: = new ofstream (ostr+1, ios::out);
477: if(dump_tree_arg.output_stream->fail()) {
478: perror ("cfront");
479: fprintf (stderr, "Failed to open %s\n",
480: ostr + 1);
481: exit (11);
482: }
483: }
484: break;
485: case 'o':
486: out_file = fopen (ostr+1, "w");
487: if(out_file == NULL) {
488: perror ("cfront");
489: fprintf(stderr, "Failed to open %s\n",
490: ostr+1);
491: exit(11);
492: }
493: break;
494: case 'g':
495: /* rick, ODI, 3-28-89; used to switch off some
496: cfront renaming. "+gx" causes
497: "limit_renaming" to be set. This turns off
498: the renaming of locals and data members
499: whose names don't clash with a base data
500: member. Additionally, transformed names are
501: captured using the field
502: name::output_sting. */
503: if (*++ostr == 'x') {
504: limit_renaming = 1;
505: capture_renaming = 1;
506: } else {
507: fprintf(stderr, "cfront: argument syntax: invalid ODI +g option.");
508: exit(11);
509: }
510: break;
511: }
512: }
513:
514:
515: main(int argc, char* argv[])
516: /*
517: read options, initialize, and run
518: */
519: {
520: register char * cp;
521:
522: /* go ahead and dump core. We can learn from it. Benson@odi, 89-05-11 */
523: #ifndef DEBUGGING
524: #ifdef unix
525:
526: #ifdef COMPLETE_SIG_PF
527: signal(SIGILL,core_dump);
528: signal(SIGIOT,core_dump);
529: signal(SIGEMT,core_dump);
530: signal(SIGFPE,core_dump);
531: signal(SIGBUS,core_dump);
532: signal(SIGSEGV,core_dump);
533: #else
534: typedef void (*ST)(int ...); // trick to circumvent problems with old
535: ST sick = ST(&signal); // (or C) versions <signal.h>
536: (*sick)(SIGILL,core_dump);
537: (*sick)(SIGIOT,core_dump);
538: (*sick)(SIGEMT,core_dump);
539: (*sick)(SIGFPE,core_dump);
540: (*sick)(SIGBUS,core_dump);
541: (*sick)(SIGSEGV,core_dump);
542:
543: #endif
544: #endif
545: #endif /* debugging */
546:
547: // SUM: not needed
548: // #ifdef apollo
549: // set_sbrk_size(1000000); // resets free store size
550: //#else
551: #ifndef apollo
552: (void) malloc(0); // suppress cashing in V8 malloc
553: #endif
554: error_init();
555:
556: for (int i=1; i<argc; ++i) {
557: switch (*(cp=argv[i])) {
558: case '+':
559: while (*++cp) {
560: switch(*cp) {
561: case 'O':
562: odi_option (cp);
563: goto xx;
564: case 'f':
565: src_file_name = cp+1;
566: goto xx;
567: case 'x': // read cross compilation table
568: if (read_align(afile = cp+1)) {
569: fprintf(stderr,"bad size-table (option +x)\n");
570: exit(11);
571: }
572: goto xx;
573: case 'e':
574: switch (*++cp) {
575: case '0':
576: case '1':
577: vtbl_opt = *cp-'0';
578: break;
579: default:
580: fprintf(stderr,"bad +e option\n");
581: exit(11);
582: }
583: break;
584: case 'd':
585: debug_opt = 1;
586: break;
587: case 'z':
588: // Internal debugging toggle
589: zdebug = 1 ;
590: break ;
591: case 'w':
592: warning_opt = 1;
593: break;
594: case 'a':
595: switch (*++cp) {
596: case '0':
597: case '1':
598: ansi_opt = *cp-'0';
599: break;
600: default:
601: fprintf(stderr,"bad +a option\n");
602: exit(11);
603: }
604: break;
605: case 'p':
606: strict_opt = 1;
607: break;
608: case 'L':
609: line_format = "\n#line %d \"%s\"\n";
610: break;
611: default:
612: fprintf(stderr,"%s: unexpected option: +%c ignored\n",
613: prog_name,*cp);
614:
615: }
616: }
617: xx:
618: break;
619: default:
620: fprintf(stderr,"%s: bad argument \"%s\"\n",prog_name,cp);
621: exit(11);
622: }
623: }
624:
625: fprintf(out_file,line_format+1,1,src_file_name?src_file_name:""); // strips leading \n
626: fprintf(out_file,"\n/* %s */\n",prog_name);
627: if (src_file_name) fprintf(out_file,"/* < %s > */\n",src_file_name);
628:
629: // if (Nspy) {
630: // start_time = time(0);
631: // print_align(afile);
632: // }
633: fflush(stderr);
634: otbl_init();
635: lex_init();
636: syn_init();
637: typ_init();
638: simpl_init();
639: scan_started = 1;
640: curloc.putline();
641: run();
642: if(dump_tree) {
643: ostream_printf(*dump_tree_arg.output_stream, "------------ GTBL ------------\n\n");
644: display_cfront_node (dump_tree_arg, ktbl);
645:
646: ostream_printf(*dump_tree_arg.output_stream, "------------ KTBL ------------\n\n");
647: display_cfront_node (dump_tree_arg, ktbl);
648: }
649:
650: // if (Nspy) {
651: // stop_time = time(0);
652: // spy(src_file_name);
653: // }
654: exit( (0<=error_count && error_count<127) ? error_count : 127);
655: }
656:
657: char* st_name(char* pref)
658: /*
659: make name "pref|source_file_name|_" or "pref|source_file_name|_"
660: where non alphanumeric characters are replaced with '_'
661: and add def_name at end to ensure uniqueness
662: */
663: {
664: int prefl = strlen(pref);
665: int strl = prefl + 2; // trailing '_' and 0
666: if (src_file_name) strl += strlen(src_file_name);
667: char* defs;
668: int defl;
669: if (def_name) {
670: defs = def_name->string;
671: defl = strlen(defs)+1; // '_'
672: }
673: else {
674: defs = 0;
675: defl = 0;
676: }
677: char* name = new char[strl+defl];
678: strcpy(name,pref);
679: if (src_file_name) strcpy(name+prefl,src_file_name);
680: name[strl-2] = '_';
681: name[strl-1] = 0;
682: // char *p = name;
683: // while ( *++p ) if (!isalpha(*p) && !isdigit(*p)) *p = '_';
684: for (char* p = name; *p; p++) if (!isalpha(*p) && !isdigit(*p)) *p = '_';
685: if (defs) {
686: strcpy(name+strl-1,defs); // after the '_'
687: name[strl+defl-2] = '_';
688: name[strl+defl-1] = 0;
689: }
690: #ifdef DENSE
691: void chop(char*);
692: chop(name);
693: #endif
694:
695: return name;
696: }
697:
698: /* ODI notes -
699:
700: tree dumping
701: limit_renaming
702:
703: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.