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