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