|
|
1.1 root 1: /*ident "@(#)ctrans:src/print2.c 1.3.6.27" */
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: #include <string.h>
18: #include "template.h"
19:
20: extern FILE* out_file;
21: bit Cast;
22: int last_ll = 1;
23: Pin curr_icall;
24: char emode;
25: int ntok;
26:
27: static int MAIN; // fudge to get _main() called by main()
28:
29: #define eprint(e) if (e) Eprint(e)
30:
31: #ifdef DENSE
32: void chop(char*);
33: #endif
34:
35:
36: /* The following strings (new_string and tmp_string) are
37: used to capture a transformed string. The captured
38: string is then assigned to "name::output_string".
39: This is done in "name::print". */
40:
41: static char new_string[1024]; // The transformed string.
42: static char tmp_string[1024]; // Used to format the transformed string.
43:
44: /* Rick, ODI, 6-20-89: The following #define is used to control whether
45: renamings are saved. */
46:
47: #define OUTPUT_PAIR_FUNCTIONALITY 0
48:
49: #if OUTPUT_PAIR_FUNCTIONALITY
50: static void output_pair (name *declarator);
51: #endif
52:
53: /* Rick, ODI, 6-20-89: Local functions used in renaming work. */
54:
55: extern bit capture_renaming;/* Rick, ODI; used to switch off cfront renaming
56: capture. */
57: static Pname is_data_member (Pname p_name);
58: static Pname matches_base_member (Pname p_name, Pclass class_);
59: static Pname look_any (Ptable p_table, char* s);
60:
61: void puttok(TOK t)
62: /*
63: print the output representation of "t"
64: */
65: {
66: // if (t<=0 || MAXTOK<t) error("illegal token %d",t);
67: // char* s = keys[t];
68: // if (s == 0) error("V representation token %d",t);
69:
70: putstring(keys[t]);
71:
72: if(!emode) {
73: if (12<ntok++) {
74: ntok = 0;
75: last_line.putline();
76: }
77: else if (t == SM) {
78: ntok = 0;
79: putch('\n');
80: if (last_ll) last_line.line++;
81: }
82: else
83: putch(' ');
84: } else putch(' ');
85: }
86:
87: #define MX 20
88: #define NTBUF 10
89: class dcl_buf {
90: /*
91: buffer for assembling declaration (or cast)
92: left contains CONST_PTR => *CONST
93: CONST_RPTR => &CONST
94: PTR => *
95: RPTR => &
96: LP => (
97: right contains RP => )
98: VEC => [ rnode ]
99: FCT => ( rnode )
100: FIELD => : rnode
101: */
102: Pbase b;
103: Pname n;
104: TOK left[MX], right[MX];
105: Pnode rnode[MX];
106: Pclass lnode[MX];
107: int li, ri;
108: public:
109: void init(Pname nn) { b=0; n=nn; li=ri=0; }
110: void base(Pbase bb) { b = bb; }
111: void front(TOK t) { left[++li] = t; }
112: void front(Pclass c) { left[++li] = MEMPTR; lnode[li] = c; }
113: void back(TOK t, Pnode nod) { right[++ri] = t; rnode[ri] = nod; }
114: void paran() { front(LP); back(RP,0); }
115: void put();
116: } *tbufvec[NTBUF] = {0}, *tbuf = 0;
117:
118: int freetbuf = 0;
119:
120: void dcl_buf::put()
121: {
122: int i;
123: Pfct ff = 0;
124:
125: if (MX<=li || MX<=ri) error('i',"T buffer overflow");
126: if (b == 0) error('i',"noBT%s",Cast?" in cast":"");
127:
128: if (n && n->n_sto && n->n_sto!=REGISTER) puttok(n->n_sto);
129:
130: b->dcl_print();
131:
132: for( ; li; li--) {
133: switch (left[li]) {
134: case LP:
135: putch('(');
136: break;
137: case PTR:
138: putch('*');
139: break;
140: case RPTR:
141: if (emode)
142: putch('&');
143: else
144: putch('*');
145: break;
146: case CONST_PTR:
147: if (emode)
148: putstring("*const ");
149: else
150: putch('*');
151: break;
152: case CONST_RPTR:
153: if (emode)
154: putstring("&const ");
155: else
156: putch('*');
157: break;
158: case MEMPTR:
159: if (lnode[li]) {
160: char buff[1024] ;
161: fprintf(out_file,"%s::", (lnode[li]->string)) ;
162: }
163: }
164: }
165:
166: if (n) n->print();
167:
168: for(i=1; i<=ri; i++) {
169: switch (right[i]) {
170: case RP:
171: putch(')');
172: break;
173: case VEC:
174: putch('[');
175: { Pvec v = (Pvec) rnode[i];
176: Pexpr d = v->dim;
177: int s = v->size;
178: if (d) d->print();
179: if (s) fprintf(out_file,"%d",s);
180: }
181: putch(']');
182: break;
183: case FCT: // beware of function returning pointer to
184: // function expressed witout typedef
185: { Pfct f = Pfct(rnode[i]);
186: if (f->body) ff = f;
187: f->dcl_print();
188: break;
189: }
190: case FIELD:
191: { Pbase f = (Pbase) rnode[i];
192: Pexpr d = (Pexpr)f->b_name;
193: int s = f->b_bits;
194: putch(':');
195: if (d)
196: d->print();
197: else if (s)
198: fprintf(out_file,"%d",s);
199: else
200: puttok(ZERO);
201: break;
202: }
203: }
204: }
205: void print_body(Pfct);
206: if (ff && emode==0) print_body(ff);
207: }
208:
209: void name::dcl_print(TOK list)
210: /*
211: Print the declaration for a name (list==0) or a name list (list!=0):
212: For each name
213: (1) print storage class
214: (2) print base type
215: (3) print the name with its declarators
216: Avoid (illegal) repetition of basetypes which are class or enum declarations
217: (A name list may contain names with different base types)
218: list == SM : terminator SM
219: list == 0: single declaration with terminator SM
220: list == CM : separator CM
221: */
222: {
223: if (error_count) return;
224:
225: if (capture_renaming) { /* rick, ODI, 3-28-89; used to switch off some
226: cfront renaming. */
227: new_string[0] = '\0';
228: tmp_string[0] = '\0';
229: }
230:
231: for (Pname n=this; n; n=n->n_list) {
232: Ptype t = n->tp;
233: int sm = 0;
234:
235: //error('d',"%s->dcl_print() tp %t sto %k",n->string,t,n->n_sto);
236:
237: if (t == 0) error('i',"N::dcl_print(%n)T missing",n);
238:
239: if (t->base == TYPE) { // unroll local typedefs:
240: Pname bn = Pbase(t)->b_name;
241: if (bn->lex_level && (! bn->n_template_arg)
242: && bn->tp->base != COBJ
243: && bn->tp->base != EOBJ )
244: n->tp = t = bn->tp;
245: }
246:
247: switch (t->base) { // HACK, recursive unroller needed
248: case RPTR:
249: case PTR:
250: case VEC:
251: if (Pptr(t)->typ->base == TYPE) { // unroll local typedefs:
252: Pname bn = Pbase(Pptr(t)->typ)->b_name;
253: if (bn->lex_level && (! bn->n_template_arg)
254: && bn->tp->base != COBJ
255: && bn->tp->base != EOBJ )
256: Pptr(t)->typ = bn->tp;
257: }
258: }
259:
260: if (n->n_stclass==ENUM) if (list) continue; else return;
261:
262: if (n->where.line!=last_line.line || n->where.file!=last_line.file)
263: if (last_ll = n->where.line)
264: n->where.putline();
265: else
266: last_line.putline();
267:
268: int tc = Pbase(t)->b_const;
269: for (Ptype tt = t; tt->base==TYPE; tt = Pbase(tt)->b_name->tp)
270: tc |= Pbase(tt)->b_const;
271:
272: switch (t->base) {
273: case CLASS:
274: //fprintf(stderr,"class %s->dcl_print()\n",n->string);
275: if (n->base != TNAME) {
276: Pclass(t)->dcl_print(n);
277: sm = 1;
278: }
279: break;
280:
281: case ENUM:
282: Penum(t)->dcl_print(0);
283: sm = 1;
284: break;
285:
286: case FCT:
287: { Pfct f = Pfct(t);
288:
289: if (n->base == TNAME) puttok(TYPEDEF);
290:
291: //error('d',"fct %n->dcl_print() printed %d body %d defined %d",n,n->n_dcl_printed,f->body,f->defined);
292: //error('d',"n %d tbl %d tp %t inline %d",n,n->n_table,n->tp,f->f_inline);
293: if (n->n_dcl_printed==2 // definition already printed
294: || (n->n_dcl_printed==1 && f->body==0)
295: // declaration already printed
296: ) {
297: // don't print again
298: sm = 1; // no SM
299: break;
300: }
301:
302: if (f->f_result == 0) make_res(f);
303:
304: if (f->body && n->n_sto==EXTERN) n->n_sto = 0;
305:
306: if (f->f_inline) {
307: if (debug_opt) {
308: //error('d',"f %t defined %d inline %d",f,f->defined,f->f_inline);
309: if (f->defined&DEFINED
310: && f->defined&SIMPLIFIED
311: && f->f_inline!=ITOR)
312: goto prnt_def;
313: else if (n->n_dcl_printed==0)
314: goto prnt_dcl;
315: else {
316: sm = 1;
317: break;
318: }
319: }
320: if (f->f_virtual || n->n_addr_taken) {
321: prnt_dcl:
322: //error('d',"prnt_dcl %d %n %k",n,n,n->n_sto);
323: TOK st = n->n_sto;
324: Pblock b = f->body;
325: f->body = 0;
326: t->dcl_print(n);
327: n->n_dcl_printed = 1;
328: n->n_sto = st;
329: f->body = b;
330: break;
331: }
332: else
333: sm = 1; // no SM
334: }
335: else if ((f->defined&DEFINED)==0
336: || (f->defined&SIMPLIFIED)==0)
337: goto prnt_dcl;
338: else if (n->n_table==gtbl && strcmp(n->string,"main")==0) {
339: MAIN = 1;
340: gtbl->look("main",0)->use();
341: f->f_signature = 0;
342: t->dcl_print(n);
343: n->n_dcl_printed = f->body?2:1;
344: MAIN = 0;
345: }
346: else {
347: prnt_def:
348: //error('d',"prnt_def %n %k %d %k",n,n->n_oper,n,n->n_sto);
349: if (n->n_oper==CTOR || n->n_oper==DTOR) {
350: Pclass cl = Pclass(n->n_table->t_name->tp);
351: if (cl->c_body == 3) cl->print_all_vtbls(cl);
352: }
353: t->dcl_print(n);
354: n->n_dcl_printed = f->body?2:1;
355: }
356: if (f->body) sm = 1;
357: break;
358: }
359:
360: case OVERLOAD:
361: {
362: for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) {
363: Pname nn = gl->f;
364: nn->dcl_print(0);
365: sm = 1;
366: }
367: break;
368: }
369:
370: case ASM:
371: fprintf(out_file,"asm(\"%s\")\n",(char*)Pbase(t)->b_name);
372: break;
373:
374: case INT:
375: case EOBJ:
376: case CHAR:
377: case LONG:
378: case SHORT:
379: tcx:
380: // do not allocate space for constants unless necessary
381: if (tc
382: && n->n_sto!=EXTERN // extern const one;
383: // const one = 1;
384: // allocates storage
385: && (n->n_scope==EXTERN // FUDGE const one = 1;
386: // is treated as static
387: // need loader support
388: || n->n_scope==STATIC
389: || n->n_scope==FCT)
390: ) {
391: if (n->n_evaluated) {
392: sm = 1; /* no ; */
393: break;
394: }
395: }
396: tc = 0;
397: // no break;
398:
399: default:
400: {
401: /*
402: // don't print local instance of const
403: if ( n->n_dcl_printed == 3 ) {
404: sm = 1;
405: break;
406: }
407: */
408: Pexpr i = n->n_initializer;
409: if (tc) {
410: switch (tt->base) {
411: case CHAR:
412: case SHORT:
413: case INT:
414: case LONG:
415: case EOBJ:
416: goto tcx;
417: }
418: }
419:
420: if (n->base == TNAME) {
421: // Always print template formals, even when
422: // they have the same formal name, since the
423: // instantiation name is different. This fix
424: // should not be required when the copy
425: // mechanism is in place.
426: if (! n_template_arg)
427: for (Pname tn=ktbl->look(n->string,HIDDEN); tn; tn=tn->n_tbl_list)
428: if (tn
429: && tn->lex_level
430: && t==tn->tp) return;
431: puttok(TYPEDEF);
432: }
433:
434: if (n->n_stclass == REGISTER) {
435: // (imperfect) check against member functions
436: // register s a; a.f() illegal
437: Pname cln = n->tp->is_cl_obj();
438: if (cln) {
439: Pclass cl = Pclass(cln->tp);
440: if (cl->csu!=CLASS
441: && cl->baselist==0
442: && cl->has_itor()==0
443: && cl->virt_count==0) puttok(REGISTER);
444: }
445: else
446: puttok(REGISTER);
447: }
448:
449: if (i) {
450: if (n->n_sto==EXTERN && n->n_stclass==STATIC) {
451: n->n_initializer = 0;
452: t->dcl_print(n);
453: puttok(SM);
454: n->n_initializer = i;
455: n->n_sto = 0;
456: t->dcl_print(n);
457: n->n_sto = EXTERN;
458: }
459: else
460: t->dcl_print(n);
461: }
462: else if (n->n_evaluated && Pbase(t)->b_const) {
463: if (n->n_sto==EXTERN && n->n_stclass==STATIC) {
464: int v = n->n_evaluated;
465: n->n_evaluated = 0;
466: t->dcl_print(n);
467: puttok(SM);
468: n->n_evaluated = v;
469: n->n_sto = 0;
470: t->dcl_print(n);
471: n->n_sto = EXTERN;
472: }
473: else
474: t->dcl_print(n);
475: }
476: else {
477: //error('d',"%n sto %k val %d stc %k",n,n->n_sto,n->n_val,n_stclass);
478: if ((n->n_sto==0 || (n->n_val && n->n_evaluated==0))
479: && n_stclass==STATIC
480: && n->n_sto!=STATIC
481: && n->n_table==gtbl) {
482: if (n->n_val && n->n_evaluated==0) {
483: // extern x = f();
484: // generate int x = 0;
485: // plus dynamic initialization
486: n->n_sto = 0;
487: }
488: Ptype tt = t;
489: zaq:
490: switch (tt->base) {
491: case TYPE:
492: tt = Pbase(tt)->b_name->tp; goto zaq;
493: case COBJ: // "X a;" == "X a = {0};"
494: {
495: TOK csu = Pclass(Pbase(tt)->b_name->tp)->csu;
496: if (csu != UNION)
497: n->n_initializer = i = new expr(ILIST,zero,0);
498: break;
499: }
500: case PTR:
501: if (tt->memptr()) {
502: i = new expr(ELIST,zero,zero);
503: n->n_initializer = i = new expr(ILIST,i,zero);
504: break;
505: }
506: // no break
507: case CHAR:
508: case SHORT:
509: case INT:
510: case EOBJ:
511: case LONG:
512: case FLOAT:
513: case DOUBLE:
514: case LDOUBLE: // "int a;" == "int a = 0;"
515: n->n_initializer = i = zero;
516: }
517: }
518: t->dcl_print(n);
519: }
520:
521: if (n->n_scope!=ARG) {
522: if (i) {
523: puttok(ASSIGN);
524:
525: Pexpr i2 = i;
526: while (i2->base == CAST) i2 = i2->e1;
527: if (i2->base == ILIST) i = i2;
528: if (t!=i->tp
529: && i->base!=ZERO
530: && i->base!=ILIST /*&& i->tp!=Pchar_type*/) {
531: Ptype t1 = n->tp;
532: cmp:
533: switch (t1->base) {
534: case TYPE:
535: t1 = Pbase(t1)->b_name->tp;
536: goto cmp;
537: default:
538: i->print();
539: break;
540: // case EOBJ:
541: // goto cst;
542: case VEC:
543: if (Pvec(t1)->typ->base==CHAR) {
544: i->print();
545: break;
546: }
547: // no break
548: case PTR:
549: case RPTR:
550: if (i->tp==0 || n->tp->check(i->tp,0)) {
551: // cst:
552: putch('(');
553: bit oc = Cast;
554: Cast = 1;
555: t->print();
556: Cast = oc;
557: putch(')');
558: }
559: eprint(i);
560: }
561: }
562: else {
563: if (i==zero) {
564: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
565: // if (t->base == EOBJ) {
566: // putch('(');
567: // bit oc = Cast;
568: // Cast = 1;
569: // t->print();
570: // Cast = oc;
571: // putch(')');
572: // }
573: }
574: eprint(i);
575:
576: // i->print();
577: }
578: }
579: else if (n->n_evaluated) {
580: puttok(ASSIGN);
581: if (n->tp->base!=INT || n->tp->is_unsigned()) {
582: putstring("((");
583: bit oc = Cast;
584: Cast = 1;
585: n->tp->print();
586: Cast = oc;
587: fprintf(out_file,")%d)",n->n_val);
588: }
589: else
590: fprintf(out_file,"%d",n->n_val);
591: }
592: }
593: }
594: }
595:
596: switch (list) {
597: case SM:
598: if (sm==0) puttok(SM);
599: break;
600: case 0:
601: if (sm==0) puttok(SM);
602: #if OUTPUT_PAIR_FUNCTIONALITY
603: if (capture_renaming) { /* Rick, ODI, 3-28-89; used
604: to switch on renaming
605: capture. */
606: output_pair(this);
607: }
608: #endif
609: return;
610: case CM:
611: if (n->n_list) puttok(CM);
612: break;
613: }
614: }
615:
616: #if OUTPUT_PAIR_FUNCTIONALITY
617: if (capture_renaming) { /* rick, ODI, 3-28-89; used
618: to switch off some cfront
619: renaming. */
620: if (list != SM)
621: output_pair(this);
622: }
623: #endif
624:
625: }
626:
627: char *local_sign( Ptype pt )
628: { // get function signature for local class
629: char buf[1024];
630: char* bb = pt->signature(buf);
631: int ll = bb-buf;
632: if (1023 < ll) error('i',"local class N buffer overflow");
633: char *p = new char[ll+1];
634: strcpy(p,buf);
635: return p;
636: }
637:
638:
639: void enumdef::dcl_print(Pname cln)
640: /*
641: */
642: {
643: char* s = cln ? cln->string : 0;
644: fprintf(out_file,"enum %s { ",string);
645: for (Pname px, p=mem; p; p=px) {
646: px = p->n_list;
647: if (s) {
648: if (p->n_initializer)
649: fprintf(out_file,"%s__%s = %d",p->string,s,p->n_val);
650: else
651: fprintf(out_file,"%s__%s",p->string,s);
652: }
653: else {
654: if (p->n_initializer)
655: fprintf(out_file,"%s = %d",p->string,p->n_val);
656: else
657: fprintf(out_file,"%s",p->string);
658: }
659: if (px) puttok(CM);
660: p->n_initializer = 0;
661: delete p;
662: }
663: /* Sam says: don't zap MEM. It may be needed for the program database later. */
664: // mem = 0;
665: puttok(RC);
666: puttok(SM);
667: }
668:
669:
670: extern char *make_local_name(Pclass,int=0);
671:
672: void name::print()
673:
674: /* print just the name itself */
675:
676: {
677:
678: /* Rick, ODI, 3-28-89: This function transforms the names of name
679: instances. In fact, with default cfront renaming, only types and
680: globals pass though unscathed. This makes debugging a real pain
681: in the ass. Consequently, a mode has been introduced to cfront which
682: limits renaming (see main.c:main:case "+gx"). Using this mode reduces
683: the renaming to the following cases:
684:
685: -- static data members are suffixed with the name of their
686: class with '__#' at the beginning of the class name. The '#'
687: is the length of the class name. So, for example, given
688: "class C { static int i; }", "i" would become the global variable
689: "i__1C"--this makes global name clashes less likely;
690:
691: -- data members are prefixed just like static data members
692: only when the data member's name is identical to the name
693: of a data member in a base class. For example, given
694: "class B { int i; } class D : B { float i; }" the first
695: would not be renamed, so its name would be "i", while
696: the second would be renamed to "i__1D";
697:
698: -- functions are transformed as before. Given overloading
699: and the fact that function members are transformed into
700: global functions, function renaming must be preserved;
701:
702: -- anonymous unions have names generated for them (someone's
703: got to do it).
704:
705: All other cases are not renamed using the the "gx" mode. Additionally,
706: the generated names of anonymous unions have been simplified. Finally,
707: all names which are transformed into global objects have must have
708: any renamings be exactly as with default renaming. */
709:
710: if (this == 0) error('i',"0->N::print()");
711:
712: if (capture_renaming) { /* rick, ODI, 3-28-89; used to switch on
713: renaming capture. */
714: new_string[0] = '\0';
715: tmp_string[0] = '\0';
716: }
717:
718: if (string == 0) {
719: if (emode) putch('?');
720: if (capture_renaming) { /* rick, ODI, 3-28-89; used to switch
721: on renaming capture. */
722: new_string[0] = '\0';
723: goto handle_new_string;
724: }
725: return;
726: }
727:
728: // error( 'd', "%s->name::print(), base: %k", string, base );
729:
730: switch (base) {
731: case TNAME:
732: if ((n_template_arg_string) && emode &&tp) {
733: // hide the mangled type name, and use the type instead, since it is
734: // more useful
735: tp->dcl_print(0) ;
736: return ;
737: } ;
738:
739: if( emode && tp && tp->base == COBJ) {
740: Pclass cl = Pclass(Pbase(tp)->b_name->tp);
741: if(cl && cl->base == CLASS &&
742: (cl->class_base == instantiated_template_class)) {
743: Ptclass(cl)->inst->print_pretty_name() ;
744: return;
745: }
746: }
747:
748: putst(n_template_arg_string ? n_template_arg_string : string);
749: if (capture_renaming) {
750: /* Rick, ODI, 3-28-89: capture renaming. */
751: strcat(new_string,
752: (n_template_arg_string ? n_template_arg_string : string));
753: goto handle_new_string;
754: }
755: return;
756:
757: case MDOT:
758: Pexpr(this)->print();
759: return;
760: }
761:
762: if (emode) {
763: Ptable tbl;
764: char* cs = 0;
765: bit f = 0;
766: if (tp) {
767: switch (tp->base) {
768: case OVERLOAD:
769: case FCT:
770: f = 1;
771: default:
772: if (tbl=n_table) {
773: if (tbl == gtbl) {
774: if (f == 0) {
775: putstring("::");
776: if (capture_renaming) {
777: /* Rick, ODI, 3-28-89: capture renaming. */
778: strcat(new_string, "::");
779: }
780: }
781: }
782: else {
783: if (tbl->t_name) {
784: Ptclass pc = Ptclass(tbl->t_name->tp) ;
785: cs = tbl->t_name->string;
786: if ((pc->base == CLASS) &&
787: (pc->class_base == instantiated_template_class))
788: pc->inst->print_pretty_name() ;
789: else fprintf(out_file,"%s",cs);
790: fprintf (out_file, "::") ;
791:
792: if (capture_renaming) {
793: // Sam: I think this is not necessary in
794: // "emode" context
795: /* Rick, ODI, 3-28-89: capture renaming. */
796: sprintf(tmp_string,"%s::",cs);
797: strcat(new_string, tmp_string);
798: }
799: }
800: }
801: }
802:
803: // local class will need to modify ???
804:
805: if (n_scope==ARG && strcmp(string,"this")==0) {
806: // tell which "this" it is
807: Ptype tt = Pptr(tp)->typ;
808: Pname cn = Pbase(tt)->b_name;
809: fprintf(out_file,"%s::",cn->string);
810: if (capture_renaming) {
811: /* Rick, ODI, 3-28-89: capture renaming. */
812: sprintf(tmp_string, "%s::",cn->string);
813: strcat(new_string, tmp_string);
814: }
815:
816: }
817:
818: case CLASS:
819: case ENUM:
820: // case TYPE:
821: break;
822: }
823: nop:
824: switch (n_oper) {
825: case TYPE:
826: putstring("operator ");
827: if (capture_renaming) {
828: /* Rick, ODI, 3-28-89: capture renaming. */
829: strcat(new_string, "operator ");
830: }
831: if (tp) Pfct(tp)->returns->dcl_print(0);
832: break;
833: case 0:
834: putstring(string);
835: if (capture_renaming) {
836: /* Rick, ODI, 3-28-89: capture renaming. */
837: strcat(new_string, string);
838: }
839: break;
840: case DTOR:
841: putch('~');
842: if (capture_renaming) {
843: /* Rick, ODI, 6-6-89: capture renaming. */
844: strcat(new_string, "~");
845: }
846: case CTOR:
847: if (cs) {
848: if(tbl->t_name) {
849: Ptclass pc = Ptclass(tbl->t_name->tp) ;
850: if ((pc->base == CLASS) &&
851: (pc->class_base == instantiated_template_class))
852: pc->inst->print_pretty_name() ;
853: } else putstring(cs);
854: if (capture_renaming) {
855: /* Rick, ODI, 3-28-89: capture renaming. */
856: strcat(new_string, cs);
857: }
858: }
859:
860: else {
861: putstring("constructor");
862: if (capture_renaming) {
863: /* Rick, ODI, 3-28-89: capture renaming. */
864: strcat(new_string, "constructor");
865: }
866: f = 0;
867: }
868: break;
869: case TNAME:
870: putstring(string);
871: if (capture_renaming) {
872: /* Rick, ODI, 3-28-89: capture renaming. */
873: strcat(new_string, string);
874: }
875: break;
876: default:
877: putstring("operator ");
878: if (capture_renaming) {
879: /* Rick, ODI, 3-28-89: capture renaming. */
880: strcat(new_string,"operator " );
881: }
882: putstring(keys[n_oper]);
883: if (capture_renaming) {
884: /* Rick, ODI, 3-28-89: capture renaming. */
885: strcat(new_string, keys[n_oper]);
886: }
887: break;
888: }
889: if (f) {
890: putstring("()");
891: if (capture_renaming) {
892: /* Rick, ODI, 3-28-89: capture renaming. */
893: strcat(new_string,"()");
894: }
895: }
896: }
897: else {
898: if (n_oper) goto nop;
899: if (string) {
900: putstring(n_template_arg_string ?
901: n_template_arg_string : string);
902: if (capture_renaming) {
903: /* Rick, ODI, 3-28-89: capture renaming. */
904: strcat(new_string,
905: (n_template_arg_string ?
906: n_template_arg_string : string));
907: }
908: }
909: }
910: if (capture_renaming) { /* rick, ODI, 3-28-89; used
911: to switch on renaming capture. */
912: goto handle_new_string;
913: }
914: return;
915: }
916:
917: // AT&T used initializations. Rick's goto povoked a diagnostic. so...
918: char* sig; sig = 0;
919: Pclass cl; cl = 0;
920: int i; i = n_union;
921:
922: if (tp) {
923: Ptable tbl;
924:
925: switch (tp->base) {
926: default:
927: if (tbl=n_table) { // global or member
928: Pname tn;
929: if (tbl == gtbl) {
930:
931: /* Rick, ODI, 3-28-89: "gtbl" is the table of global
932: names (see cfront.h:124). So, "tbl" is the table
933: of global names here. */
934:
935: // if (i) fprintf(out_file,"__O%d.",i);
936:
937: if ( i ) {
938: /* Rick, ODI, 3-28-89: If "i" is greater than 0, then
939: then "this" refers to an anonymous union member,
940: whose union is global (see closest-containing
941: if). */
942:
943: if ( ! capture_renaming) {
944: /* Rick, ODI, 3-28-89: use full cfront
945: renaming. */
946: if (n_anon)
947: fprintf(out_file,"__O%d.%s.", i, n_anon );
948: else fprintf(out_file,"__O%d.",i);
949: }
950: else {
951: /* Capture the transformed name. */
952: if (n_anon) {
953: fprintf(out_file,"__O%d.%s.", i, n_anon );
954: sprintf(tmp_string, "__O%d.%s.", i, n_anon);
955: }
956: else {
957: fprintf(out_file,"__O%d.",i);
958: sprintf(tmp_string, "__O%d.", i);
959: }
960: strcat(new_string, tmp_string);
961: }
962: }
963: break;
964: }
965:
966: if (tn=tbl->t_name) {
967: cl = Pclass(tn->tp);
968: /* Rick, ODI: The table associated with "this" has a
969: name--it corresponds to a named scope. */
970: if (i) {
971:
972: /* Rick, ODI, 3-28-89: If "i" is greater than 0, then
973: then "this" refers to an anonymous union member,
974: whose union is NOT global (see if(tbl == gtbl)
975: above, note case global anonymous union has
976: break). */
977:
978: if (cl->string[0]=='_'
979: && cl->string[1]=='_'
980: && cl->string[2]=='C' )
981: {
982: if ( ! capture_renaming) {
983: /* Rick, ODI, 3-28-89; use full cfront
984: renaming. */
985: if (n_anon)
986: fprintf(out_file,"__O%d.%s.", i, n_anon );
987: else fprintf(out_file,"__O%d.",i);
988: }
989: else {
990: /* Rick, ODI: Capture the transformed name. */
991: if (n_anon) {
992: fprintf(out_file,"__O%d.%s.", i, n_anon );
993: sprintf(tmp_string, "__O%d.%s", i, n_anon);
994: }
995: else {
996: fprintf(out_file,"__O%d.",i);
997: sprintf(tmp_string, "__O%d.", i);
998: }
999: strcat(new_string, tmp_string);
1000: }
1001: }
1002: else if ( cl->lex_level ) {
1003: char *str = make_local_name(cl,1);
1004: if ( ! capture_renaming) {
1005: /* Rick, ODI, 3-28-89; use full cfront
1006: renaming. */
1007: fprintf(out_file,"__O%d%s.",i,str);
1008: }
1009: else {
1010: /* Rick, ODI: Capture the transformed name. */
1011: fprintf(out_file,"__O%d%s.",i,str);
1012: sprintf(tmp_string, "__O%d%s.", i, str);
1013: strcat(new_string, tmp_string);
1014: }
1015: delete str;
1016: }
1017: else {
1018: if ( ! capture_renaming) {
1019: /* Rick, ODI, 3-28-89; use full cfront
1020: renaming. */
1021: fprintf(out_file,"__O%d__%d%s.",
1022: i,cl->strlen,cl->string);
1023: }
1024: else if ( ! limit_renaming) {
1025: /* Rick, ODI: Capture the transformed name. */
1026: fprintf(out_file,"__O%d__%d%s.",
1027: i,cl->strlen,cl->string);
1028: sprintf(tmp_string, "__O%d__%d%s.",
1029: i,cl->strlen,cl->string);
1030: strcat(new_string, tmp_string);
1031: }
1032: else {
1033: /* Rick, ODI: Capture the transformed name.
1034: Note, that renaming less extensive than
1035: if part. */
1036: fprintf(out_file,"__O%d.", i);
1037: sprintf(tmp_string, "__O%d.", i);
1038: strcat(new_string, tmp_string);
1039: }
1040: }
1041: cl = 0;
1042: }
1043: else if (cl->string[0]=='_'
1044: && cl->string[1]=='_'
1045: && cl->string[2]=='C'
1046: && n_stclass != STATIC )
1047: cl = 0;
1048: break;
1049: }
1050: }
1051:
1052: switch (n_stclass) { // local variable
1053: case STATIC:
1054: case EXTERN:
1055: if (i) {
1056: /* Rick, ODI, 3-28-89: If "i" is greater than 0, then
1057: then "this" refers to a an anonymous union member. */
1058:
1059: if ( ! capture_renaming) {
1060: /* Rick, ODI, 3-28-89; use full cfront renaming. */
1061: fprintf(out_file,"__O%d.",i);
1062: }
1063: else {
1064: /* Capture the renaming. */
1065: fprintf(out_file,"__O%d.",i);
1066: sprintf(tmp_string, "__O%d.", i);
1067: strcat(new_string, tmp_string);
1068: }
1069: }
1070: else if (n_sto==STATIC && tp->base!=FCT) {
1071: /* Rick, ODI, 3-28-89: With full renaming, if the
1072: transformation of "this" is static (n_sto == STATIC)
1073: and not a function, then the name is prefixed with
1074: "_static_". I'm not sure why this transformation is
1075: ever necessary. Static variables never seem to have
1076: their scopes changed, so there aren't any conflicts.
1077: As for static data members, their n_sto == EXTERN
1078: since they are transformed into global variables. */
1079: // Benson sez: death to __0 names!
1080: if (capture_renaming && ! limit_renaming) {
1081: /* rick, ODI, 3-28-89; use full cfront renaming. */
1082: if (lex_level == 0) {
1083: putstring("__S");
1084: strcat(new_string, "__S");
1085: }
1086: else {
1087: fprintf(out_file,"__%d",lex_level);
1088: sprintf(tmp_string, "__%d", lex_level);
1089: strcat(new_string, tmp_string);
1090: }
1091: }
1092: else if ( ! capture_renaming && ! limit_renaming) {
1093: /* rick, ODI, 3-28-89; use full cfront renaming. */
1094: if (lex_level == 0)
1095: putstring("__S");
1096: else
1097: fprintf(out_file,"__%d",lex_level);
1098: }
1099: }
1100: break;
1101: default:
1102: // encode with lexicallevel UNLESS ``special''
1103: // e.g. __builtin
1104: if (string[0]!='_' || string[1]!='_' || string[2] != 'C' ) {
1105: // error( 'd', "print2 i: %d, lex_level: %d this: %n", i, lex_level,this );
1106: if (i) {
1107: if ( ! capture_renaming) {
1108: /* Rick, ODI: WARNING: should check that new
1109: version doesn't have problem with anonymous
1110: classes at the file level or within a block. */
1111:
1112: /* Rick, ODI, 6-20-89: Lex lexel can't be
1113: printed here unless it is also printed in
1114: the union's declaration which is handled
1115: above. The simplest fix is to get rid of
1116: the lex level output. */
1117: /* Previous version's prints:
1118: fprintf(out_file,"__%d__O%d.",lex_level-1,i,i);
1119: fprintf(out_file,"__O%d.",i,i); */
1120: if (n_anon)
1121: fprintf(out_file,"__%d__O%d.%s.",
1122: lex_level-1,i,n_anon);
1123: else fprintf(out_file,"__%d__O%d.",lex_level-1,i);
1124: }
1125: else if (capture_renaming && ! limit_renaming) {
1126: /* Rick, ODI: WARNING: should check that new
1127: version doesn't have problem with anonymous
1128: classes at the file level or within a block. */
1129:
1130: /* Rick, ODI, 6-20-89: Lex lexel can't be
1131: printed here unless it is also printed in
1132: the union's declaration which is handled
1133: above. The simplest fix is to get rid of
1134: the lex level output. */
1135: /* Previous version's prints:
1136: fprintf(out_file,"__%d__O%d.",lex_level-1,i,i);
1137: fprintf(out_file,"__O%d.",i,i); */
1138: if (n_anon) {
1139: fprintf(out_file,"__%d__O%d.%s.",
1140: lex_level-1,i,n_anon);
1141: sprintf(tmp_string, "__%d__O%d.%s.",
1142: lex_level-1,i,n_anon);
1143: strcat(new_string, tmp_string);
1144: }
1145: else {
1146: fprintf(out_file,"__%d__O%d.",lex_level-1,i);
1147: sprintf(tmp_string, "__%d__O%d.",
1148: lex_level-1,i);
1149: strcat(new_string, tmp_string);
1150: }
1151: }
1152: else {
1153: /* Capture the renaming. Note, the renaming is not
1154: as extensive as the if part. */
1155: if (n_anon) {
1156: fprintf(out_file,"__O%d.%s.", i,n_anon);
1157: sprintf(tmp_string,"__O%d.%s.", i,n_anon);
1158: }
1159: else {
1160: fprintf(out_file,"__O%d.", i);
1161: sprintf(tmp_string,"__O%d.", i);
1162: }
1163: strcat(new_string, tmp_string);
1164: }
1165: }
1166: else
1167: if( ! limit_renaming) {
1168: /* rick, ODI, 3-28-89; use full cfront renaming. */
1169: fprintf(out_file,"__%d",lex_level);
1170: if (capture_renaming) {
1171: sprintf(tmp_string, "__%d", lex_level);
1172: strcat(new_string, tmp_string);
1173: }
1174: }
1175: }
1176: }
1177: break;
1178: case CLASS:
1179: case ENUM:
1180: break;
1181: }
1182:
1183: if (tp->base==FCT) {
1184: sig = Pfct(tp)->f_signature;
1185: if (sig && sig[0]==0) sig = 0;
1186: }
1187: }
1188:
1189: if (string) {
1190: #ifdef DENSE
1191: /* Rick, ODI, 6-6-89: This is suppose to be for machines with a 31
1192: character limit on the length of an identifier. Only the first
1193: 29 [0..28] characters are perserved, the remaining characters are
1194: hashed and the result is used to generate characters [29] and
1195: [30] out of a choice of 63 characters (see chop() below). In a
1196: uniform distribution, the two characters positions would produce
1197: 3969 possibilities. The real question is what are the likely
1198: distributions? We might want to analyse the reliability
1199: of this algorithm to determine whether or not it should be
1200: removed. At least the authors gave the #define an appropriate
1201: name. */
1202: int i = strlen(string);
1203: if (cl) i += cl->strlen+4; // __dd<class name>
1204: if (sig) {
1205: if (cl == 0) i += 2;
1206: i += strlen(sig);
1207: }
1208:
1209: if (31<i) {
1210: char buf[1024];
1211:
1212: if ( ! limit_renaming || tp->base == FCT || tp->base == INLINE ||
1213: tp->base == VIRTUAL || tp->base == OVERLOAD ||
1214: tp->base == OPERATOR) {
1215:
1216: /* Rick, ODI, 3-28-89: Not much can be done with
1217: functions. Given overloading and the fact that
1218: all class function members are transformed into
1219: global functions, function name transformation
1220: must be left alone. */
1221:
1222: if (cl && sig)
1223: sprintf(buf,"%s__%d%s%s",string,cl->strlen,cl->string,sig);
1224: else if (cl)
1225: sprintf(buf,"%s__%d%s",string,cl->strlen,cl->string);
1226: else if (sig)
1227: sprintf(buf,"%s__%s",string,sig);
1228: else
1229: sprintf(buf,"%s",string);
1230:
1231: }
1232:
1233: else if ((class_name = is_data_member(this)) &&
1234: (n_stclass == STATIC ||
1235: matches_base_member(this, Pclass(class_name->tp)))) {
1236:
1237: /* Rick, ODI, 3-28-89: There are two cases where
1238: a data member must have its name transformed:
1239: -- when the data member is static;
1240: -- when the data member has the same name
1241: as data member belonging to any of the
1242: class's base types.
1243: Capture the name transformation. */
1244:
1245: if (cl)
1246: sprintf(buf,"%s__%d%s",string,cl->strlen,cl->string);
1247: else
1248: sprintf(buf,"%s",string);
1249:
1250: }
1251:
1252: else /* Don't rename. */
1253: sprintf(buf,"%s",string);
1254:
1255: chop(buf);
1256: fprintf(out_file,"%s ",buf);
1257: if (capture_renaming) {
1258: /* Capture renaming. */
1259: strcat(new_string, buf);
1260: }
1261: if (capture_renaming)
1262: goto handle_new_string;
1263: return;
1264: }
1265: #endif
1266: putstring(n_template_arg_string ? n_template_arg_string : string);
1267: if (capture_renaming) { /* Capture renaming. */
1268: strcat(new_string,
1269: (n_template_arg_string ? n_template_arg_string : string));
1270: }
1271:
1272: // local class
1273:
1274: /* Rick, ODI, 6-7-89: I don't know why the previous comment
1275: asserts that "cl" is a "local class". As near as I can tell
1276: any class will set cl to non-zero and only the cases of
1277: unions and classes whose names begin with "__C" and have
1278: non-static data members clear cl. */
1279:
1280: Pname class_name; /* Rick, ODI, 6-7-89: Used to hold
1281: a data member's class name. */
1282:
1283: if ( cl ) {
1284: if ( cl->lex_level ) { /* Rick, ODI, 6-7-89: Can assert here
1285: that "cl" is a local class. */
1286: char *str = str = make_local_name( cl, 1 );
1287: putstring( str );
1288: delete str;
1289: }
1290: else { // Rick, ODI, 6-7-89: Global class (cl->lex_level == 0).
1291:
1292: if ( ! limit_renaming || tp->base == FCT ||
1293: tp->base == INLINE || tp->base == VIRTUAL ||
1294: tp->base == OVERLOAD || tp->base == OPERATOR) {
1295:
1296: /* Rick, ODI, 3-28-89: Not much can be done with
1297: functions. Given overloading and the fact that
1298: all class function members are transformed into
1299: global functions, function name transformation
1300: must be left alone. */
1301:
1302: fprintf(out_file,"__%d%s",cl->strlen,cl->string);
1303: if (capture_renaming) { /* Capture renaming. */
1304: sprintf(tmp_string, "__%d%s", cl->strlen,cl->string);
1305: strcat(new_string, tmp_string);
1306: }
1307: }
1308:
1309: else if ((class_name = is_data_member(this)) &&
1310: (n_stclass == STATIC ||
1311: matches_base_member(this, Pclass(class_name->tp)))) {
1312:
1313: /* Rick, ODI, 3-28-89: There are two cases where
1314: a data member must have its name transformed:
1315: -- when the data member is static;
1316: -- when the data member has the same name
1317: as data member belonging to any of the
1318: class's base types.
1319: Capture the name transformation. */
1320:
1321: fprintf(out_file,"__%d%s",cl->strlen,cl->string);
1322: if (capture_renaming) { /* Capture renaming. */
1323: sprintf(tmp_string, "__%d%s", cl->strlen,cl->string);
1324: strcat(new_string, tmp_string);
1325: }
1326: }
1327: }
1328: }
1329:
1330: if (sig) { /* Rick, ODI, 6-7-89: Function, so output signiture */
1331: if (cl == 0) {
1332: putstring("__");
1333: if (capture_renaming) { /* Capture renaming. */
1334: strcat(new_string, "__");
1335: }
1336: }
1337: putstring(sig);
1338: if (capture_renaming) { /* Capture renaming. */
1339: strcat(new_string, sig);
1340: }
1341: }
1342: putch(' ');
1343:
1344: }
1345:
1346: handle_new_string:
1347:
1348: if (capture_renaming) {
1349:
1350: /* Rick, ODI, 3-28-89: If the renaming has not been seen before,
1351: then set "this"'s "output_string" to refer to the renaming. */
1352:
1353: if (string && new_string[0] != '\0' &&
1354: strcmp(string, new_string) != 0 &&
1355: ! (tp->base == FCT && ! Pfct(tp)->body)) {
1356: if ( ! output_string || strcmp(output_string, new_string) != 0) {
1357: if (output_string)
1358: delete output_string;
1359: output_string = new char[strlen(new_string) + 1];
1360: strcpy(output_string, new_string);
1361: }
1362: #if OUTPUT_PAIR_FUNCTIONALITY
1363: if (tp->base == FCT)
1364: output_pair(this);
1365: #endif
1366: }
1367: else
1368: output_string = (char *) 0;
1369: }
1370:
1371: } // name::print
1372:
1373:
1374: #ifdef DENSE
1375: void chop(char* buf)
1376: {
1377: static char alpha[] = "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1378: static const asz = sizeof(alpha)-1;
1379: int hash = 0;
1380: char* p = &buf[29];
1381:
1382: while (*p) {
1383: hash <<= 1;
1384: if (hash & (1<<12)) {
1385: hash &= ~(1<<12);
1386: hash++;
1387: }
1388: hash ^= *p++;
1389: }
1390:
1391: buf[29] = alpha[(int)(hash%asz)];
1392: buf[30] = alpha[(int)((hash/asz)%asz)];
1393: buf[31] = 0;
1394: }
1395: #endif
1396:
1397: void type::print()
1398: {
1399: switch (base) {
1400: case PTR:
1401: case RPTR:
1402: case VEC:
1403: Pptr(this)->dcl_print(0);
1404: break;
1405: case FCT:
1406: Pfct(this)->dcl_print();
1407: break;
1408: // case VEC:
1409: // Pvec(this)->dcl_print(0);
1410: // break;
1411: case CLASS:
1412: case ENUM:
1413: if (emode)
1414: fprintf(out_file,"%k",base);
1415: else
1416: // error('i',"%p->T::print(%k %s)",this,base,Pclass(this)->string);
1417: fprintf(out_file,"struct %s *",Pclass(this)->string);
1418: break;
1419: case TYPE:
1420: if (Cast) {
1421: Pbase(this)->b_name->tp->print();
1422: break;
1423: }
1424: // no break
1425: default:
1426: Pbase(this)->dcl_print();
1427: }
1428: }
1429:
1430: char* type::signature(register char* p)
1431: /*
1432: take a signature suitable for argument types for overloaded
1433: function names
1434: */
1435: {
1436: Ptype t = this;
1437: int pp = 0; // pointer to
1438:
1439: xx:
1440: //error('d',"xx(%d) %d %k",this,t,t->base);
1441:
1442: // first unroll typedefs and handle derived types:
1443:
1444: switch (t->base) {
1445: case TYPE:
1446: if (Pbase(t)->b_const) *p++ = 'C';
1447: t = Pbase(t)->b_name->tp;
1448: goto xx;
1449:
1450: case VEC:
1451: if (pp && Pvec(t)->size) { // A<size>_
1452: *p++ = 'A';
1453: sprintf(p,"%d\0",Pvec(t)->size); // don't trust
1454: // sprintf return value
1455: while (*++p);
1456: *p++ = '_';
1457: }
1458: else
1459: *p++ = 'P';
1460: t = Pvec(t)->typ;
1461: pp = 1;
1462: goto xx;
1463:
1464: case PTR:
1465: if (Pptr(t)->rdo) *p++ = 'C'; // *const
1466: if (Pptr(t)->memof) { // M<size><classname>
1467: Pclass cl = Pptr(t)->memof;
1468: register char* s = cl->string;
1469: int d = cl->strlen;
1470: if (d==0) cl->strlen = d = strlen(s);
1471: *p++ = 'M';
1472: if (d/10) *p++ = '0'+d/10;
1473: *p++ = '0'+ d%10; // assume <100 char
1474: while (*p++ = *s++);
1475: --p; // not the '\0'
1476: }
1477: else
1478: *p++ = 'P';
1479: t = Pptr(t)->typ;
1480: pp = 1;
1481: goto xx;
1482:
1483: case RPTR:
1484: *p++ = 'R';
1485: t = Pptr(t)->typ;
1486: pp = 1;
1487: goto xx;
1488:
1489: case FCT:
1490: { Pfct f = Pfct(t);
1491: Pname n = f->argtype;
1492:
1493: if (f->f_const) *p++ = 'C'; // constant member function
1494: if (f->f_static) *p++ = 'S'; // static member function
1495: // if (f->memof && f->f_this==0) *p++ = 'S'; //SSS static member function
1496: *p++ = 'F';
1497: if (n == 0)
1498: *p++ = 'v'; // VOID, that is f() == f(void)
1499: else
1500: for ( ; n; n=n->n_list) { // print argument encoding
1501: // check if argtype is the same
1502: // as previously seen argtype
1503: int i = 0;
1504: for (Pname nn=f->argtype; n!=nn; nn=nn->n_list) {
1505: i++;
1506: if (nn->tp==n->tp || nn->tp->check(n->tp,0)==0) {
1507: // typeof (n) == typeof(arg i)
1508: int x = 1; // try for a run after n
1509: Pname nnn = n;
1510: while ((nnn=nnn->n_list) && x<9) {
1511: if (nnn->tp==n->tp
1512: || nnn->tp->check(n->tp,0)==0) {
1513: x++;
1514: n = nnn;
1515: }
1516: else
1517: break;
1518: }
1519:
1520: if (x == 1) // Ti
1521: *p++ = 'T';
1522: else { // Nxi
1523: *p++ = 'N';
1524: *p++ = '0'+x;
1525: }
1526:
1527: // assume <100 arguments
1528: if (9<i) *p++ = '0'+i/10;
1529: *p++ = '0'+i%10;
1530: goto zk;
1531: }
1532: }
1533:
1534: // ``normal'' case print argument type signature
1535: // if (n->n_xref) *p++ = 'R';
1536: p = n->tp->signature(p);
1537: zk:;
1538: }
1539:
1540: if (f->nargs_known == ELLIPSIS) *p++ = 'e';
1541:
1542: if (pp) { // '_' result type
1543: *p++ = '_';
1544: p = f->returns->signature(p);
1545: }
1546:
1547: *p = 0;
1548: return p;
1549: }
1550: }
1551:
1552: // base type modifiers:
1553:
1554: if ( Pbase(t)->b_const ) *p++ = 'C';
1555: // if ( Pbase(t)->b_signed ) *p++ = 'S';
1556: if ( Pbase(t)->b_unsigned ) *p++ = 'U';
1557: // if ( Pbase(t)->b_volatile ) *p++ = 'V';
1558:
1559:
1560: // now base types:
1561:
1562: register char* s;
1563: int d;
1564: Pclass cl;
1565: //lll:
1566: switch (t->base) {
1567: // case TNAME: t = Pbase(t)->b_name->tp; goto lll;
1568: case ANY: break;
1569: case ZTYPE: break;
1570: case VOID: *p++ = 'v'; break;
1571: case CHAR: *p++ = 'c'; break;
1572: case SHORT: *p++ = 's'; break;
1573: // case EOBJ:
1574: case INT: *p++ = 'i'; break;
1575: case LONG: *p++ = 'l'; break;
1576: case FLOAT: *p++ = 'f'; break;
1577: case DOUBLE: *p++ = 'd'; break;
1578: case LDOUBLE: *p++ = 'r'; break;
1579: case EOBJ:
1580: // *p++ = 'i';
1581: // break;
1582: { Penum en = Penum(Pbase(t)->b_name->tp);
1583: // t = en->e_type;
1584: // goto lll;
1585: s = en->string;
1586: d = en->strlen;
1587: if (d==0) en->strlen = d = strlen(s);
1588: goto pppp;
1589: }
1590:
1591: case COBJ:
1592: { cl = Pclass(Pbase(t)->b_name->tp);
1593: s = cl->string;
1594: d = cl->strlen;
1595: if (d==0) cl->strlen = d = strlen(s);
1596: pppp:
1597: sprintf(p, "%d", d) ;
1598: while (*p++) ; --p ;
1599: while (*p++ = *s++);
1600: --p;
1601: break;
1602:
1603: // pppp:
1604: // if (d/10) *p++ = '0'+d/10;
1605: // *p++ = '0'+ d%10; // assume less that 99 characters
1606: // while (*p++ = *s++);
1607: // --p;
1608: // break;
1609: }
1610: case FIELD:
1611: default:
1612: error('i',"signature of %k",t->base);
1613: }
1614:
1615: *p = 0;
1616: return p;
1617: }
1618:
1619: void basetype::dcl_print()
1620: {
1621: Pname nn;
1622: Pclass cl;
1623:
1624: if (emode) {
1625: if (b_virtual) puttok(VIRTUAL);
1626: if (b_inline) puttok(INLINE);
1627: if (b_const) puttok(CONST);
1628: }
1629: if (b_unsigned) puttok(UNSIGNED);
1630:
1631: switch (base) {
1632: case ANY:
1633: if (emode)
1634: putstring("any ");
1635: else
1636: putstring("int ");
1637: break;
1638:
1639: case ZTYPE:
1640: if (emode)
1641: putstring("zero ");
1642: else
1643: putstring("int ");
1644: break;
1645:
1646: case VOID:
1647: /* sun's compiler, and most all others, support void */
1648: #ifndef sun
1649: if (emode==0 && ansi_opt==0
1650: ) {
1651: // silly trick to bypass BSD C compiler bug
1652: // void* (*)() dosn't work there
1653: // note simpl.c knows that VOID -> CHAR grep for VCVC
1654: puttok(CHAR);
1655: } else puttok(VOID);
1656: #else
1657: puttok(VOID);
1658: #endif
1659: break;
1660:
1661: case CHAR:
1662: case SHORT:
1663: case INT:
1664: case LONG:
1665: case FLOAT:
1666: case DOUBLE:
1667: case LDOUBLE:
1668: puttok(base);
1669: break;
1670:
1671: case EOBJ:
1672: nn = b_name;
1673: eob:
1674: if (emode == 0)
1675: // puttok(INT);
1676: Penum(nn->tp)->e_type->dcl_print();
1677: else {
1678: puttok(ENUM);
1679: nn->print();
1680: }
1681: break;
1682:
1683: case COBJ:
1684: nn = b_name;
1685: cob:
1686: cl = Pclass(nn->tp);
1687: if (emode && (cl->base == CLASS) &&
1688: (cl->class_base == instantiated_template_class)) {
1689: Ptclass(cl)->inst->print_pretty_name() ;
1690: break ;
1691: }else if (cl && (cl->csu==UNION || cl->csu==ANON))
1692: puttok(UNION);
1693: else
1694: puttok(STRUCT);
1695: { // local class
1696: char* s = 0;
1697: if ( cl && cl->lex_level ) s = make_local_name( cl );
1698: putst(s?s:nn->string);
1699: delete s;
1700: }
1701: break;
1702:
1703: case TYPE:
1704: if (emode == 0) {
1705: switch (b_name->tp->base) {
1706: case COBJ:
1707: nn = Pbase(b_name->tp)->b_name;
1708: goto cob;
1709: case EOBJ:
1710: nn = Pbase(b_name->tp)->b_name;
1711: goto eob;
1712: // default:
1713: // {
1714: // if (b_name->lex_level !=0 )
1715: // {
1716: // error('d', "default: %n %t", b_name, b_name->tp );
1717: // Pbase(b_name->tp)->dcl_print();
1718: // b_name->tp->print();
1719: // return;
1720: // }
1721: // }
1722:
1723: }
1724: }
1725: b_name->print();
1726: break;
1727:
1728: default:
1729: if (emode) {
1730: if (0<base && base<=MAXTOK && keys[base])
1731: fprintf(out_file," %s",keys[base]);
1732: else
1733: putch('?');
1734: }
1735: else
1736: error('i',"%p->BT::dcl_print(%d)",this,base);
1737: }
1738: }
1739: Pbase memptr_type;
1740:
1741: void type::dcl_print(Pname n)
1742: /*
1743: "this" type is the type of "n". Print the declaration
1744: */
1745: {
1746: //error('d',"%p::dcl_print(%n)",this,n);
1747: Ptype t = this;
1748: Pptr p;
1749: TOK pre = 0;
1750:
1751: if (t == 0) error('i',"0->dcl_print()");
1752: if (n && n->tp!=t) error('i',"not %n'sT (%p)",n,t);
1753:
1754: if (base == OVERLOAD) {
1755: for (Plist gl=Pgen(this)->fct_list; gl; gl=gl->l) {
1756: Pname nn = gl->f;
1757: nn->tp->dcl_print(nn);
1758: if (gl->l) puttok(SM);
1759: }
1760: return;
1761: }
1762:
1763: tbuf = tbufvec[freetbuf];
1764: if (tbuf == 0) {
1765: if (freetbuf == NTBUF-1) error('i',"AT nesting overflow");
1766: tbufvec[freetbuf] = tbuf = new class dcl_buf;
1767: }
1768: freetbuf++;
1769: tbuf->init(n);
1770: if (n && n->n_xref) tbuf->front(PTR);
1771:
1772: while (t) {
1773: TOK k;
1774:
1775: switch (t->base) {
1776: case PTR:
1777: p = Pptr(t);
1778: k = (p->rdo) ? CONST_PTR : PTR;
1779: goto ppp;
1780: case RPTR:
1781: p = Pptr(t);
1782: k = (p->rdo) ? CONST_RPTR : RPTR;
1783: ppp:
1784: if (p->memof) {
1785: if (emode) {
1786: tbuf->front(k);
1787: tbuf->front(p->memof);
1788: }
1789: else {
1790: t = p->typ;
1791: while (t->base==TYPE) t = Pbase(t)->b_name->tp;
1792: if (t->base == FCT) {
1793: extern Pbase mptr_type;
1794: tbuf->base(mptr_type);
1795: goto zaq;
1796: }
1797: else
1798: tbuf->front(k);
1799: }
1800: }
1801: else
1802: tbuf->front(k);
1803: pre = PTR;
1804: t = p->typ;
1805: break;
1806: case VEC:
1807: { Pvec v = Pvec(t);
1808: if (Cast && pre != PTR && pre != VEC) { // for Macintosh: ptr to array uses [] notation
1809: tbuf->front(PTR);
1810: pre = PTR;
1811: }
1812: else {
1813: if (pre == PTR) tbuf->paran();
1814: tbuf->back(VEC,v);
1815: pre = VEC;
1816: }
1817: t = v->typ;
1818: break;
1819: }
1820:
1821: case FCT:
1822: { Pfct f = Pfct(t);
1823: if (pre == PTR)
1824: tbuf->paran();
1825: else if (emode && f->memof && n==0)
1826: tbuf->front(f->memof);
1827: tbuf->back(FCT,f);
1828: pre = FCT;
1829: t = (f->s_returns) ? f->s_returns : f->returns;
1830: break;
1831: }
1832: case FIELD:
1833: tbuf->back(FIELD,t);
1834: tbuf->base( Pbase(Pbase(t)->b_fieldtype) );
1835: t = 0;
1836: break;
1837: case 0:
1838: error('i',"noBT(B=0)");
1839: case TYPE:
1840: if (Cast) { // unravel type in case it contains vectors
1841: t = Pbase(t)->b_name->tp;
1842: break;
1843: }
1844:
1845: default: // the base has been reached
1846: /* This is WRONG. What happens to all the CONST, etc, stuff that
1847: basetype::dcl_print knows about ? */
1848: #if 0
1849: if (emode) {
1850: tbuf->base(Pbase(t));
1851: for (Ptype tt = t; tt->base==TYPE; tt=Pbase(tt)->b_name->tp);
1852: switch (tt->base) {
1853: case COBJ:
1854: tt == Pbase(tt)->b_name->tp;
1855: /* and fall through into the CLASS case */
1856: case CLASS:
1857: s = Pclass(tt)->string;
1858: if (Ptclass(this)->class_base == instantiated_template_class ||
1859: Ptclass(this)->class_base == uninstantiated_template_class)
1860: {
1861: Ptclass(this)->inst->print_pretty_name() ;
1862: freetbuf-- ;
1863: return ;
1864: } else {
1865: if (s[0]=='_' &&s[1]=='_' && s[2]=='C') s="class";
1866: putstring(s);
1867: }
1868: break ;
1869: case ENUM:
1870: s = "enum";
1871: goto fret;
1872: case OVERLOAD:
1873: s = "overloaded";
1874: fret:
1875: putstring(s);
1876: freetbuf--;
1877: return;
1878: }
1879:
1880: }
1881: #endif
1882:
1883: tbuf->base( Pbase(t) );
1884: goto zaq;
1885: } // switch
1886: } // while
1887: zaq:
1888: tbuf->put();
1889: freetbuf--;
1890: }
1891:
1892: void fct::dcl_print()
1893: {
1894: Pname nn;
1895: //error('d',"fct::dcl_print()");
1896: if (emode) {
1897: putch('(');
1898: for (nn=argtype; nn;) {
1899: nn->tp->dcl_print(0);
1900: if (nn=nn->n_list) puttok(CM); else break;
1901: }
1902: switch (nargs_known) {
1903: case 0: // putst("?"); break;
1904: case ELLIPSIS: puttok(ELLIPSIS); break;
1905: }
1906: putch(')');
1907: if (f_const) puttok(CONST);
1908: if (f_static) puttok(STATIC); // wrong place for ``static''
1909: return;
1910: }
1911:
1912: Pname at = f_args;
1913: putch('(');
1914:
1915: if (ansi_opt) {
1916: // print typed arguments:
1917: at = (f_this) ? f_this : (f_result) ? f_result : argtype;
1918: // WNG -- note: at = f_args had 0 value with ansi_opt set
1919: // mystery fix added here
1920: if (at == 0) {
1921: if (nargs_known == ELLIPSIS) {
1922: putch(')');
1923: return;
1924: }
1925: puttok(VOID);
1926: }
1927: else if (body && Cast==0)
1928: at->dcl_print(CM); // print argument type and name
1929: else {
1930: for (nn=at; nn;) {
1931: // nn->tp->dcl_print(0); // print argument type
1932: nn->tp->dcl_print(nn); // print argument type
1933: // (there may not be a name)
1934: if (nn=nn->n_list) puttok(CM); else break;
1935: }
1936: }
1937: if (nargs_known == ELLIPSIS) putstring(",...");
1938: putch(')');
1939: }
1940: else {
1941: // print argument names followed by argument type declarations:
1942: if (body && Cast==0) {
1943: for (nn=at; nn;) {
1944: nn->print();
1945: #if OUTPUT_PAIR_FUNCTIONALITY
1946: if (capture_renaming) { /* rick, ODI, 3-28-89; used
1947: to switch off some cfront
1948: renaming. */
1949: output_pair(nn);
1950: }
1951: #endif
1952: if (nn=nn->n_list) puttok(CM); else break;
1953: }
1954: putch(')');
1955: }
1956: else
1957: putch(')');
1958: }
1959: }
1960:
1961: void print_body(Pfct f)
1962: {
1963: if (Cast==0) {
1964:
1965: if (ansi_opt==0 && f->f_args) f->f_args->dcl_print(SM);
1966:
1967: if (MAIN) {
1968: putstring("{ _main(); "); // call constructors
1969: f->body->print();
1970: puttok(RC);
1971: }
1972: else
1973: f->body->print();
1974: }
1975: }
1976:
1977: Pbcl shared_seen;
1978:
1979: void classdef::print_members()
1980: {
1981: int i;
1982:
1983: Pbcl l = baselist;
1984: // error('d',"%t->print_members()",this);
1985: if (l) {
1986: if (l->base == NAME) {
1987: l->bclass->print_members(); // first base only
1988: // pad to ensure alignment:
1989: int boff = l->bclass->real_size;
1990: int ba = l->bclass->align();
1991: int xtra = boff%ba;
1992: int waste = (xtra) ? ba-xtra : 0; // padding
1993: //error('d',"%s: size % align %d waste %d",string,boff,ba,waste);
1994: if (waste) {
1995: // waste it to protect against structure
1996: // assignments to the base class
1997: char* s = make_name('W');
1998: fprintf(out_file,"char %s[%d];\n",s,waste);
1999: delete s;
2000: }
2001: l = l->next;
2002: }
2003:
2004: for (; l; l=l->next)
2005: /* for second base etc. one must allocate as an object
2006: (rather than a list of members) to ensure proper alignment
2007: for shared base allocate a pointer
2008: size, alignment, & offset handled in cassdef::dcl()
2009: */
2010: if (l->base == NAME) {
2011: Pclass bcl = l->bclass;
2012: puttok(STRUCT);
2013: putst(bcl->string);
2014: putcat('O',bcl->string);
2015: puttok(SM);
2016: }
2017: }
2018:
2019: // Sam: A class or an enum type declared within a class can hide a
2020: // member with the same name, so make sure that it gets printed by
2021: // traversing the n_tbl_list to get at these names.
2022: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i))
2023: do if (nn->base==NAME
2024: && nn->n_union==0
2025: && nn->tp->base!=FCT
2026: && nn->tp->base!=OVERLOAD
2027: && nn->tp->base!=CLASS
2028: && nn->tp->base!=ENUM
2029: && nn->n_stclass != STATIC) {
2030: if (nn->tp->base==FIELD && Pbase(nn->tp)->b_bits==0) continue;
2031: Pexpr i = nn->n_initializer;
2032: nn->n_initializer = 0;
2033: nn->dcl_print(0);
2034: nn->n_initializer = i;
2035: }
2036: // The while condition can be true for atmost one iteration per
2037: // outer iteration.
2038: while ((nn->base == NAME) &&
2039: ((nn->tp->base!=CLASS) || (nn->tp->base!=ENUM)) &&
2040: (nn = nn->n_tbl_list)) ;
2041:
2042: for (l=baselist; l; l=l->next)
2043: if (l->base==VIRTUAL && l->ptr_offset) {
2044: Pclass bcl = l->bclass;
2045: char* bs = bcl->string;
2046:
2047: puttok(STRUCT); // struct bcl* Pbcl;
2048: putst(bs);
2049: putch('*');
2050: putcat('P',bs);
2051: puttok(SM);
2052: }
2053: }
2054:
2055: void classdef::print_vtbl(Pvirt vtab)
2056: {
2057: //error('d',"%s->print_vtbl(%s) vtbl_opt %d",string,vtab->string,vtbl_opt);
2058: // error('d',"print_vtbl: lex_level: %d", lex_level );
2059:
2060: // switch (vtbl_opt) {
2061: // case -1:
2062: // case 1:
2063: vlist = new vl(this,vtab,vlist);
2064: // }
2065:
2066: int oo = vtbl_opt; // make `simulated static' name
2067: vtbl_opt = -1;
2068: char* str = lex_level ? make_local_name(this) : 0;
2069: char* s = vtbl_name(vtab->string,str?str:string);
2070: vtbl_opt = oo;
2071: // char* s = vtbl_name(vtab->string,string);
2072: // fprintf(out_file,"extern struct __mptr %s[];\n",s);
2073: s[2] = 'p'; // pointer, not tbl itself
2074: fprintf(out_file,"extern struct __mptr* %s;\n",s);
2075:
2076: delete s;
2077: delete str;
2078: }
2079:
2080: vl* vlist;
2081:
2082: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss);
2083:
2084: int p2(Pname nn, Ptype t, Pclass cl, Pvirt vtab, char* s)
2085: {
2086: int init;
2087:
2088: if (t->base == FCT) {
2089: Pfct f = Pfct(t);
2090:
2091: //error('d',"p2 %n init %d inline %d virtual %d",nn,nn->n_initializer,f->f_inline,f->f_virtual);
2092: //error('d',"p2 %s expr %d imeasure %d body %d",s,f->f_expr,f->f_imeasure,f->body);
2093: //error('d',"sto %k",nn->n_sto);
2094: if (nn->n_initializer
2095: || nn->n_sto==STATIC
2096: || f->f_inline
2097: || f->f_imeasure
2098: || f->f_virtual==0) return 0;
2099: init = f->body!=0;
2100: }
2101: else
2102: init = nn->n_initializer!=0;
2103:
2104: int oo = vtbl_opt;
2105: vtbl_opt = 1; // make sure the name is universal
2106: char* sstr = cl->lex_level ? make_local_name(cl) : 0;
2107: char* ss = vtbl_name(vtab->string,sstr?sstr:cl->string);
2108:
2109: if (init) { // unique definition here
2110: really_really_print(cl,vtab,ss,s);
2111: }
2112: else { // unique definition elsewhere
2113: //error('d',"elsewhere %n %s",nn,ss);
2114: fprintf(out_file,"extern struct __mptr %s[];\n",ss);
2115: s[2] = 'p';
2116: fprintf(out_file,"struct __mptr* %s = ",s);
2117: fprintf(out_file,"%s;\n",ss);
2118: }
2119: vtbl_opt = oo;
2120:
2121: delete ss;
2122: delete sstr;
2123:
2124: return 1;
2125: }
2126:
2127: void classdef::really_print(Pvirt vtab)
2128: {
2129: //error('d',"really_print %t %d",this,vtbl_opt);
2130: int oo = vtbl_opt; // make `simulated static' name
2131: vtbl_opt = -1;
2132: char* str = lex_level ? make_local_name(this) : 0;
2133: char* s = vtbl_name(vtab->string,str?str:string);
2134: vtbl_opt = oo;
2135:
2136: // see if needed
2137: int i;
2138: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
2139: Ptype t = nn->tp;
2140: zse:
2141: if (t)
2142: switch (t->base) {
2143: case TYPE:
2144: t = Pbase(t)->b_name->tp;
2145: goto zse;
2146: /*
2147: case COBJ:
2148: if (nn->n_sto == EXTERN)
2149: { Pclass cl = Pclass(Pbase(t)->b_name->tp);
2150: if (cl->has_ctor()) {
2151: p2(nn,t,this,vtab,s);
2152: return;
2153: }
2154: }
2155: break;
2156: */
2157: case FCT:
2158: if (p2(nn,t,this,vtab,s)) return;
2159: break;
2160:
2161: case OVERLOAD:
2162: { for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l)
2163: if (p2(gl->f,gl->f->tp,this,vtab,s)) return;
2164: }
2165: }
2166: }
2167:
2168: if (vtbl_opt) {
2169: // make vtbl name according to option:
2170: char* sstr = lex_level ? make_local_name(this) : 0;
2171: char* ss = vtbl_name(vtab->string,str?str:string);
2172: really_really_print(this,vtab,ss,s);
2173:
2174: delete ss;
2175: delete sstr;
2176: }
2177:
2178: delete s;
2179: delete str;
2180: }
2181:
2182: void really_really_print(Pclass, Pvirt vtab, char* s, char* ss)
2183: {
2184: //error('d',"really %s",s);
2185: // make sure function is declared before using
2186: // it in vtbl initializer
2187: Pname nn;
2188: int i;
2189: for (i=0; nn = vtab->virt_init[i].n; i++) {
2190: Pfct f = Pfct(nn->tp);
2191: if (nn->n_initializer) { // pure virtual
2192: static pv;
2193: if (pv == 0) { // VCVC void->char assumed
2194: #ifdef sun
2195: fprintf(out_file,"void __pure_virtual_called();\n");
2196: #else
2197: fprintf(out_file,"char __pure_virtual_called();\n");
2198: #endif
2199: pv = 1;
2200: }
2201: continue;
2202: }
2203: if (f->base != FCT) error('i',"vtbl %n",nn);
2204: //void expand_dtor(Pclass cl);
2205: // if (f->f_inline == IDTOR) expand_dtor(f->memof);
2206:
2207: if (nn->n_dcl_printed==0 /*|| f->f_inline*/) {
2208: if (f->f_inline && vtbl_opt) puttok(STATIC);
2209: if (f->f_result == 0) make_res(f);
2210: Ptype r = f->s_returns ? f->s_returns : f->returns;
2211: r->print();
2212: nn->print();
2213: putstring("()");
2214: puttok(SM);
2215: nn->n_dcl_printed = 1;
2216: }
2217: }
2218:
2219: // if (vtbl_opt == -1) puttok(STATIC);
2220:
2221:
2222: fprintf(out_file,"struct __mptr %s[] = {0,0,0,\n",s);
2223:
2224: Pname n;
2225: for (i=0; n=vtab->virt_init[i].n; i++) {
2226: if (n->n_initializer)
2227: putstring("0,0,(__vptp)__pure_virtual_called,\n");
2228: else {
2229: fprintf(out_file,"%d,0,(__vptp)",-vtab->virt_init[i].offset);
2230: n->print();
2231: n->n_addr_taken = 1;
2232: putstring(",\n");
2233: }
2234: }
2235: putstring("0,0,0};\n");
2236:
2237: ss[2] = 'p';
2238: fprintf(out_file,"struct __mptr* %s = ",ss);
2239: s[2] = 'v';
2240: fprintf(out_file,"%s;\n",s);
2241:
2242: //error('d',"really-> %s",s);
2243: }
2244:
2245: #include <ctype.h>
2246: extern char* src_file_name;
2247: char* vtbl_name(char* s1, char* s2)
2248: {
2249: //extern Pname def_name;
2250: char* s3 = (vtbl_opt == -1 && src_file_name) ? src_file_name : 0;
2251: // if vtbl_opt == -1 fake a static (there are no portable
2252: // way of doing a forward declaration of a static in C)
2253: int ll = s1 ? strlen(s1) : 0;
2254: int ll2 = strlen(s2);
2255: int ll3 = s3 ? strlen(s3) : 0;
2256: // int ll4 = s3&&def_name ? strlen(def_name->string) : 0;
2257: // int sz = (ll+ll2+ll3+ll4+22)/32+1; // avoid fragmentation
2258: int sz = (ll+ll2+ll3+20)/32+1; // avoid fragmentation
2259:
2260: sz *= 32;
2261: //error('d',"vtbl_name(%s,%s,%s) %d",s1?s1:"",s2,s3?s3:"",sz);
2262: char* buf = new char[sz];
2263: if (s3) {
2264: // if (s1 && def_name)
2265: // sprintf(buf,"__vtbl__%d%s__%d%s__%s__%s",ll,s1,ll2,s2,s3,def_name->string);
2266: // else
2267: if (s1)
2268: sprintf(buf,"__vtbl__%d%s__%d%s__%s",ll,s1,ll2,s2,s3);
2269: // else if (def_name)
2270: // sprintf(buf,"__vtbl__%d%s__%s__%s",ll2,s2,s3,def_name->string);
2271: else
2272: sprintf(buf,"__vtbl__%d%s__%s",ll2,s2,s3);
2273: }
2274: else if (s1)
2275: sprintf(buf,"__vtbl__%d%s__%d%s",ll,s1,ll2,s2);
2276: else
2277: sprintf(buf,"__vtbl__%d%s",ll2,s2);
2278:
2279: if (vtbl_opt == -1) {
2280: for (char* p = buf+ll2+11; *p; p++)
2281: if (!isalpha(*p) && !isdigit(*p)) *p = '_';
2282: }
2283: #ifdef DENSE
2284: chop(buf);
2285: #endif
2286: return buf;
2287: }
2288:
2289: void classdef::print_all_vtbls(Pclass bcl)
2290: {
2291: //error('d',"%t->print_all_vtbls(%t) vlt %d bl %d",this,bcl,virt_list,baselist);
2292:
2293: for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) {
2294: if (this != blist->vclass) continue;
2295: if (blist->printed) continue;
2296: // if (blist->string==0 && find_vptr(this)==0) { //BSopt
2297: // continue;
2298: // }
2299: print_vtbl(blist);
2300: blist->printed = 1;
2301: }
2302:
2303: for (Pbcl b = bcl->baselist; b; b = b->next)
2304: print_all_vtbls(b->bclass);
2305:
2306: if (this==bcl) c_body = 0;
2307: }
2308:
2309: void classdef::dcl_print(Pname)
2310: {
2311: extern Pclass current_instantiation ;
2312: // Sam: this kludge needs to be there in the absence of a true tree
2313: // copy for templates, to ensure that template instantiations are
2314: // printed exactly once.
2315: if ((class_base != vanilla_class) && (current_instantiation != this))
2316: return ;
2317:
2318:
2319: if (c_body==0 || c_body==3 || (defined&DEFINED)==0) return;
2320: c_body = 3;
2321:
2322: int i;
2323: //error('d',"%t->classdef::dcl_print",this);
2324: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
2325: if (nn->base==NAME
2326: && nn->n_union==0
2327: && nn->tp->base==CLASS
2328: && Pclass(nn->tp)->c_body==1)
2329: Pclass(nn->tp)->dcl_print(nn);
2330: else if (nn->base == TNAME && Pbase(nn->tp)->base != COBJ)
2331: nn->dcl_print(0);
2332: else if (nn->tp && nn->tp->base == ENUM)
2333: Penum(nn->tp)->dcl_print(nn);
2334: }
2335:
2336: TOK lvl = lex_level ? LOCAL : 0;
2337: Pname n = ktbl->look(string,lvl);
2338: if (n==0) n = ktbl->look(string,HIDDEN);
2339:
2340: if (n) {
2341: if (n->where.line!=last_line.line
2342: || n->where.file!=last_line.file)
2343: if (last_ll = n->where.line)
2344: n->where.putline();
2345: else
2346: last_line.putline();
2347: }
2348:
2349: TOK c = csu==CLASS ? STRUCT : csu;
2350: puttok(c);
2351: // if (string[0]!='_' || string[1]!='_' || string[2]!='C')
2352:
2353: char *str = 0;
2354: if ( lex_level ) str = make_local_name( this );
2355: putst(str?str:string);
2356:
2357: int sm = 0;
2358: int sz = tsizeof();
2359: int dvirt = 0;
2360:
2361: fprintf(out_file,"{\t/* sizeof %s == %d */\n",str?str:string,obj_size);
2362: delete str;
2363:
2364: print_members();
2365: for (Pbcl b = baselist; b; b = b->next) { // declare virtual classes
2366: if (b->base != VIRTUAL) continue;
2367: Pclass bcl = b->bclass;
2368: dvirt += bcl->virt_count;
2369: //error('d',"%t in %t %d",b->bclass,this,b->allocated);
2370: if (b->allocated==0) continue;
2371: puttok(STRUCT); // struct bcl Obcl;
2372: putst(bcl->string);
2373: putcat('O',bcl->string);
2374: puttok(SM);
2375: }
2376: putstring("};\n");
2377:
2378: for (nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) {
2379: if (nn->base==NAME && nn->n_union==0) {
2380: Ptype t = nn->tp;
2381: switch (t->base) {
2382: case FCT:
2383: case OVERLOAD:
2384: break;
2385: default:
2386: if (nn->n_stclass == STATIC) {
2387: TOK b = nn->n_sto;
2388: //error('d',"print nn %n tp %t b %k eval %d",nn,nn->tp,b,nn->n_evaluated);
2389: /*
2390: Pname cn;
2391: TOK bb = ((cn=nn->tp->is_cl_obj())
2392: && Pclass(cn->tp)->has_ctor())==0
2393: ?0:b; // force explicit initialization
2394: nn->n_sto = (nn->n_evaluated) ? STATIC : bb;
2395: */
2396: nn->n_sto = (nn->n_evaluated) ? STATIC : b;
2397: nn->dcl_print(0);
2398: nn->n_sto = b;
2399: }
2400: }
2401: }
2402: }
2403: if (vtbl_opt != -1) print_all_vtbls(this); // force declaration
2404: //error('d',"dcl_print -> ");
2405: }
2406:
2407:
2408: #if OUTPUT_PAIR_FUNCTIONALITY
2409:
2410: static FILE *name_pairs = (FILE *) 0;
2411:
2412:
2413: static void output_pair (name *decl)
2414:
2415: /* This function can be used to remember an original name and
2416: its transformation. These pairs can then be used in a mapping
2417: function which maps the original name to the transformed name.
2418:
2419: Currently, this routine outputs the pairs to a file. At some
2420: point, the routine might be adapted to place the pair in the
2421: .o file or in the program database. However, it would be better
2422: if the information was simply kept on the database symbol
2423: (whatever that is) like it is currently kept on cfront names
2424: using the fields "expr::string" and "name::output_string". Should
2425: the database symbol provide this facility, then this function
2426: can be removed. */
2427:
2428: {
2429:
2430: extern char* file_name[];
2431: char function_member_string[100];
2432: char name[1024];
2433:
2434:
2435: if ( ! name_pairs) {
2436: if (src_file_name) {
2437: strcpy(name, src_file_name);
2438: strcat(name, "_pairs");
2439: if ( ! (name_pairs = fopen(name, "w")))
2440: error('i',"output_pair' ! (name_pairs = fopen())");
2441: }
2442: else if ( ! (name_pairs = stderr))
2443: error('i',"output_pair' ! (name_pairs = stderr)");
2444: }
2445:
2446: if (decl->output_string) {
2447:
2448:
2449: fprintf(name_pairs, "%s\n%s\n\n", decl->string, decl->output_string);
2450:
2451: #if 0
2452: fprintf(name_pairs, "\"%s\",\"%s\"\n", decl->string,
2453: decl->output_string);
2454: #endif
2455:
2456: delete decl->output_string;
2457: decl->output_string = (char *) 0;
2458:
2459: }
2460:
2461: #if 0
2462: else
2463: fprintf(name_pairs, "%s\n", decl->string);
2464: #endif
2465:
2466: new_string[0] = '\0';
2467: tmp_string[0] = '\0';
2468:
2469: } // output_pair
2470:
2471: #endif
2472:
2473:
2474:
2475:
2476: static Pname is_data_member (Pname p_name)
2477:
2478: /* Returns the member's class if the given name is a data member.
2479: Otherwise returns (Pname) 0. */
2480:
2481: {
2482:
2483: TOK base = p_name->tp->base;
2484: Ptable p_table;
2485: Pname table_name;
2486: char *table_string;
2487: Ptable outer_table;
2488: Pname class_name;
2489:
2490: /* If the name is any kind of function, return false. */
2491:
2492: if (base == FCT || base == INLINE || base == VIRTUAL ||
2493: base == OPERATOR || base == OVERLOAD)
2494: return (Pname) 0;
2495:
2496: /* Get the member's table. Get the table's name. Get the table's
2497: outer table. Lookup the table's name in the outer table.
2498: If the name is a class, struct, or union, then return the
2499: name. Otherwise, return (Pname) 0. */
2500:
2501: if ( ! (p_table = p_name->n_table)) return (Pname) 0;
2502: if ( ! (table_name = p_table->t_name)) return (Pname) 0;
2503: if ( ! (table_string = table_name->string)) return (Pname) 0;
2504:
2505: /* If there is no outer table, then assume that outer_table
2506: is gtbl (the module level table). In 1.2, no outer table implied
2507: that p_name was not a data member, that p_table == gtbl and
2508: p_name was a module level name. */
2509:
2510: if ( ! (outer_table = p_table->next)) {
2511: outer_table = gtbl;
2512: }
2513:
2514: /* Look for a class, struct, or union matching the table string.
2515: Verify that the table containing the given name (p_table) is
2516: the table associated with the class (class_name->tp->memtbl). */
2517:
2518: if ((class_name = outer_table->look(table_string, CLASS)) ||
2519: (class_name = outer_table->look(table_string, STRUCT)) ||
2520: (class_name = outer_table->look(table_string, UNION))) {
2521: if (((struct classdef *)(class_name->tp))->memtbl == p_table)
2522: return class_name;
2523: }
2524:
2525: return (Pname) 0;
2526:
2527: } // is_data_member
2528:
2529:
2530:
2531: static Pname matches_base_member (Pname p_name, Pclass class_)
2532:
2533: /* Returns the matching member if found, otherwise returns
2534: (Pname) 0. */
2535:
2536: {
2537:
2538: Pbcl base_class;
2539: Pname matching_member;
2540:
2541: /* For each base class, look for a matching member, if
2542: found return the member. Otherwise, return (Pname) 0. */
2543:
2544: // in 1.2, this used classdef.cl_base. Now it uses baselist --benson
2545:
2546: for (base_class = class_->baselist; base_class;
2547: base_class = base_class->next) {
2548: if ((matching_member
2549: = look_any(base_class->bclass->memtbl,
2550: p_name->string)))
2551: return matching_member;
2552: else if (matching_member
2553: = matches_base_member(p_name, base_class->bclass))
2554: return matching_member;
2555: }
2556:
2557: return (Pname) 0;
2558:
2559: } // matches_base_member
2560:
2561:
2562:
2563:
2564: static Pname look_any (Ptable p_table, char* s)
2565:
2566: /* This was ripped off from table.c:table::look. The TOK
2567: argument is not considered and has been removed. The first
2568: matching name is returned. If none are found, then (Pname) 0
2569: if returned.
2570:
2571: look for "s" in table,
2572: look and insert MUST be the same lookup algorithm */
2573: {
2574:
2575: Ptable t;
2576: register char * p;
2577: register char * q;
2578: register int i;
2579: Pname n;
2580: int rr;
2581:
2582: // if (s == 0) error('i',"%d->look(0)",p_table);
2583: // if (p_table == 0) error('i',"0->look(%s)",s);
2584: // if (base != TABLE) error('i',"(%d,%d)->look(%s)",p_table,base,s);
2585:
2586: /* use simple hashing with linear search for overflow */
2587:
2588: p = s;
2589: i = 0;
2590: while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/
2591: rr = (0<=i) ? i : -i;
2592:
2593: for (t=p_table; t; t=t->next) {
2594: /* in this and all enclosing scopes look for name "s" */
2595: Pname* np = t->entries;
2596: int mx = t->hashsize;
2597: short* hash = t->hashtbl;
2598: int firsti = i = rr%mx;
2599:
2600: do {
2601: if (hash[i] == 0) goto not_found;
2602: n = np[hash[i]];
2603: if (n == 0) error('i',"hashed lookup");
2604: p = n->string; /* strcmp(n->n_string,s) */
2605: q = s;
2606: while (*p && *q)
2607: if (*p++ != *q++) goto nxt;
2608: if (*p == *q) goto found;
2609: nxt:
2610: if (mx <= ++i) i = 0; /* wrap around */
2611: } while (i != firsti);
2612:
2613: found:
2614: #if 0
2615: for (; n; n=n->n_tbl_list) { /* for all name "s"s look for a key
2616: match */
2617: if (n->n_key == k) return n;
2618: }
2619: #endif
2620: return n;
2621:
2622: not_found:;
2623: }
2624:
2625: return 0; /* not found && no enclosing scope */
2626:
2627: } // look_any
2628:
2629:
2630:
2631: char *
2632: make_local_name( Pclass cl, int ln )
2633: {
2634: char *buf;
2635: if ( cl->in_fct == 0 ) error( 'i', "localC %s missingFN", cl->string );
2636: char *fsig = Pfct(cl->in_fct->tp)->f_signature;
2637: if ( fsig == 0 ) fsig = local_sign( cl->in_fct->tp );
2638: char *fs = cl->in_fct->string;
2639: int class_len=cl->strlen+strlen(fsig)+strlen(fs)+strlen(cl->lcl)+4;
2640: int sz = (class_len+20)/32+1; // from vtbl_name()
2641:
2642: if ( Pfct(cl->in_fct->tp)->memof == 0 ) {
2643: sz *= 32;
2644: buf = new char[ sz ];
2645: // error('d', "make_local_name: sz: %d", sz );
2646:
2647: if (ln)
2648: sprintf(buf, "__%d%s__%s__%s%s", class_len, cl->string, fs, fsig, cl->lcl);
2649: else
2650: sprintf(buf, "%s__%s__%s%s", cl->string, fs, fsig, cl->lcl);
2651: }
2652: else
2653: {
2654: char *cs = Pclass(Pfct(cl->in_fct->tp)->memof)->string;
2655: int len = Pclass(Pfct(cl->in_fct->tp)->memof)->strlen;
2656: if ( len < 10 )
2657: ++class_len;
2658: else
2659: if ( len > 99 )
2660: class_len += 3;
2661: else class_len += 2;
2662: class_len += len;
2663: sz = (class_len+20)/32+1;
2664: sz *= 32;
2665: buf = new char[ sz ];
2666: // error('d', "make_local_name: sz: %d", sz );
2667:
2668: if ( ln )
2669: sprintf(buf, "__%d%s__%s__%d%s%s%s",class_len,cl->string,fs,len,cs,fsig,cl->lcl);
2670: else sprintf(buf, "%s__%s__%d%s%s%s",cl->string,fs,len,cs,fsig,cl->lcl);
2671: }
2672:
2673: #ifdef DENSE
2674: chop( buf );
2675: #endif
2676:
2677: return buf;
2678: }
2679:
2680: /* ODI notes
2681:
2682: template classes
2683:
2684: limit renaming
2685:
2686: on sun's print void as void.
2687: */
2688:
2689:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.