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