|
|
1.1 root 1: /*ident "@(#)ctrans:src/print2.c 1.4" */
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 Rights Reserved
8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9:
10: print2.c:
11:
12: print names and declarations
13:
14: ****************************************************************************/
15:
16: #include "cfront.h"
17: #include "template.h"
18:
19: bit Cast;
20: int last_ll = 1;
21: Pin curr_icall;
22: char emode;
23: int ntok;
24:
25: static int MAIN; // fudge to get _main() called by main()
26:
27: #define eprint(e) if (e) Eprint(e)
28:
29: #ifdef DENSE
30: void chop(char*);
31: #endif
32:
33: void puttok(TOK t)
34: /*
35: print the output representation of "t"
36: */
37: {
38: // if (t<=0 || MAXTOK<t) error("illegal token %d",t);
39: // char* s = keys[t];
40: // if (s == 0) error("V representation token %d",t);
41:
42: putstring(keys[t]);
43:
44: if (12<ntok++) {
45: ntok = 0;
46: last_line.putline();
47: }
48: else if (t == SM) {
49: ntok = 0;
50: putch('\n');
51: if (last_ll) last_line.line++;
52: }
53: else
54: putch(' ');
55: }
56:
57: #define MX 20
58: #define NTBUF 10
59: class dcl_buf {
60: /*
61: buffer for assembling declaration (or cast)
62: left contains CONST_PTR => *CONST
63: CONST_RPTR => &CONST
64: PTR => *
65: RPTR => &
66: LP => (
67: right contains RP => )
68: VEC => [ rnode ]
69: FCT => ( rnode )
70: FIELD => : rnode
71: */
72: Pbase b;
73: Pname n;
74: TOK left[MX], right[MX];
75: Pnode rnode[MX];
76: Pclass lnode[MX];
77: int li, ri;
78: public:
79: void init(Pname nn) { b=0; n=nn; li=ri=0; }
80: void base(Pbase bb) { b = bb; }
81: void front(TOK t) { left[++li] = t; }
82: void front(Pclass c) { left[++li] = MEMPTR; lnode[li] = c; }
83: void back(TOK t, Pnode nod) { right[++ri] = t; rnode[ri] = nod; }
84: void paran() { front(LP); back(RP,0); }
85: void put();
86: } *tbufvec[NTBUF] = {0}, *tbuf = 0;
87:
88: int freetbuf = 0;
89:
90: void dcl_buf::put()
91: {
92: int i;
93: Pfct ff = 0;
94:
95: if (MX<=li || MX<=ri) error('i',"T buffer overflow");
96: if (b == 0) error('i',"noBT%s",Cast?" in cast":"");
97:
98: if (n && n->n_sto && n->n_sto!=REGISTER) puttok(n->n_sto);
99:
100: b->dcl_print();
101:
102: for( ; li; li--) {
103: switch (left[li]) {
104: case LP:
105: putch('(');
106: break;
107: case PTR:
108: putch('*');
109: break;
110: case RPTR:
111: if (emode)
112: putch('&');
113: else
114: putch('*');
115: break;
116: case CONST_PTR:
117: if (emode)
118: putstring("*const ");
119: else
120: putch('*');
121: break;
122: case CONST_RPTR:
123: if (emode)
124: putstring("&const ");
125: else
126: putch('*');
127: break;
128: case MEMPTR:
129: if (lnode[li]) fprintf(out_file,"%s::",lnode[li]->string);
130: }
131: }
132:
133: if (n) n->print();
134:
135: for(i=1; i<=ri; i++) {
136: switch (right[i]) {
137: case RP:
138: putch(')');
139: break;
140: case VEC:
141: putch('[');
142: { Pvec v = (Pvec) rnode[i];
143: Pexpr d = v->dim;
144: int s = v->size;
145: if (d) d->print();
146: if (s) fprintf(out_file,"%d",s);
147: }
148: putch(']');
149: break;
150: case FCT: // beware of function returning pointer to
151: // function expressed witout typedef
152: { Pfct f = Pfct(rnode[i]);
153: if (f->body) ff = f;
154: f->dcl_print();
155: break;
156: }
157: case FIELD:
158: { Pbase f = (Pbase) rnode[i];
159: Pexpr d = (Pexpr)f->b_name;
160: int s = f->b_bits;
161: putch(':');
162: if (d)
163: d->print();
164: else if (s)
165: fprintf(out_file,"%d",s);
166: else
167: puttok(ZERO);
168: break;
169: }
170: }
171: }
172: void print_body(Pfct);
173: if (ff && emode==0) print_body(ff);
174: }
175:
176: static Pexpr mk_zero_init( Ptype tt, Pname obname, Pname currname )
177: /*
178: creates 0 initializer for defined objects
179: side effect: generates right nesting level for {}
180: */
181: {
182: zaq:
183: switch (tt->base) {
184: case TYPE:
185: tt = Pbase(tt)->b_name->tp; goto zaq;
186: case VEC: // type a[size]; => type a[size] = {0};
187: {
188: if ( obname == currname ) {
189: //xxx initializing vectors blows up the size of some programs
190: return 0;
191: } else {
192: Pexpr i = mk_zero_init(Pvec(tt)->typ,obname,currname);
193: if ( i == 0 ) return 0;
194: return new expr( ILIST, i, 0 );
195: }
196: }
197: case COBJ: // "X a;" == "X a = {0};"
198: {
199: Pclass cl = Pclass(Pbase(tt)->b_name->tp);
200: if ( !ansi_opt && (cl->csu == ANON || cl->csu == UNION) ) {
201: if ( warning_opt ) {
202: // ridiculous handstands to avoid printing
203: // compiler generated names in warning
204: Ptype tn = obname->tp;
205: for(;;) if(tn->base==VEC) tn=Pvec(tn)->typ; else break;
206: if ( obname == currname && tt == tn ) {
207: if ( cl->string[0]=='_' && cl->string[1]=='_' )
208: error('w',&obname->where,"cannot generate zeroIr for%n ofT union; toI, compile with +a1 or insert non-union object as first member",obname);
209: else
210: error('w',&obname->where,"cannot generate zeroIr for%n ofT%t; toI, compile with +a1 or insert non-union object as first member",obname,obname->tp);
211: } else { Pclass cx;
212: if ( tn->base == COBJ
213: && (cx=(Pclass)Pbase(tn)->b_name->tp,
214: cx->string[0]=='_' && cx->string[1]=='_') )
215: error('w',&obname->where,"cannot generate zeroIr for%n (union or aggregate with union as first element); toI, compile with +a1 or insert non-union object as first member",obname);
216: else
217: error('w',&obname->where,"cannot generate zeroIr for%n ofT%t (union or aggregate with union as first element); toI, compile with +a1 or insert non-union object as first member",obname,obname->tp);
218: }
219: } // if warning_opt
220: return 0;
221: }
222: Pbcl l = cl->baselist;
223: while ( l ) {
224: if ( l->base == NAME ) cl = l->bclass;
225: else return new expr(ILIST,zero,0);
226: l = cl->baselist;
227: }
228: int i = 1;
229: Pname nn = cl->memtbl->get_mem(i);
230: for ( ; nn; nn = cl->memtbl->get_mem(++i) ) {
231: Ptype tx = nn->tp;
232: while ( tx->base == TYPE ) tx = Pbase(tx)->b_name->tp;
233: if (nn->base==NAME
234: && nn->n_union==0
235: && tx->base!=FCT
236: && tx->base!=OVERLOAD
237: && tx->base!=CLASS
238: && tx->base!=ENUM
239: && nn->n_stclass != STATIC) {
240: Pexpr i = mk_zero_init(tx,obname,nn);
241: if ( i == 0 ) return 0;
242: return new expr(ILIST,i,0);
243: }
244: }
245: return 0;
246: }
247: case PTR:
248: if (tt->memptr()) {
249: Pexpr i = new expr(ELIST,zero,zero);
250: return new expr(ILIST,i,zero);
251: }
252: // no break
253: case RPTR:
254: case CHAR:
255: case SHORT:
256: case INT:
257: case EOBJ:
258: case LONG:
259: case FLOAT:
260: case DOUBLE:
261: case LDOUBLE: // "int a;" == "int a = 0;"
262: case FIELD:
263: case ANY:
264: return zero;
265: }
266: return 0;
267: }
268:
269: void name::dcl_print(TOK list)
270: /*
271: Print the declaration for a name (list==0) or a name list (list!=0):
272: For each name
273: (1) print storage class
274: (2) print base type
275: (3) print the name with its declarators
276: Avoid (illegal) repetition of basetypes which are class or enum declarations
277: (A name list may contain names with different base types)
278: list == SM : terminator SM
279: list == 0: single declaration with terminator SM
280: list == CM : separator CM
281: */
282: {
283: if (error_count) return;
284:
285: for (Pname n=this; n; n=n->n_list) {
286: Ptype t = n->tp;
287: int sm = 0;
288:
289: // error('d',"%s->dcl_print() tp %t sto %k",n->string,t,n->n_sto);
290: if (t == 0) error('i',"N::dcl_print(%n)T missing",n);
291:
292: if (n->n_stclass==ENUM) if (list) continue; else return;
293:
294: if (n->where.line!=last_line.line || n->where.file!=last_line.file)
295: //fprintf(stderr,"%s ",n->string?n->string:"<0>"); n->where.put(stderr); fprintf(stderr," last "); last_line.put(stderr); putc('\n',stderr);
296: if (last_ll = n->where.line)
297: n->where.putline();
298: else
299: last_line.putline();
300:
301: int tc = Pbase(t)->b_const;
302: for (Ptype tt = t; tt->base==TYPE; tt = Pbase(tt)->b_name->tp)
303: tc |= Pbase(tt)->b_const;
304:
305: switch (t->base) {
306: case CLASS:
307: //fprintf(stderr,"class %s->dcl_print()\n",n->string);
308: if (n->base != TNAME) {
309: Pclass(t)->dcl_print(n);
310: sm = 1;
311: }
312: break;
313:
314: case ENUM:
315: Penum(t)->dcl_print(0);
316: sm = 1;
317: break;
318:
319: case FCT:
320: { Pfct f = Pfct(t);
321:
322: if (n->base == TNAME) puttok(TYPEDEF);
323:
324: // error('d',"fct %n->dcl_print() printed %d body %d defined %d",n,n->n_dcl_printed,f->body,f->defined);
325: // error('d',"n %d tbl %d tp %t inline %d",n,n->n_table,n->tp,f->f_inline);
326: if (n->n_dcl_printed==2 // definition already printed
327: || (n->n_dcl_printed==1 && f->body==0)
328: // declaration already printed
329: ) {
330: // don't print again
331: sm = 1; // no SM
332: break;
333: }
334:
335: if (f->f_result == 0) make_res(f);
336:
337: if (f->body && n->n_sto==EXTERN) n->n_sto = 0;
338:
339: if (f->f_inline && ((n->n_table!=gtbl) || strcmp(n->string,"main"))) {
340: if (debug_opt) {
341: //error('d',"f %t defined %d inline %d",f,f->defined,f->f_inline);
342: if (f->defined&DEFINED
343: && f->defined&SIMPLIFIED
344: && f->f_inline!=ITOR)
345: goto prnt_def;
346: else if (n->n_dcl_printed==0)
347: goto prnt_dcl;
348: else {
349: sm = 1;
350: break;
351: }
352: }
353: if (f->f_virtual || n->n_addr_taken) {
354: prnt_dcl:
355: //error('d',"prnt_dcl %d %n %k",n,n,n->n_sto);
356: TOK st = n->n_sto;
357: Pblock b = f->body;
358: f->body = 0;
359: t->dcl_print(n);
360: n->n_dcl_printed = 1;
361: n->n_sto = st;
362: f->body = b;
363: break;
364: }
365: else
366: sm = 1; // no SM
367: }
368: else if ((f->defined&DEFINED)==0
369: || (f->defined&SIMPLIFIED)==0)
370: goto prnt_dcl;
371: else if (n->n_table==gtbl && strcmp(n->string,"main")==0) {
372: if (f->f_inline) {
373: if (warning_opt) {
374: error('w',"main() cannot be inlined");
375: error('w',"out-of-line copy of main() created");
376: }
377: n->n_sto=0;
378: }
379: MAIN = 1;
380: gtbl->look("main",0)->use();
381: f->f_signature = 0;
382: t->dcl_print(n);
383: n->n_dcl_printed = f->body?2:1;
384: MAIN = 0;
385: }
386: else {
387: prnt_def:
388: // error('d',"prnt_def %n %k %d %k",n,n->n_oper,n,n->n_sto);
389: if (n->n_oper==CTOR || n->n_oper==DTOR) {
390: Pclass cl = Pclass(n->n_table->t_name->tp);
391: if (cl->c_body == 3) cl->print_all_vtbls(cl);
392: }
393:
394: if ( n->n_sto == STATIC &&
395: pdef_name == 0 && def_name == 0 ) {
396: // error('d', "printing ptbl_vec without first definition" );
397: pdef_name = n;
398: ptbl_init(0);
399: }
400: t->dcl_print(n);
401: n->n_dcl_printed = f->body?2:1;
402: }
403: if (f->body) sm = 1;
404: break;
405: }
406:
407: case OVERLOAD:
408: {
409: for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) {
410: Pname nn = gl->f;
411: nn->dcl_print(0);
412: sm = 1;
413: }
414: break;
415: }
416:
417: case ASM:
418: fprintf(out_file,"asm(\"%s\")\n",(char*)Pbase(t)->b_name);
419: break;
420:
421: case INT:
422: case EOBJ:
423: case CHAR:
424: case LONG:
425: case SHORT:
426: tcx:
427: // do not allocate space for constants unless necessary
428: if (tc
429: && n->n_sto!=EXTERN // extern const one;
430: // const one = 1;
431: // allocates storage
432: && (n->n_scope==EXTERN // FUDGE const one = 1;
433: // is treated as static
434: // need loader support
435: || n->n_scope==STATIC
436: || n->n_scope==FCT)
437: ) {
438: if (n->n_evaluated && n->n_addr_taken==0) {
439: sm = 1; /* no ; */
440: break;
441: }
442: }
443: tc = 0;
444: // no break;
445:
446: default:
447: {
448: /*
449: // don't print local instance of const
450: if ( n->n_dcl_printed == 3 ) {
451: sm = 1;
452: break;
453: }
454: */
455: Pexpr i = n->n_initializer;
456: if (n->base == TNAME && n->n_key == NESTED) i = 0;
457: if (tc) {
458: switch (tt->base) {
459: case CHAR:
460: case SHORT:
461: case INT:
462: case LONG:
463: case EOBJ:
464: goto tcx;
465: }
466: }
467:
468: if (n->base == TNAME) {
469: /* Always print template formals, even when they have the same
470: * formal name, since the instantiation name is different. This
471: * fix should not be required when the copy mechanism is in place. */
472: if (! n_template_arg)
473: for (Pname tn=ktbl->look(n->string,HIDDEN); tn; tn=tn->n_tbl_list)
474: if (tn && tn->lex_level && t==tn->tp) return;
475: puttok(TYPEDEF);
476: }
477:
478: if (n->n_stclass == REGISTER) {
479: // (imperfect) check against member functions
480: // register s a; a.f() illegal
481: Pname cln = n->tp->is_cl_obj();
482: if (cln) {
483: Pclass cl = Pclass(cln->tp);
484: if (cl->csu!=CLASS
485: && cl->baselist==0
486: && cl->has_itor()==0
487: && cl->virt_count==0) puttok(REGISTER);
488: }
489: else
490: puttok(REGISTER);
491: }
492:
493: if (i) {
494: if (n->n_sto==EXTERN && n->n_stclass==STATIC) {
495: n->n_initializer = 0;
496: t->dcl_print(n);
497: puttok(SM);
498: n->n_initializer = i;
499: n->n_sto = 0;
500: t->dcl_print(n);
501: n->n_sto = EXTERN;
502: }
503: else
504: t->dcl_print(n);
505: if(n->n_table) {
506: Pname nn = n->n_table->look(n->string,0);
507: if(nn)
508: nn->n_dcl_printed = 1;
509: else
510: n->n_dcl_printed = 1;
511: }
512: else
513: n->n_dcl_printed = 1;
514: }
515: else if (n->n_evaluated && Pbase(t)->b_const) {
516: if (n->n_sto==EXTERN && n->n_stclass==STATIC) {
517: int v = n->n_evaluated;
518: n->n_evaluated = 0;
519: t->dcl_print(n);
520: puttok(SM);
521: if (n->where.line!=last_line.line || n->where.file!=last_line.file)
522: if (last_ll = n->where.line)
523: n->where.putline();
524: else
525: last_line.putline();
526: n->n_evaluated = v;
527: n->n_sto = 0;
528: t->dcl_print(n);
529: n->n_sto = EXTERN;
530: }
531: else
532: t->dcl_print(n);
533: if(n->n_table) {
534: Pname nn = n->n_table->look(n->string,0);
535: if(nn)
536: nn->n_dcl_printed = 1;
537: else
538: n->n_dcl_printed = 1;
539: }
540: else
541: n->n_dcl_printed = 1;
542: }
543: else {
544: //error('d',"%n sto %k val %d stc %k",n,n->n_sto,n->n_val,n_stclass);
545: if ((n->n_sto==0 || (n->n_val && n->n_evaluated==0))
546: && n_stclass==STATIC
547: && n->n_sto!=STATIC
548: && n->n_table==gtbl) {
549: if (n->n_val && n->n_evaluated==0) {
550: // extern x = f();
551: // generate int x = 0;
552: // plus dynamic initialization
553: n->n_sto = 0;
554: }
555:
556: n->n_initializer = i = mk_zero_init(t,n,n);
557: }
558: t->dcl_print(n);
559: if(n->n_table) {
560: Pname nn = n->n_table->look(n->string,0);
561: if(nn)
562: nn->n_dcl_printed = 1;
563: else
564: n->n_dcl_printed = 1;
565: }
566: else
567: n->n_dcl_printed = 1;
568: }
569:
570: if (n->n_scope!=ARG) {
571: if (i) {
572: puttok(ASSIGN);
573:
574: Pexpr i2 = i;
575: while (i2->base == CAST) i2 = i2->e1;
576: if (i2->base == ILIST) i = i2;
577: if (t!=i->tp
578: && i->base!=ZERO
579: && i->base!=ILIST /*&& i->tp!=Pchar_type*/) {
580: Ptype t1 = n->tp;
581: cmp:
582: switch (t1->base) {
583: case TYPE:
584: t1 = Pbase(t1)->b_name->tp;
585: goto cmp;
586: default:
587: i->print();
588: break;
589: // case EOBJ:
590: // goto cst;
591: case VEC:
592: if (Pvec(t1)->typ->base==CHAR) {
593: i->print();
594: break;
595: }
596: // no break
597: case PTR:
598: case RPTR:
599: if (i->tp==0 || n->tp->check(i->tp,0)) {
600: // cst:
601: putch('(');
602: bit oc = Cast;
603: Cast = 1;
604: t->print();
605: Cast = oc;
606: putch(')');
607: }
608: eprint(i);
609: }
610: }
611: else {
612: if (i==zero) {
613: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
614: // if (t->base == EOBJ) {
615: // putch('(');
616: // bit oc = Cast;
617: // Cast = 1;
618: // t->print();
619: // Cast = oc;
620: // putch(')');
621: // }
622: }
623: eprint(i);
624:
625: // i->print();
626: }
627: }
628: else if (n->n_evaluated) {
629: puttok(ASSIGN);
630: if (n->tp->base!=INT || n->tp->is_unsigned()) {
631: putstring("((");
632: bit oc = Cast;
633: Cast = 1;
634: n->tp->print();
635: Cast = oc;
636: fprintf(out_file,")%d)",n->n_val);
637: }
638: else
639: fprintf(out_file,"%d",n->n_val);
640: }
641: }
642: }
643: }
644:
645: switch (list) {
646: case SM:
647: if (sm==0) puttok(SM);
648: break;
649: case 0:
650: if (sm==0) puttok(SM);
651: return;
652: case CM:
653: if (n->n_list) puttok(CM);
654: break;
655: }
656: }
657: }
658:
659: char *local_sign( Ptype pt )
660: { // get function signature for local class
661: char buf[1024];
662: char* bb = pt->signature(buf);
663: int ll = bb-buf;
664: if (1023 < ll) error('i',"local class N buffer overflow");
665: char *p = new char[ll+1];
666: strcpy(p,buf);
667: return p;
668: }
669:
670: void enumdef::dcl_print(Pname cln)
671: /*
672: */
673: {
674: // note: ***** modify to handle local enums
675: // error('d', "%t::dcl_print(%n) in_class: %t nested_sig: %s", this, cln, in_class, nested_sig );
676: char* s = nested_sig?nested_sig:(cln ? cln->string:0);
677: if ( nested_sig )
678: fprintf(out_file,"enum __%s { ",nested_sig);
679: else fprintf(out_file,"enum %s { ",string);
680:
681: for (Pname px, p=mem; p; p=px) {
682: px = p->n_list;
683: if (s) {
684: if (p->n_evaluated)
685: fprintf(out_file,"%s__%s = %d",p->string,s,p->n_val);
686: else
687: fprintf(out_file,"%s__%s",p->string,s);
688: }
689: else {
690: if (p->n_evaluated)
691: fprintf(out_file,"%s = %d",p->string,p->n_val);
692: else
693: fprintf(out_file,"%s",p->string);
694: }
695: if (px) puttok(CM);
696: p->n_initializer = 0;
697: delete p;
698: }
699: mem = 0;
700: puttok(RC);
701: puttok(SM);
702: }
703:
704: void name::print()
705: { // print just the name itself
706: if (this == 0) error('i',"0->N::print()");
707: if (string == 0) {
708: if (emode) putch('?');
709: return;
710: }
711:
712: // error( 'd', "%s->name::print(), base: %k", string, base );
713: switch (base) {
714: case TNAME:
715: if (n_key == NESTED && tpdef &&
716: tpdef->nested_sig) {
717: if ( emode == 0 ) {
718: putstring( " __" );
719: putst(tpdef->nested_sig);
720: }
721: else {
722: putst(tpdef->in_class->string);
723: putstring( "::" );
724: putst(string);
725: }
726: return;
727: }
728:
729: if (emode && tp) {
730: if (n_template_arg_string) {
731: tp->dcl_print(0); return;
732: } else
733: if(tp->base == COBJ) {
734: Pclass cl = Pclass(Pbase(tp)->b_name->tp);
735: if(cl && cl->base == CLASS &&
736: (cl->class_base == instantiated_template_class)) {
737: Ptclass(cl)->inst->print_pretty_name(); return;
738: }
739: }
740: }
741:
742: putst(n_template_arg_string ? n_template_arg_string : string);
743: return;
744:
745: case MDOT:
746: Pexpr(this)->print();
747: return;
748: }
749:
750: if (emode) {
751: Ptable tbl;
752: char* cs = 0;
753: bit f = 0;
754: if (tp) {
755: switch (tp->base) {
756: case OVERLOAD:
757: case FCT:
758: f = 1;
759: default:
760: if (tbl=n_table) {
761: if (tbl == gtbl) {
762: if (f == 0) putstring("::");
763: }
764: else {
765: if (tbl->t_name) {
766: Ptclass pc = Ptclass(tbl->t_name->tp);
767: cs = tbl->t_name->string;
768: if ((pc->base == CLASS) &&
769: (pc->class_base == instantiated_template_class))
770: pc->inst->print_pretty_name();
771: else fprintf(out_file,"%s",cs);
772: fprintf (out_file, "::") ;
773: }
774: }
775: }
776:
777: if (n_scope==ARG && strcmp(string,"this")==0) {
778: // tell which "this" it is
779: Ptype tt = Pptr(tp)->typ;
780: Pname cn = Pbase(tt)->b_name;
781: fprintf(out_file,"%s::",cn->string);
782: }
783:
784: case CLASS:
785: case ENUM:
786: // case TYPE:
787: break;
788: }
789: nop:
790: switch (n_oper) {
791: case TYPE:
792: putstring("operator ");
793: if (tp) Pfct(tp)->returns->dcl_print(0);
794: break;
795: case 0:
796: putstring(string);
797: break;
798: case DTOR:
799: putch('~');
800: case CTOR:
801: if (cs) {
802: if(tbl->t_name) {
803: Ptclass pc = Ptclass(tbl->t_name->tp);
804: if ((pc->base == CLASS) &&
805: (pc->class_base == instantiated_template_class))
806: pc->inst->print_pretty_name();
807: else putstring(cs);
808: }
809: }
810: else {
811: if (string)
812: fprintf(out_file,"%s()", n_template_arg_string
813: ? n_template_arg_string : string);
814: else putstring("constructor");
815: f = 0;
816: }
817: break;
818: case TNAME:
819: putstring(string);
820: break;
821: default:
822: putstring("operator ");
823: putstring(keys[n_oper]);
824: break;
825: }
826: if (f) putstring("()");
827: }
828: else {
829: if (n_oper) goto nop;
830: if (string)
831: putstring(n_template_arg_string
832: ? n_template_arg_string : string);
833: }
834: return;
835: }
836:
837: char* sig = 0;
838: Pclass cl = 0;
839: Penum en = 0;
840: int i = n_union;
841:
842: if (tp) {
843: Ptable tbl;
844:
845: switch (tp->base) {
846: default:
847: if (tbl=n_table) { // global or member
848: Pname tn;
849: if (tbl == gtbl) {
850: // if (i) fprintf(out_file,"__O%d.",i);
851: if ( i ) {
852: if (n_anon)
853: fprintf(out_file,"__O%d.%s.", i, n_anon );
854: else fprintf(out_file,"__O%d.",i);
855: }
856: break;
857: }
858:
859: if (tn=tbl->t_name) {
860: cl = Pclass(tn->tp);
861: if (i) {
862: if (cl->string[0]=='_'
863: && cl->string[1]=='_'
864: && cl->string[2]=='C' ) {
865: if (n_anon)
866: fprintf(out_file,"__O%d.%s.", i, n_anon );
867: else fprintf(out_file,"__O%d.",i);
868: }
869: else
870: if ( cl->nested_sig )
871: fprintf(out_file,"__O%d__%s.",i,cl->nested_sig);
872: else
873: if ( cl->lex_level ) {
874: char *str = make_local_name(cl,1);
875: fprintf(out_file,"__O%d%s.",i,str);
876: delete str;
877: }
878: else fprintf(out_file,"__O%d__%d%s.",i,cl->strlen,cl->string);
879: cl = 0;
880: }
881: else
882: if (cl->string[0]=='_'
883: && cl->string[1]=='_'
884: && cl->string[2]=='C'
885: && n_stclass != STATIC )
886: cl = 0;
887: break;
888: }
889: }
890:
891: switch (n_stclass) { // local variable
892: case STATIC:
893: case EXTERN:
894: if (i)
895: fprintf(out_file,"__O%d.",i);
896: else if (n_sto==STATIC && tp->base!=FCT) {
897: if (lex_level == 0)
898: putstring("__S");
899: else
900: fprintf(out_file,"__%d",lex_level);
901: }
902: break;
903: default:
904: // encode with lexical level UNLESS ``special''
905: // e.g. __builtin
906: if (string[0]!='_' || string[1]!='_' || string[2] != 'C' ) {
907: if (i)
908: {
909: if (n_anon)
910: fprintf(out_file,"__%d__O%d.%s.",lex_level-1,i,n_anon);
911: else fprintf(out_file,"__%d__O%d.",lex_level-1,i);
912: }
913: else
914: fprintf(out_file,"__%d",lex_level);
915: }
916: }
917: break;
918: case CLASS:
919: case ENUM:
920: if (tp->in_class && tp->nested_sig) en = Penum(tp);
921: break;
922: }
923:
924: if (tp->base==FCT) {
925: sig = Pfct(tp)->f_signature;
926: if (sig && sig[0]==0) sig = 0;
927: }
928: }
929:
930: if (string) {
931: #ifdef DENSE
932: int i = strlen(string);
933: if (cl) i += cl->strlen+4; // __dd<class name>
934: if (sig) {
935: if (cl == 0) i += 2;
936: i += strlen(sig);
937: }
938:
939: if (31<i) {
940: char buf[256];
941: if (cl && sig)
942: sprintf(buf,"%s__%d%s%s",string,cl->strlen,cl->string,sig);
943: else if (cl)
944: sprintf(buf,"%s__%d%s",string,cl->strlen,cl->string);
945: else if (sig)
946: sprintf(buf,"%s__%s",string,sig);
947: else
948: sprintf(buf,"%s",string);
949: chop(buf);
950: fprintf(out_file,"%s ",buf);
951: return;
952: }
953: #endif
954:
955: if ( en )
956: fprintf(out_file,"__%s", en->nested_sig);
957: else
958: putstring(n_template_arg_string
959: ? n_template_arg_string : string);
960:
961: if ( cl ) {
962: if ( cl->nested_sig )
963: fprintf(out_file,"__%s",cl->nested_sig);
964: else
965: if ( cl->lex_level ) {
966: char *str = make_local_name( cl, 1 );
967: putstring( str );
968: delete str;
969: }
970: else fprintf(out_file,"__%d%s",cl->strlen,cl->string);
971: }
972:
973: if (sig) {
974: if (cl == 0) putstring("__");
975: putstring(sig);
976: }
977: putch(' ');
978: }
979: }
980:
981: #ifdef DENSE
982: void chop(char* buf)
983: {
984: static char alpha[] = "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
985: static const asz = sizeof(alpha)-1;
986: int hash = 0;
987: char* p = &buf[29];
988:
989: while (*p) {
990: hash <<= 1;
991: if (hash & (1<<12)) {
992: hash &= ~(1<<12);
993: hash++;
994: }
995: hash ^= *p++;
996: }
997:
998: buf[29] = alpha[(int)(hash%asz)];
999: buf[30] = alpha[(int)((hash/asz)%asz)];
1000: buf[31] = 0;
1001: }
1002: #endif
1003:
1004: void type::print()
1005: {
1006: switch (base) {
1007: case PTR:
1008: case RPTR:
1009: case VEC:
1010: Pptr(this)->dcl_print(0);
1011: break;
1012: case FCT:
1013: Pfct(this)->dcl_print();
1014: break;
1015: // case VEC:
1016: // Pvec(this)->dcl_print(0);
1017: // break;
1018: case CLASS:
1019: case ENUM:
1020: if (emode)
1021: fprintf(out_file,"%k",base);
1022: else
1023: // error('i',"%p->T::print(%k %s)",this,base,Pclass(this)->string);
1024: fprintf(out_file,"struct %s *",Pclass(this)->string);
1025: break;
1026: case TYPE:
1027: if (Cast||Pbase(this)->b_name->lex_level) {
1028: Pbase(this)->b_name->tp->print();
1029: break;
1030: }
1031: // no break
1032: default:
1033: Pbase(this)->dcl_print();
1034: }
1035: }
1036:
1037: char* type::signature(register char* p)
1038: /*
1039: take a signature suitable for argument types for overloaded
1040: function names
1041: */
1042: {
1043: Ptype t = this;
1044: int pp = 0; // pointer to
1045:
1046: xx:
1047: //error('d',"xx(%d) %d %k",this,t,t->base);
1048:
1049: // first unroll typedefs and handle derived types:
1050:
1051: switch (t->base) {
1052: case TYPE:
1053: if (Pbase(t)->b_const) *p++ = 'C';
1054: t = Pbase(t)->b_name->tp;
1055: goto xx;
1056:
1057: case VEC:
1058: if (pp && Pvec(t)->size) { // A<size>_
1059: *p++ = 'A';
1060: sprintf(p,"%d\0",Pvec(t)->size); // don't trust
1061: // sprintf return value
1062: while (*++p);
1063: *p++ = '_';
1064: }
1065: else
1066: *p++ = 'P';
1067: t = Pvec(t)->typ;
1068: pp = 1;
1069: goto xx;
1070:
1071: case PTR:
1072: if (Pptr(t)->rdo) *p++ = 'C'; // *const
1073: if (Pptr(t)->memof) { // M<size><classname>
1074: Pclass cl = Pptr(t)->memof;
1075: register char* s = cl->string;
1076: int d = cl->strlen;
1077: if (d==0) cl->strlen = d = strlen(s);
1078: *p++ = 'M';
1079: if (d/10) *p++ = '0'+d/10;
1080: *p++ = '0'+ d%10; // assume <100 char
1081: while (*p++ = *s++);
1082: --p; // not the '\0'
1083: }
1084: else
1085: *p++ = 'P';
1086: t = Pptr(t)->typ;
1087: pp = 1;
1088: goto xx;
1089:
1090: case RPTR:
1091: *p++ = 'R';
1092: t = Pptr(t)->typ;
1093: pp = 1;
1094: goto xx;
1095:
1096: case FCT:
1097: { Pfct f = Pfct(t);
1098: Pname n = f->argtype;
1099:
1100: if (f->f_const) *p++ = 'C'; // constant member function
1101: if (f->f_static) *p++ = 'S'; // static member function
1102: // if (f->memof && f->f_this==0) *p++ = 'S'; //SSS static member function
1103: *p++ = 'F';
1104: if (n == 0)
1105: *p++ = 'v'; // VOID, that is f() == f(void)
1106: else
1107: for ( ; n; n=n->n_list) { // print argument encoding
1108: // check if argtype is the same
1109: // as previously seen argtype
1110: int i = 0;
1111: for (Pname nn=f->argtype; n!=nn; nn=nn->n_list) {
1112: i++;
1113: if (nn->tp==n->tp || nn->tp->check(n->tp,0)==0) {
1114: // typeof (n) == typeof(arg i)
1115: int x = 1; // try for a run after n
1116: Pname nnn = n;
1117: while ((nnn=nnn->n_list) && x<9) {
1118: if (nnn->tp==n->tp
1119: || nnn->tp->check(n->tp,0)==0) {
1120: x++;
1121: n = nnn;
1122: }
1123: else
1124: break;
1125: }
1126:
1127: if (x == 1) // Ti
1128: *p++ = 'T';
1129: else { // Nxi
1130: *p++ = 'N';
1131: *p++ = '0'+x;
1132: }
1133:
1134: // assume <100 arguments
1135: if (9<i) *p++ = '0'+i/10;
1136: *p++ = '0'+i%10;
1137: goto zk;
1138: }
1139: }
1140:
1141: // ``normal'' case print argument type signature
1142: // if (n->n_xref) *p++ = 'R';
1143: p = n->tp->signature(p);
1144: zk:;
1145: }
1146:
1147: if (f->nargs_known == ELLIPSIS) *p++ = 'e';
1148:
1149: if (pp) { // '_' result type
1150: *p++ = '_';
1151: p = f->returns->signature(p);
1152: }
1153:
1154: *p = 0;
1155: return p;
1156: }
1157: }
1158:
1159: // base type modifiers:
1160:
1161: if ( Pbase(t)->b_const ) *p++ = 'C';
1162: // if ( Pbase(t)->b_signed ) *p++ = 'S';
1163: if ( Pbase(t)->b_unsigned ) *p++ = 'U';
1164: // if ( Pbase(t)->b_volatile ) *p++ = 'V';
1165:
1166:
1167: // now base types:
1168:
1169: register char *s, *ns = 0;;
1170: int d;
1171: Pclass cl;
1172: //lll:
1173: switch (t->base) {
1174: // case TNAME: t = Pbase(t)->b_name->tp; goto lll;
1175: case ANY: break;
1176: case ZTYPE: break;
1177: case VOID: *p++ = 'v'; break;
1178: case CHAR: *p++ = 'c'; break;
1179: case SHORT: *p++ = 's'; break;
1180: // case EOBJ:
1181: case INT: *p++ = 'i'; break;
1182: case LONG: *p++ = 'l'; break;
1183: case FLOAT: *p++ = 'f'; break;
1184: case DOUBLE: *p++ = 'd'; break;
1185: case LDOUBLE: *p++ = 'r'; break;
1186: case EOBJ:
1187: // *p++ = 'i';
1188: // break;
1189: { Penum en = Penum(Pbase(t)->b_name->tp);
1190: // t = en->e_type;
1191: // goto lll;
1192: ns = en->nested_sig;
1193: s = en->string;
1194: d = en->strlen;
1195: if (d==0) en->strlen = d = strlen(s);
1196: goto pppp;
1197: }
1198:
1199: case COBJ:
1200: { cl = Pclass(Pbase(t)->b_name->tp);
1201: ns = cl->nested_sig;
1202: s = cl->string;
1203: d = cl->strlen;
1204: if (d==0) cl->strlen = d = strlen(s);
1205: pppp:
1206: if ( ns == 0 ) {
1207: if (d/10) *p++ = '0'+d/10;
1208: *p++ = '0'+ d%10; // assume less that 99 characters
1209: }
1210: else s = ns;
1211:
1212: while (*p++ = *s++);
1213: --p;
1214: break;
1215: }
1216: case FIELD:
1217: default:
1218: error('i',"signature of %k",t->base);
1219: }
1220:
1221: *p = 0;
1222: return p;
1223: }
1224:
1225: void basetype::dcl_print()
1226: {
1227: Pname nn;
1228: Pclass cl;
1229:
1230: if (emode) {
1231: if (b_virtual) puttok(VIRTUAL);
1232: if (b_inline) puttok(INLINE);
1233: }
1234: if(ansi_opt || emode)
1235: if (b_const) puttok(CONST);
1236: if (b_unsigned) puttok(UNSIGNED);
1237:
1238: switch (base) {
1239: case ANY:
1240: if (emode)
1241: putstring("any ");
1242: else
1243: putstring("int ");
1244: break;
1245:
1246: case ZTYPE:
1247: if (emode)
1248: putstring("zero ");
1249: else
1250: putstring("int ");
1251: break;
1252:
1253: case VOID:
1254: if (emode==0 && ansi_opt==0) {
1255: // silly trick to bypass BSD C compiler bug
1256: // void* (*)() dosn't work there
1257: // note simpl.c knows that VOID -> CHAR grep for VCVC
1258: puttok(CHAR);
1259: break;
1260: }
1261: case CHAR:
1262: case SHORT:
1263: case INT:
1264: case LONG:
1265: case FLOAT:
1266: case DOUBLE:
1267: case LDOUBLE:
1268: puttok(base);
1269: break;
1270:
1271: case EOBJ:
1272: nn = b_name;
1273: eob:
1274: if (emode == 0)
1275: // puttok(INT);
1276: Penum(nn->tp)->e_type->dcl_print();
1277: else {
1278: puttok(ENUM);
1279: nn->print();
1280: }
1281: break;
1282:
1283: case COBJ:
1284: nn = b_name;
1285: cob:
1286: cl = Pclass(nn->tp);
1287: if (emode && (cl->base == CLASS) &&
1288: (cl->class_base == instantiated_template_class)) {
1289: Ptclass(cl)->inst->print_pretty_name();
1290: break;
1291: } else
1292: if (cl && (cl->csu==UNION || cl->csu==ANON))
1293: puttok(UNION);
1294: else puttok(STRUCT);
1295: {
1296: char* s = 0;
1297: if ( cl && cl->nested_sig )
1298: fprintf(out_file," __%s ",cl->nested_sig);
1299: else {
1300: if ( cl && cl->lex_level )
1301: s = make_local_name( cl );
1302: putst(s?s:nn->string);
1303: delete s;
1304: }
1305: }
1306: break;
1307:
1308: case TYPE:
1309: if (emode == 0) {
1310: switch (b_name->tp->base) {
1311: case COBJ:
1312: nn = Pbase(b_name->tp)->b_name;
1313: goto cob;
1314: case EOBJ:
1315: nn = Pbase(b_name->tp)->b_name;
1316: goto eob;
1317: }
1318: }
1319: b_name->print();
1320: break;
1321:
1322: default:
1323: if (emode) {
1324: if (0<base && base<=MAXTOK && keys[base])
1325: fprintf(out_file," %s",keys[base]);
1326: else
1327: putch('?');
1328: }
1329: else
1330: error('i',"%p->BT::dcl_print(%d)",this,base);
1331: }
1332: }
1333: Pbase memptr_type;
1334:
1335: void type::dcl_print(Pname n)
1336: /*
1337: "this" type is the type of "n". Print the declaration
1338: */
1339: {
1340: //error('d',"%p::dcl_print(%n)",this,n);
1341: Ptype t = this;
1342: Pptr p;
1343: TOK pre = 0;
1344:
1345: if (t == 0) error('i',"0->dcl_print()");
1346: if (n && n->tp!=t) error('i',"not %n'sT (%p)",n,t);
1347:
1348: if (base == OVERLOAD) {
1349: for (Plist gl=Pgen(this)->fct_list; gl; gl=gl->l) {
1350: Pname nn = gl->f;
1351: nn->tp->dcl_print(nn);
1352: if (gl->l) puttok(SM);
1353: }
1354: return;
1355: }
1356:
1357: tbuf = tbufvec[freetbuf];
1358: if (tbuf == 0) {
1359: if (freetbuf == NTBUF-1) error('i',"AT nesting overflow");
1360: tbufvec[freetbuf] = tbuf = new class dcl_buf;
1361: }
1362: freetbuf++;
1363: if ( base==FIELD && Pbase(this)->b_bits == 0 )
1364: tbuf->init(0);// some compilers can't handle mangled names here
1365: else
1366: tbuf->init(n);
1367: if (n && n->n_xref) tbuf->front(PTR);
1368:
1369: while (t) {
1370: TOK k;
1371:
1372: switch (t->base) {
1373: case PTR:
1374: p = Pptr(t);
1375: k = (p->rdo) ? CONST_PTR : PTR;
1376: goto ppp;
1377: case RPTR:
1378: p = Pptr(t);
1379: k = (p->rdo) ? CONST_RPTR : RPTR;
1380: ppp:
1381: if (p->memof) {
1382: if (emode) {
1383: tbuf->front(k);
1384: tbuf->front(p->memof);
1385: }
1386: else {
1387: t = p->typ;
1388: while (t->base==TYPE) t = Pbase(t)->b_name->tp;
1389: if (t->base == FCT) {
1390: tbuf->base(mptr_type);
1391: goto zaq;
1392: }
1393: else
1394: tbuf->front(k);
1395: }
1396: }
1397: else
1398: tbuf->front(k);
1399: pre = PTR;
1400: t = p->typ;
1401: break;
1402: case VEC:
1403: { Pvec v = Pvec(t);
1404: if (Cast && pre != PTR && pre != VEC) { // for Macintosh: ptr to array uses [] notation
1405: tbuf->front(PTR);
1406: pre = PTR;
1407: }
1408: else {
1409: if (pre == PTR) tbuf->paran();
1410: tbuf->back(VEC,v);
1411: pre = VEC;
1412: }
1413: t = v->typ;
1414: break;
1415: }
1416:
1417: case FCT:
1418: { Pfct f = Pfct(t);
1419: if (pre == PTR)
1420: tbuf->paran();
1421: else if (emode && f->memof && n==0)
1422: tbuf->front(f->memof);
1423: tbuf->back(FCT,f);
1424: pre = FCT;
1425: t = (f->s_returns) ? f->s_returns : f->returns;
1426: break;
1427: }
1428: case FIELD:
1429: tbuf->back(FIELD,t);
1430: tbuf->base( Pbase(Pbase(t)->b_fieldtype) );
1431: t = 0;
1432: break;
1433: case 0:
1434: if(!emode)error('i',"noBT(B=0)");
1435: goto dobase;
1436: case TYPE:
1437: if (Cast||Pbase(t)->b_name->lex_level) { // unravel type in case it contains vectors
1438: t = Pbase(t)->b_name->tp;
1439: break;
1440: }
1441: default: // the base has been reached
1442: dobase:
1443: if (emode) {
1444: char* s;
1445: for (Ptype tt = t; tt->base==TYPE; tt=Pbase(tt)->b_name->tp);
1446: switch (tt->base) {
1447: case CLASS:
1448: s = Pclass(tt)->string;
1449: if (Ptclass(this)->class_base == instantiated_template_class ||
1450: Ptclass(this)->class_base == uninstantiated_template_class) {
1451: Ptclass(this)->inst->print_pretty_name();
1452: --freetbuf;
1453: return;
1454: }
1455: if (s[0]=='_' &&s[1]=='_' && s[2]=='C') s="class";
1456: goto fret;
1457: case ENUM:
1458: s = "enum";
1459: goto fret;
1460: case OVERLOAD:
1461: s = "overloaded";
1462: fret:
1463: putstring(s);
1464: freetbuf--;
1465: return;
1466: }
1467: }
1468:
1469: tbuf->base( Pbase(t) );
1470: goto zaq;
1471: } // switch
1472: } // while
1473: zaq:
1474: tbuf->put();
1475: freetbuf--;
1476: }
1477:
1478: void fct::dcl_print()
1479: {
1480: Pname nn;
1481: //error('d',"fct::dcl_print()");
1482: if (emode) {
1483: putch('(');
1484: for (nn=argtype; nn;) {
1485: nn->tp->dcl_print(0);
1486: if (nn=nn->n_list) puttok(CM); else break;
1487: }
1488: switch (nargs_known) {
1489: case 0: // putst("?"); break;
1490: case ELLIPSIS: puttok(ELLIPSIS); break;
1491: }
1492: putch(')');
1493: if (f_const) puttok(CONST);
1494: if (f_static) puttok(STATIC); // wrong place for ``static''
1495: return;
1496: }
1497:
1498: Pname at = f_args;
1499: putch('(');
1500:
1501: if (ansi_opt) {
1502: // print typed arguments:
1503: at = (f_this) ? f_this : (f_result) ? f_result : argtype;
1504: // WNG -- note: at = f_args had 0 value with ansi_opt set
1505: // mystery fix added here
1506: if (at == 0) {
1507: if (nargs_known == ELLIPSIS) {
1508: putch(')');
1509: return;
1510: }
1511: puttok(VOID);
1512: }
1513: else if (body && Cast==0)
1514: at->dcl_print(CM); // print argument type and name
1515: else {
1516: for (nn=at; nn;) {
1517: // nn->tp->dcl_print(0); // print argument type
1518: nn->tp->dcl_print(nn); // print argument type
1519: // (there may not be a name)
1520: if (nn=nn->n_list) puttok(CM); else break;
1521: }
1522: }
1523: if (nargs_known == ELLIPSIS) putstring(",...");
1524: putch(')');
1525: }
1526: else {
1527: // print argument names followed by argument type declarations:
1528: if (body && Cast==0) {
1529: for (nn=at; nn;) {
1530: nn->print();
1531: if (nn=nn->n_list) puttok(CM); else break;
1532: }
1533: #ifdef mips
1534: if (nargs_known == ELLIPSIS)
1535: putstring(", va_alist");
1536: #endif
1537: #ifdef sparc
1538: if (nargs_known == ELLIPSIS)
1539: putstring(", __builtin_va_alist");
1540: #endif
1541: putch(')');
1542: }
1543: else
1544: putch(')');
1545: }
1546: }
1547:
1548: void print_body(Pfct f)
1549: {
1550: if (Cast==0) {
1551:
1552: if (ansi_opt==0 && f->f_args) {
1553: f->f_args->dcl_print(SM);
1554: if ( last_ll==0 && (last_ll = f->body->where.line) )
1555: f->body->where.putline();
1556: }
1557:
1558: if (MAIN) {
1559: putstring("{ _main(); "); // call constructors
1560: f->body->print();
1561: puttok(RC);
1562: }
1563: else
1564: f->body->print();
1565: }
1566: }
1567:
1568: Pbcl shared_seen;
1569:
1570: void classdef::print_members()
1571: {
1572: int i;
1573:
1574: Pbcl l = baselist;
1575: // error('d',"%t->print_members()",this);
1576: if (l) {
1577: if (l->base == NAME) {
1578: l->bclass->print_members(); // first base only
1579: // pad to ensure alignment:
1580: int boff = l->bclass->real_size;
1581: int ba = l->bclass->align();
1582: int xtra = boff%ba;
1583: int waste = (xtra) ? ba-xtra : 0; // padding
1584: //error('d',"%s: size % align %d waste %d",string,boff,ba,waste);
1585: if (waste) {
1586: // waste it to protect against structure
1587: // assignments to the base class
1588: char* s = make_name('W');
1589: fprintf(out_file,"char %s[%d];\n",s,waste);
1590: delete s;
1591: }
1592: l = l->next;
1593: }
1594:
1595: for (; l; l=l->next)
1596: /* for second base etc. one must allocate as an object
1597: (rather than a list of members) to ensure proper alignment
1598: for shared base allocate a pointer
1599: size, alignment, & offset handled in cassdef::dcl()
1600: */
1601: if (l->base == NAME) {
1602: Pclass bcl = l->bclass;
1603: char *str = 0;
1604: char *cs = bcl->nested_sig?bcl->nested_sig:bcl->string;
1605: if (bcl->lex_level &&
1606: bcl->nested_sig==0)
1607: str=make_local_name(bcl);
1608: puttok(STRUCT);
1609: putst(str?str:cs);
1610: putcat('O',bcl->string); // leave as unencoded
1611: puttok(SM);
1612: delete str;
1613: }
1614: }
1615:
1616: // Sam: A class or an enum type declared within a class can hide a
1617: // member with the same name, so make sure that it gets printed by
1618: // traversing the n_tbl_list to get at these names.
1619: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i)) {
1620: do { if (nn->base==NAME
1621: && nn->n_union==0
1622: && nn->tp->base!=FCT
1623: && nn->tp->base!=OVERLOAD
1624: && nn->tp->base!=CLASS
1625: && nn->tp->base!=ENUM
1626: && nn->n_stclass != STATIC) {
1627: // if (nn->tp->base==FIELD && Pbase(nn->tp)->b_bits==0) continue;
1628: Pexpr i = nn->n_initializer;
1629: nn->n_initializer = 0;
1630: nn->dcl_print(0);
1631: nn->n_initializer = i;
1632: }
1633: } while ((nn->base == NAME) &&
1634: ((nn->tp->base!=CLASS) || (nn->tp->base!=ENUM)) &&
1635: (nn = nn->n_tbl_list)) ;
1636: }
1637:
1638: for (l=baselist; l; l=l->next)
1639: if (l->base==VIRTUAL && l->ptr_offset) {
1640: Pclass bcl = l->bclass;
1641: char* str = 0;
1642: char *cs = bcl->nested_sig?bcl->nested_sig:bcl->string;
1643: if (bcl->lex_level &&
1644: bcl->nested_sig==0)
1645: str=make_local_name(bcl);
1646: puttok(STRUCT);
1647: putst(str?str:cs);
1648: putch('*');
1649: putcat('P',bcl->string); // leave unencoded
1650: puttok(SM);
1651: delete str;
1652: }
1653: }
1654:
1655: // void classdef::print_vtbl(Pvirt vtab)
1656: // {
1657: // error('d',"%s->print_vtbl(%s) vtbl_opt %d",string,vtab->string,vtbl_opt);
1658: // error('d',"print_vtbl: lex_level: %d", lex_level );
1659: //
1660: // switch (vtbl_opt) {
1661: // case -1:
1662: // case 1:
1663: // vlist = new vl(this,vtab,vlist);
1664: // }
1665: //
1666: // int oo = vtbl_opt; // make `simulated static' name
1667: // vtbl_opt = -1;
1668: // char* str = lex_level ? make_local_name(this) : 0;
1669: // char* s = vtbl_name(vtab->string,str?str:string);
1670: // vtbl_opt = oo;
1671: // fprintf(out_file,"extern struct __mptr %s[];\n",s);
1672: // s[2] = 'p'; // pointer, not tbl itself
1673: // fprintf(out_file,"extern struct __mptr* %s;\n",s);
1674: //
1675: // delete s;
1676: // delete str;
1677: // }
1678:
1679: vl* vlist;
1680:
1681: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss);
1682:
1683: int p2(Pname nn, Ptype t, Pclass cl, Pvirt vtab, char* s)
1684: {
1685: int init;
1686:
1687: if (t->base == FCT) {
1688: Pfct f = Pfct(t);
1689:
1690: //error('d',"p2 %n init %d inline %d virtual %d",nn,nn->n_initializer,f->f_inline,f->f_virtual);
1691: //error('d',"p2 %s expr %d imeasure %d body %d",s,f->f_expr,f->f_imeasure,f->body);
1692: //error('d',"sto %k",nn->n_sto);
1693: if (nn->n_initializer
1694: || nn->n_sto==STATIC
1695: || f->f_inline
1696: || f->f_imeasure
1697: || f->f_virtual==0) return 0;
1698: init = f->body!=0;
1699: }
1700: else
1701: init = nn->n_initializer!=0;
1702:
1703: int oo = vtbl_opt;
1704: vtbl_opt = 1; // make sure the name is universal
1705: char *cs = cl->nested_sig?cl->nested_sig:cl->string;
1706: char* sstr = (cl->lex_level&&cl->nested_sig==0)? make_local_name(cl) : 0;
1707: char* ss = vtbl_name(vtab->string,sstr?sstr:cs);
1708:
1709: if (init) { // unique definition here
1710: really_really_print(cl,vtab,ss,s);
1711: }
1712: else { // unique definition elsewhere
1713: char *vstr = 0;
1714: if ( vtab && vtab->string ) {
1715: vstr = new char[strlen(vtab->string)+cl->strlen+1];
1716: strcpy( vstr, vtab->string );
1717: strcat( vstr, cl->string );
1718: }
1719: Pname nn;
1720: if (nn=ptbl->look(vstr?vstr:cl->string,0)) { // use of ptbl in file
1721: fprintf(out_file,"extern struct __mptr %s[];\n",ss);
1722: s[2] = 'p';
1723: // fprintf(out_file,"struct __mptr* %s = ",s);
1724: // fprintf(out_file,"%s;\n",ss);
1725: ptbl_add_pair(s, ss);
1726: nn->n_key=HIDDEN;
1727: }
1728: delete vstr;
1729: }
1730: vtbl_opt = oo;
1731:
1732: delete ss;
1733: delete sstr;
1734:
1735: return 1;
1736: }
1737:
1738: void classdef::really_print(Pvirt vtab)
1739: {
1740: // error('d',"really_print %t %d",this,vtbl_opt);
1741: int oo = vtbl_opt; // make `simulated static' name
1742: vtbl_opt = -1;
1743: char *cs = nested_sig?nested_sig:string;
1744: char* str = (lex_level&&nested_sig==0) ? make_local_name(this) : 0;
1745: char* s = vtbl_name(vtab->string,str?str:cs);
1746: // error('d', "really_print: %s, vtab: %s, s: %s", string, vtab->string, s );
1747: vtbl_opt = oo;
1748:
1749: // see if needed
1750: int i;
1751: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
1752: Ptype t = nn->tp;
1753: zse:
1754: if (t)
1755: switch (t->base) {
1756: case TYPE:
1757: t = Pbase(t)->b_name->tp;
1758: goto zse;
1759: /*
1760: case COBJ:
1761: if (nn->n_sto == EXTERN)
1762: { Pclass cl = Pclass(Pbase(t)->b_name->tp);
1763: if (cl->has_ctor()) {
1764: p2(nn,t,this,vtab,s);
1765: return;
1766: }
1767: }
1768: break;
1769: */
1770: case FCT:
1771: if (p2(nn,t,this,vtab,s))
1772: goto xyzzy;
1773: break;
1774:
1775: case OVERLOAD:
1776: { for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l)
1777: if (p2(gl->f,gl->f->tp,this,vtab,s))
1778: goto xyzzy;
1779: }
1780: }
1781: }
1782:
1783: { // must be initialized var in block to permit goto
1784: char* ss = vtbl_name(vtab->string,str?str:cs);
1785: // error('d', "really_print: %s, vtab: %s, ss: %s", cs, vtab->string, s );
1786:
1787: if (vtbl_opt)
1788: really_really_print(this,vtab,ss,s);
1789: else {
1790: char *vstr = 0;
1791: if ( vtab && vtab->string ) {
1792: vstr = new char[::strlen(vtab->string)+strlen+1];
1793: strcpy( vstr, vtab->string );
1794: strcat( vstr, string );
1795: }
1796: Pname nn;
1797: if (nn=ptbl->look(vstr?vstr:string,0)) { // use of ptbl in file
1798: fprintf(out_file,"extern struct __mptr %s[];\n",ss);
1799: s[2] = 'p';
1800: // fprintf(out_file,"struct __mptr* %s = ",s);
1801: // fprintf(out_file,"%s;\n",ss);
1802: ptbl_add_pair(s, ss);
1803: nn->n_key=HIDDEN;
1804: }
1805: delete vstr;
1806: }
1807: delete ss;
1808: }
1809: xyzzy:
1810: delete s;
1811: delete str;
1812: }
1813:
1814: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss)
1815: {
1816: // error('d',"really %s %s",s, ss);
1817: // make sure function is declared before using
1818: // it in vtbl initializer
1819: Pname nn;
1820: int i;
1821: for (i=0; nn = vtab->virt_init[i].n; i++) {
1822: Pfct f = Pfct(nn->tp);
1823: if (nn->n_initializer) { // pure virtual
1824: static pv;
1825: if (pv == 0) { // VCVC void->char assumed
1826: fprintf(out_file,"char __pure_virtual_called();\n");
1827: pv = 1;
1828: }
1829: continue;
1830: }
1831: if (f->base != FCT) error('i',"vtbl %n",nn);
1832: //extern void expand_dtor(Pclass cl);
1833: // if (f->f_inline == IDTOR) expand_dtor(f->memof);
1834:
1835: if (nn->n_dcl_printed==0 /*|| f->f_inline*/) {
1836: if (f->f_inline && vtbl_opt) puttok(STATIC);
1837: if (f->f_result == 0) make_res(f);
1838: Ptype r = f->s_returns ? f->s_returns : f->returns;
1839: r->print();
1840: nn->print();
1841: putstring("()");
1842: puttok(SM);
1843: nn->n_dcl_printed = 1;
1844: }
1845: }
1846:
1847: // if (vtbl_opt == -1) puttok(STATIC);
1848:
1849:
1850: fprintf(out_file,"struct __mptr %s[] = {0,0,0,\n",s);
1851:
1852: Pname n;
1853: for (i=0; n=vtab->virt_init[i].n; i++) {
1854: if (n->n_initializer)
1855: putstring("0,0,(__vptp)__pure_virtual_called,\n");
1856: else {
1857: fprintf(out_file,"%d,0,(__vptp)",-vtab->virt_init[i].offset);
1858: n->print();
1859: n->n_addr_taken = 1;
1860: putstring(",\n");
1861: }
1862: }
1863: putstring("0,0,0};\n");
1864:
1865: ss[2] = 'p';
1866: // fprintf(out_file,"struct __mptr* %s = ",ss);
1867: s[2] = 'v';
1868: // fprintf(out_file,"%s;\n",s);
1869: ptbl_add_pair(ss,s);
1870:
1871: Pname nm;
1872: char *cstr = 0;
1873: char *vstr = 0;
1874: char *cs = cl->nested_sig?cl->nested_sig:cl->string;
1875: if (cl->lex_level && cl->nested_sig==0) cstr = make_local_name( cl );
1876: if ( vtab && vtab->string ) {
1877: vstr = new char[strlen(vtab->string)+(cstr?strlen(cstr):strlen(cs))+1];
1878: strcpy( vstr, vtab->string );
1879: strcat( vstr, cstr?cstr:cs );
1880: }
1881:
1882: if ( vstr == 0 ) vstr = cstr;
1883: if ( nm = ptbl->look(vstr?vstr:cl->string,0) )
1884: nm->n_key = HIDDEN;
1885: else
1886: if ( ptbl->look(vstr?vstr:cl->string,HIDDEN) == 0 )
1887: ptbl->insert(new name(vstr?vstr:cl->string),HIDDEN);
1888: if (cstr == vstr) delete cstr;
1889: else {
1890: delete cstr;
1891: delete vstr;
1892: }
1893:
1894: //error('d',"really-> %s",s);
1895: }
1896:
1897: #include <ctype.h>
1898: char* vtbl_name(char* s1, char* s2)
1899: {
1900: char* s3 = (vtbl_opt == -1 && *src_file_name) ? src_file_name : 0;
1901: // if vtbl_opt == -1 fake a static (there are no portable
1902: // way of doing a forward declaration of a static in C)
1903: int ll = s1 ? strlen(s1) : 0;
1904: int ll2 = strlen(s2);
1905: int ll3 = s3 ? strlen(s3) : 0;
1906: int sz = (ll+ll2+ll3+20)/32+1; // avoid fragmentation
1907:
1908: sz *= 32;
1909: // error('d',"vtbl_name(%s,%s,%s) %d",s1?s1:"",s2,s3?s3:"",sz);
1910: char* buf = new char[sz];
1911: if (s3) {
1912: if (s1)
1913: sprintf(buf,"__vtbl__%d%s__%d%s__%s",ll,s1,ll2,s2,s3);
1914: else
1915: sprintf(buf,"__vtbl__%d%s__%s",ll2,s2,s3);
1916: }
1917: else if (s1)
1918: sprintf(buf,"__vtbl__%d%s__%d%s",ll,s1,ll2,s2);
1919: else
1920: sprintf(buf,"__vtbl__%d%s",ll2,s2);
1921:
1922: if (vtbl_opt == -1) {
1923: for (char* p = buf+ll2+11; *p; p++)
1924: if (!isalpha(*p) && !isdigit(*p)) *p = '_';
1925: }
1926: #ifdef DENSE
1927: chop(buf);
1928: #endif
1929: return buf;
1930: }
1931:
1932: void classdef::print_all_vtbls(Pclass bcl)
1933: {
1934: //error('d',"%t->print_all_vtbls(%t) vlt %d bl %d",this,bcl,virt_list,baselist);
1935:
1936: for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) {
1937: if (this != blist->vclass) continue;
1938: if (blist->printed) continue;
1939: // if (blist->string==0 && find_vptr(this)==0) { //BSopt
1940: // continue;
1941: // }
1942: // print_vtbl(blist);
1943: vlist = new vl(this,blist,vlist);
1944: blist->printed = 1;
1945: }
1946:
1947: for (Pbcl b = bcl->baselist; b; b = b->next)
1948: print_all_vtbls(b->bclass);
1949:
1950: if (this==bcl) c_body = 0;
1951: }
1952:
1953: extern Pclass current_instantiation;
1954: void classdef::dcl_print(Pname)
1955: {
1956: //error('d',"%t->classdef::dcl_print() -- c_body==%d defined==0%o",this,c_body,defined);
1957: defined |= REF_SEEN;
1958: // ensure template instantiations are printed exactly once.
1959: if (class_base != vanilla_class && current_instantiation != this) return;
1960:
1961: if (c_body==0 || c_body==3 || (defined&DEFINED)==0) return;
1962: c_body = 3;
1963:
1964: int i;
1965: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
1966: if (nn->base==NAME
1967: && nn->n_union==0
1968: && nn->tp->base==CLASS
1969: && Pclass(nn->tp)->c_body==1)
1970: Pclass(nn->tp)->dcl_print(nn);
1971: else if (nn->base == TNAME && Pbase(nn->tp)->base != COBJ)
1972: nn->dcl_print(0);
1973: else if (nn->tp && nn->tp->base == ENUM) {
1974: if(nn->n_union==0) Penum(nn->tp)->dcl_print(nn);
1975: }
1976: }
1977:
1978: TOK lvl = in_class ? NESTED : lex_level ? LOCAL : 0;
1979: Pname n = ktbl->look(string,lvl);
1980: if (n==0) n = ktbl->look(string,HIDDEN);
1981:
1982: if (n) {
1983: if (n->where.line!=last_line.line
1984: || n->where.file!=last_line.file)
1985: if (last_ll = n->where.line)
1986: n->where.putline();
1987: else
1988: last_line.putline();
1989: }
1990:
1991: TOK c = csu==CLASS ? STRUCT : csu;
1992: puttok(c);
1993: // if (string[0]!='_' || string[1]!='_' || string[2]!='C')
1994:
1995: char *str = 0;
1996: if ( lex_level && nested_sig == 0) str = make_local_name( this );
1997: if ( nested_sig ) putstring( " __" );
1998: putst(str?str:(nested_sig?nested_sig:string));
1999:
2000: int sm = 0;
2001: int sz = tsizeof();
2002: int dvirt = 0;
2003:
2004: if ( nested_sig )
2005: fprintf(out_file,"{\t/* sizeof __%s == %d */\n",nested_sig,obj_size);
2006: else
2007: fprintf(out_file,"{\t/* sizeof %s == %d */\n",str?str:string,obj_size);
2008: if ( last_ll ) last_line.line++;
2009: delete str;
2010:
2011: print_members();
2012: for (Pbcl b = baselist; b; b = b->next) { // declare virtual classes
2013: if (b->base != VIRTUAL) continue;
2014: Pclass bcl = b->bclass;
2015: dvirt += bcl->virt_count;
2016: //error('d',"%t in %t %d",b->bclass,this,b->allocated);
2017: if (b->allocated==0) continue;
2018: char* str = 0;
2019: if (bcl->lex_level) str = make_local_name(bcl);
2020: puttok(STRUCT); // struct bcl Obcl;
2021: putst(str?str:bcl->string);
2022: putcat('O',bcl->string); // leave unencoded
2023: puttok(SM);
2024: delete str;
2025: }
2026: putstring("};\n");
2027: if ( last_ll ) last_line.line++;
2028:
2029: for (nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
2030: if (nn->base==NAME && nn->n_union==0) {
2031: Ptype t = nn->tp;
2032: switch (t->base) {
2033: case FCT:
2034: case OVERLOAD:
2035: break;
2036: default:
2037: if (nn->n_stclass == STATIC) {
2038: TOK b = nn->n_sto;
2039: //error('d',"print nn %n tp %t b %k eval %d",nn,nn->tp,b,nn->n_evaluated);
2040: /*
2041: Pname cn;
2042: TOK bb = ((cn=nn->tp->is_cl_obj())
2043: && Pclass(cn->tp)->has_ctor())==0
2044: ?0:b; // force explicit initialization
2045: nn->n_sto = (nn->n_evaluated) ? STATIC : bb;
2046: */
2047: nn->n_sto = (nn->n_evaluated) ? STATIC : b;
2048: nn->dcl_print(0);
2049: nn->n_sto = b;
2050: }
2051: }
2052: }
2053: }
2054: if (vtbl_opt != -1) print_all_vtbls(this); // force declaration
2055: //error('d',"dcl_print -> ");
2056: }
2057:
2058:
2059: char *
2060: make_local_name( Pclass cl, int ln )
2061: {
2062: char *buf;
2063: if ( cl->in_fct == 0 ) error( 'i', "localC %s missingFN", cl->string );
2064: char *fsig = Pfct(cl->in_fct->tp)->f_signature;
2065: if ( fsig == 0 ) fsig = local_sign( cl->in_fct->tp );
2066: char *fs = cl->in_fct->string;
2067: int class_len=cl->strlen+strlen(fsig)+strlen(fs)+strlen(cl->lcl)+4;
2068: int sz = (class_len+20)/32+1; // from vtbl_name()
2069:
2070: if ( Pfct(cl->in_fct->tp)->memof == 0 ) {
2071: sz *= 32;
2072: buf = new char[ sz ];
2073: // error('d', "make_local_name: sz: %d", sz );
2074:
2075: if (ln)
2076: sprintf(buf, "__%d%s__%s__%s%s", class_len, cl->string, fs, fsig, cl->lcl);
2077: else
2078: sprintf(buf, "%s__%s__%s%s", cl->string, fs, fsig, cl->lcl);
2079: }
2080: else
2081: {
2082: char *cs = Pclass(Pfct(cl->in_fct->tp)->memof)->string;
2083: int len = Pclass(Pfct(cl->in_fct->tp)->memof)->strlen;
2084: if ( len < 10 )
2085: ++class_len;
2086: else
2087: if ( len > 99 )
2088: class_len += 3;
2089: else class_len += 2;
2090: class_len += len;
2091: sz = (class_len+20)/32+1;
2092: sz *= 32;
2093: buf = new char[ sz ];
2094: // error('d', "make_local_name: sz: %d", sz );
2095:
2096: if ( ln )
2097: sprintf(buf, "__%d%s__%s__%d%s%s%s",class_len,cl->string,fs,len,cs,fsig,cl->lcl);
2098: else sprintf(buf, "%s__%s__%d%s%s%s",cl->string,fs,len,cs,fsig,cl->lcl);
2099: }
2100:
2101: #ifdef DENSE
2102: chop( buf );
2103: #endif
2104:
2105: return buf;
2106: }
2107:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.