|
|
1.1 root 1: /*ident "@(#)ctrans:src/print.c 1.3" */
2: /**************************************************************************
3:
4: C++ source for cfront, the C++ compiler front-end
5: written in the computer science research center of Bell Labs
6:
7: Copyright (c) 1984 AT&T, Inc. All rights Reserved
8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9:
10: print.c:
11:
12: print statements and expressions
13:
14: ****************************************************************************/
15:
16: #include "cfront.h"
17:
18: static int addrof_cm ;
19: extern void puttok(TOK);
20:
21: /*
22: void cprint(Pexpr e)
23: {
24: if (e == 0) return;
25: //error('d',"%k %n %t",e->base,e->base==NAME?e:0,e->tp);
26: // if ((e->base==NAME || e->base==ANAME)
27: // && Pname(e)->n_evaluated==0) {
28: Ptype t = e->tp;
29: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
30: if (t->base == EOBJ) fprintf(out_file,"(int)");
31: // }
32:
33: Eprint(e);
34: }
35: */
36: #define cprint(e) if (e) Eprint(e)
37: #define eprint(e) if (e) Eprint(e)
38:
39: void Eprint(Pexpr e)
40: {
41: switch (e->base) {
42: case REF:
43: if (Pref(e)->mem && Pref(e)->mem->tp && Pref(e)->mem->tp->base == FCT) {
44: // suppress ``this'' in ``this->f''
45: Pref(e)->mem->print();
46: break;
47: }
48: case NAME:
49: case MDOT:
50: case ID:
51: case ZERO:
52: case ICON:
53: case CCON:
54: case FCON:
55: case STRING:
56: case IVAL:
57: case TEXT:
58: case CM:
59: case G_CM:
60: case ELIST:
61: case COLON:
62: case ILIST:
63: case DOT:
64: case THIS:
65: case CALL:
66: case G_CALL:
67: case ICALL:
68: case ANAME:
69: e->print();
70: case DUMMY:
71: break;
72: default:
73: putch('(');
74: e->print();
75: putch(')');
76: }
77: }
78:
79: void expr::print()
80: {
81: if (this == 0) error('i',"0->E::print()");
82: if (this==e1 || this==e2) error('i',"(%p%k)->E::print(%p %p)",this,base,e1,e2);
83: // error('d',"(%d %k)->expr::print(%d %d)",this,base,e1,e2);
84:
85: switch (base) {
86: case MDOT:
87: {
88: // error('d',"mdot %s i1 %d %t",string2,i1,mem->tp);
89: int not_allocated = 0;
90: switch (i1) {
91: case 0:
92: putcat('O',string2);
93: puttok(DOT); // use sub-object directly
94: mem->print();
95: break;
96: case 1:
97: putcat('P',string2);
98: puttok(REF); // use through pointer
99: mem->print();
100: break;
101: case 2:
102: if (mem->tp->is_ptr_or_ref()==0) {
103: mem->print();
104: puttok(DOT);
105: putcat('O',string2);
106: }
107: else
108: {
109: putch('('); // REF turns pointer into object: add &
110: putch('&'); // ``this'' is a pointer
111: putch('(');
112: eprint(mem);//mem->print();
113: puttok(REF); // call sub-object directly
114: putcat('O',string2);
115: putch(')');
116: putch(')');
117: }
118: break;
119: case 5:
120: not_allocated = 1;
121: // no break;
122: case 3:
123: if (mem->tp->is_ptr_or_ref()==0) {
124: putch('('); // Px is a pointer (T*) turn it back to a T
125: putch('*'); // *Px
126: putch('(');
127: eprint(mem);//mem->print();
128: puttok(DOT); // call through pointer
129: putcat('P',string2);
130: putch(')');
131: putch(')');
132: }
133: else {
134: // eprint(mem); // <<< mem->print()
135: if (not_allocated) {
136: putch('(');
137: mem->print();
138: if ( mem->base == NAME )
139: puttok(REF);
140: else puttok(DOT);
141: putcat('O',string4);
142: putch(')');
143: }
144: else eprint(mem);
145: if (mem->base == NAME && not_allocated)
146: puttok(DOT);
147: else puttok(REF); // call through pointer
148: putcat('P',string2);
149: }
150: break;
151: case 9: // vtbl entry: (p->_vtbl).f, (p->_vtbl).i, (p->_vtbl).d
152: // or memptr: mp.f, mp.i, mp.d
153: eprint(mem);
154: putch('.');
155: putstring(string2);
156: } // end switch(i1)
157: break;
158: } // end MDOT
159:
160: case NAME:
161: { Pname n = Pname(this);
162: if (n->n_evaluated
163: // && n->tp->base!=EOBJ // this output enumerators
164: && n->n_scope!=ARG) {
165: Ptype t = tp;
166: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
167: if (t->base == EOBJ) t = Penum(Pbase(t)->b_name->tp)->e_type;
168: if (t->base!=INT || t->is_unsigned()) {
169: putstring("((");
170: bit oc = Cast;
171: Cast = 1;
172: t->print();
173: Cast = oc;
174: fprintf(out_file,")%d)",n->n_val);
175: }
176: else
177: fprintf(out_file,"%d",n->n_val);
178: }
179: else
180: n->print();
181: break;
182: }
183: case ANAME:
184: if (curr_icall) { // in expansion: look it up
185: Pname n = Pname(this);
186: int argno = int(n->n_val);
187:
188: for (Pin il=curr_icall; il; il=il->i_next)
189: if (n->n_table == il->i_table) goto aok;
190: goto bok;
191: aok:
192: if (n = il->i_args[argno].local) {
193: n->print();
194: }
195: else {
196: Pexpr ee = il->i_args[argno].arg;
197: Ptype t = il->i_args[argno].tp;
198: if (ee==0 || ee==this) error('i',"%p->E::print(A %p)",this,ee);
199: if (ee->tp==0
200: || (t!=ee->tp
201: && t->check(ee->tp,0)
202: && t->is_cl_obj()==0
203: // && eobj==0)
204: )
205: ) {
206: putstring("((");
207: bit oc = Cast;
208: Cast = 1;
209: t->print();
210: Cast = oc;
211: putch(')');
212: // eprint(ee);
213: // if (ee->base == CAST) {
214: // eprint(ee->e1);
215: // }
216: // else
217: eprint(ee);
218: putch(')');
219: }
220: else
221: eprint(ee);
222: }
223: }
224: else {
225: bok: /* in body: print it: */
226: Pname(this)->print();
227: }
228: break;
229:
230: case ICALL:
231: { il->i_next = curr_icall;
232: curr_icall = il;
233: //error('d',"icall %n",il->fct_name);
234: if (il == 0) error('i',"E::print: iline missing");
235: Pexpr a0 = il->i_args[0].arg;
236: int val = QUEST;
237: if (il->fct_name->n_oper != CTOR) goto dumb;
238:
239: /*
240: find the value of "this"
241: if the argument is a "this" NOT assigned to
242: by the programmer, it was initialized
243: */
244: switch (a0->base) {
245: case ZERO:
246: val = 0;
247: break;
248: case ADDROF:
249: case G_ADDROF:
250: val = 1;
251: break;
252: case CAST:
253: if (a0->e1->base == ANAME || a0->e1->base == NAME) {
254: Pname a = (Pname)a0->e1;
255: if (a->n_assigned_to == FUDGE111) val = FUDGE111;
256: }
257: }
258: if (val==QUEST) goto dumb;
259: /*
260: now find the test: "(this==0) ? _new(sizeof(X)) : 0"
261:
262: e1 is a comma expression,
263: the test is either the first sub-expression
264: or the first sub-expression after the assignments
265: initializing temporary variables
266: */
267: dumb:
268: eprint(e1);
269: if (e2) Pstmt(e2)->print();
270: curr_icall = il->i_next;
271: break;
272: }
273: case REF:
274: case DOT:
275: eprint(e1);
276: puttok(base);
277: if (mem == 0) {
278: fprintf(out_file,"MEM0");
279: break;
280: }
281: if (mem->base == NAME)
282: Pname(mem)->print();
283: else
284: mem->print();
285: break;
286:
287: case MEMPTR:
288: error("P toMF not called");
289: break;
290:
291: case VALUE:
292: tp2->print();
293: puttok(LP);
294:
295: // if (e2) {
296: // putstring(" &");
297: // e2->print();
298: // putstring(", ");
299: // }
300: if (e1) e1->print();
301: puttok(RP);
302: break;
303:
304: case SIZEOF:
305: puttok(SIZEOF);
306: if (e1 && e1!=dummy) {
307: eprint(e1);
308: }
309: else if (tp2) {
310: putch('(');
311: if (tp2->base == CLASS) {
312: Pclass cl = Pclass(tp2);
313: putstring((cl->csu == UNION)?"union ":"struct ");
314: char *str = 0;
315: // nested local class does not encode name
316: if ( cl->lex_level && cl->nested_sig == 0 )
317: str = make_local_name( cl );
318: putstring(str?str:(cl->nested_sig?cl->nested_sig:cl->string));
319: delete str;
320: }
321: else
322: tp2->print();
323: putch(')');
324: }
325: break;
326:
327: /*
328: // always turned into function calls:
329: case NEW:
330: case GNEW:
331: // error('d',"print new %d tp2 %t e1 %d e2 %d",base,tp2,e1,e2);
332: puttok(NEW);
333: tp2->print();
334: if (e1) {
335: putch('(');
336: e1->print();
337: putch(')');
338: }
339: break;
340:
341: case DELETE:
342: case GDELETE:
343: //error('d',"print delete");
344: puttok(DELETE);
345: e1->print();
346: break;
347: */
348: case CAST:
349: putch('(');
350: //error('d',"print cast %t",tp2);
351: if (tp2->base != VOID && tp2->memptr() == 0 ) {
352: // when VOID is represented as CHAR not everything
353: // can be cast to VOID
354: putch('(');
355: bit oc = Cast;
356: Cast = 1;
357: tp2->print();
358: Cast = oc;
359: putch(')');
360: }
361: eprint(e1);
362: putch(')');
363: break;
364:
365: case ICON:
366: case FCON:
367: case CCON:
368: case ID:
369: if (string) putst(string);
370: break;
371:
372: case STRING:
373: // avoid printing very long lines
374: ntok += 4;
375: fprintf(out_file,"\"%s\"",string);
376: break;
377:
378: case THIS:
379: case ZERO:
380: putstring("0 ");
381: break;
382:
383: case IVAL:
384: fprintf(out_file,"%d",i1);
385: break;
386:
387: case TEXT:
388: {
389: int oo = vtbl_opt; // make `simulated static' name
390: vtbl_opt = -1;
391: char* s = vtbl_name(string,string2);
392: vtbl_opt = oo;
393: s[2] = 'p'; // pointer, not tbl itself
394: char* t = ptbl_lookup(s);
395: fprintf(out_file, " %s",t);
396: delete t;
397:
398: char *str = 0;
399: if ( string ) {
400: str = new char[ strlen(string) + strlen(string2) + 1 ];
401: strcpy( str, string );
402: strcat( str, string2 );
403: }
404:
405: if ( ptbl->look( str?str:string2, 0 ) == 0 &&
406: ptbl->look( str?str:string2, HIDDEN ) == 0 ) {
407: Pname nn = ptbl->insert(new name(str?str:string2),0);
408: nn->string2 = new char[strlen(s)+1];
409: strcpy(nn->string2,s);
410: }
411:
412: delete str;
413: delete s;
414: }
415: // no break;
416:
417: case DUMMY:
418: break;
419:
420: case G_CALL:
421: case CALL:
422: { Pname fn = fct_name;
423: Pname at;
424: int m_ptr = 0;
425:
426: if (fn) {
427: Pfct f = Pfct(fn->tp);
428:
429: if (f->base==OVERLOAD) { // overloaded after call
430: fct_name = fn = Pgen(f)->fct_list->f;
431: f = Pfct(fn->tp);
432: }
433:
434: fn->print();
435: at = f->f_args;
436: }
437: else {
438: Pfct f = Pfct(e1->tp);
439:
440: if (f) { // pointer to fct
441: Pexpr exex = e1;
442: if ( exex->base == DEREF ) {
443: exex = exex->e1;
444: while ( exex->base == CAST )
445: exex = exex->e1;
446: if ( exex->base == MDOT )
447: m_ptr = 1;
448: }
449:
450: if (f->base == OVERLOAD) { // overloaded after call
451: fct_name = fn = Pgen(f)->fct_list->f;
452: f = Pfct(fn->tp);
453: }
454:
455: while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp);
456: if (f->base == PTR) {
457: putstring("(*");
458: e1->print();
459: putch(')');
460: f = Pfct(Pptr(f)->typ);
461: while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp);
462: }
463: else
464: eprint(e1);
465:
466: // at = (f->f_result) ? f->f_result : f->argtype;
467: at = f->f_args;
468: }
469: else { // virtual: argtype encoded
470: // f_this already linked to f_result and/or argtype
471: at = (e1->base==QUEST) ? Pname(e1->e1->tp2) : Pname(e1->tp2);
472: eprint(e1);
473: }
474: }
475:
476: puttok(LP);
477:
478: if (e2) {
479: if (at) {
480: Pexpr e = e2;
481: while (at) {
482: Pexpr ex;
483: Ptype t = at->tp;
484:
485: if (t == 0) error('i',"T ofA missing for%n",fn);
486: if (e == 0) error('i',"%tA missing for%n",t,fn);
487: if (e->base == ELIST) {
488: ex = e->e1;
489: e = e->e2;
490: }
491: else
492: ex = e;
493:
494: if (ex == 0) error('i',"A ofT%t missing",t);
495: if (t!=ex->tp
496: && ex->tp
497: && t->check(ex->tp,0)
498: && t->is_cl_obj()==0
499: && eobj==0
500: && m_ptr == 0
501: && (t->is_ptr()==0 || Mptr==0)) {
502: putch('(');
503: bit oc = Cast;
504: Cast = 1;
505: t->print();
506: Cast = oc;
507: putch(')');
508: #ifdef sun
509: if (ex->base == DIV) { // defend against perverse SUN cc bug
510: putstring("(0+");
511: eprint(ex);
512: putch(')');
513: }
514: else
515: #endif
516: // eprint(ex);
517: // if (ex->base==CAST) {
518: // eprint(ex->e1);
519: // }
520: // else
521: eprint(ex);
522: }
523: else
524: ex->print();
525:
526: // if m_ptr is set, then don't advance at
527: // at does not know about generated `this'
528: if ( m_ptr ) {
529: m_ptr = 0;
530: if (at) puttok(CM);
531: continue;
532: }
533:
534: at = at->n_list;
535: if (at) puttok(CM);
536: }
537: if (e) {
538: puttok(CM);
539: e->print();
540: }
541: }
542: else
543: e2->print();
544: }
545: puttok(RP);
546: break;
547: }
548:
549: case ASSIGN:
550: if (e1->base==ANAME && Pname(e1)->n_assigned_to==FUDGE111) {
551: // suppress assignment to "this" that has been optimized away
552: Pname n = Pname(e1);
553: int argno = int(n->n_val);
554: for (Pin il=curr_icall; il; il=il->i_next)
555: if (il->i_table == n->n_table) goto akk;
556: goto bkk;
557: akk:
558: if (il->i_args[argno].local == 0) {
559: e2->print();
560: break;
561: }
562: }
563: //no break
564: case EQ:
565: case NE:
566: case GT:
567: case GE:
568: case LE:
569: case LT:
570: bkk:
571: { Ptype t1 = e1->tp;
572: Ptype t2 = e2->tp;
573:
574: if (base!=ASSIGN) {
575: cprint(e1);
576: }
577: else
578: eprint(e1);
579: puttok(base);
580:
581: if (t1 && t1!=t2 && e2->base!=ZERO) {
582: // cast, but beware of int!=long etc.
583: cmp:
584: switch (t1->base) {
585: case TYPE:
586: t1 = Pbase(t1)->b_name->tp;
587: goto cmp;
588: default:
589: // if (e2->base==NAME
590: // && Pname(e2)->n_evaluated==0
591: // && e2->tp->base==EOBJ)
592: // fprintf(out_file,"(int)");
593: break;
594: // case EOBJ:
595: // if (base==ASSIGN) goto cst;
596: // break;
597: case PTR:
598: case RPTR:
599: case VEC:
600: if (t2)
601: while ( t2->base == TYPE )
602: t2 = Pbase(t2)->b_name->tp;
603:
604: if (e2->tp==0
605: || (Pptr(t1)->typ!=Pptr(t2)->typ && t1->check(t2,0))) {
606: // cst:
607: putch('(');
608: bit oc = Cast;
609: Cast = 1;
610: e1->tp->print();
611: Cast = oc;
612: putch(')');
613: }
614: }
615: }
616:
617: eprint(e2);
618: break;
619: }
620:
621: case DEREF:
622: if (e2) {
623:
624: eprint(e1);
625: putch('[');
626: cprint(e2);
627: putch(']');
628: }
629: else {
630: putch('(');
631: putch('*');
632: eprint(e1);
633: putch(')');
634: }
635: break;
636:
637: case ILIST:
638: puttok(LC);
639: if (e1) e1->print();
640: if (e2) { // member pointer initiliazers
641: puttok(CM);
642: e2->print();
643: }
644: puttok(RC);
645: break;
646:
647: case ELIST:
648: { Pexpr e = this;
649: for(;;) {
650: if (e->base == ELIST) {
651: e->e1->print();
652: if (e = e->e2) {
653: puttok(CM);
654: }
655: else
656: return;
657: }
658: else {
659: e->print();
660: return;
661: }
662: }
663: }
664:
665: case QUEST:
666: { // look for (&a == 0) etc.
667: Neval = 0;
668: binary_val = 1;
669: long i = cond->eval();
670: binary_val = 0;
671: if (Neval == 0)
672: (i?e1:e2)->print();
673: else {
674: eprint(cond);
675: putch('?');
676: cprint(e1);
677: putch(':');
678: cprint(e2);
679: }
680: break;
681: }
682:
683: case CM: // do &(a,b) => (a,&b) for previously checked inlines
684: case G_CM:
685: puttok(LP);
686: switch (e1->base) {
687: case ZERO:
688: case IVAL:
689: case ICON:
690: case NAME:
691: case MDOT:
692: case DOT:
693: case REF:
694: case FCON:
695: // case FVAL:
696: case STRING:
697: goto le2; // suppress constant a: &(a,b) => (&b)
698: default:
699: { int oo = addrof_cm; // &(a,b) does not affect a
700: addrof_cm = 0;
701: eprint(e1);
702: addrof_cm = oo;
703: }
704: puttok(CM);
705: le2:
706: if (addrof_cm) {
707: switch (e2->base) {
708: case CAST:
709: if (e2->e2)
710: switch (e2->e2->base) {
711: case CM:
712: case G_CM:
713: case ICALL: goto ec;
714: }
715: case NAME:
716: case MDOT:
717: case DOT:
718: case DEREF:
719: case REF:
720: case ANAME:
721: puttok(ADDROF);
722: addrof_cm--;
723: eprint(e2);
724: addrof_cm++;
725: break;
726: case ICALL:
727: // case CALL:
728: case CM:
729: case G_CM:
730: ec:
731: eprint(e2);
732: break;
733: case G_CALL:
734: /* & ( e, ctor() ) with temporary optimized away */
735: if (e2->fct_name
736: && e2->fct_name->n_oper==CTOR) {
737: addrof_cm--;
738: eprint(e2);
739: addrof_cm++;
740: break;
741: }
742: default:
743: error('i',"& inlineF call (%k)",e2->base);
744: }
745: }
746: else
747: // e2->print();
748: eprint(e2);
749: puttok(RP);
750: }
751: break;
752:
753: case UPLUS: // only preserved for ansi_opt==1
754: case UMINUS:
755: case NOT:
756: case COMPL:
757: // puttok(base);
758: // eprint(e2);
759: // break;
760: goto op2;
761: case ADDROF:
762: case G_ADDROF:
763: switch (e2->base) { // & *e1 or &e1[e2]
764: case DEREF:
765: if (e2->e2 == 0) { // &*e == e
766: e2->e1->print();
767: return;
768: }
769: break;
770: case ICALL:
771: addrof_cm++; // assumes inline expanded into ,-expression
772: eprint(e2);
773: addrof_cm--;
774: return;
775: case ASSIGN: // &(a=b) ??? works on many cc s
776: eprint(e2); // make sure it breaks!
777: return;
778: case NAME: {
779: Pname n = Pname(e2);
780: if(n->n_evaluated) {
781: n->n_evaluated=0;
782: puttok(ADDROF);
783: eprint(e2);
784: n->n_evaluated=1;
785: return;
786: }
787: break;
788: }
789: }
790:
791: // suppress cc warning on &fct
792: if (e2->tp==0 || e2->tp->base!=FCT) puttok(ADDROF);
793:
794: eprint(e2);
795: break;
796:
797: case PLUS:
798: case MINUS:
799: case MUL:
800: case DIV:
801: case MOD:
802: case LS:
803: case RS:
804: case AND:
805: case OR:
806: case ER:
807: case ANDAND:
808: case OROR:
809: case DECR:
810: case INCR:
811: cprint(e1);
812: op2:
813: puttok(base);
814: cprint(e2);
815: break;
816: case ASOR:
817: case ASER:
818: case ASAND:
819: case ASPLUS:
820: case ASMINUS:
821: case ASMUL:
822: case ASMOD:
823: case ASDIV:
824: case ASLS:
825: case ASRS:
826: eprint(e1);
827: goto op2;
828:
829: default:
830: error('i',"%p->E::print%k",this,base);
831: // fprintf(out_file," EEE(%d) ",base);
832: }
833: }
834:
835: Pexpr aval(Pname a)
836: {
837: int argno = int(a->n_val);
838: Pin il;
839: for (il=curr_icall; il; il=il->i_next)
840: if (il->i_table == a->n_table) goto aok;
841: return 0;
842: aok:
843: Pexpr aa = il->i_args[argno].arg;
844: ll:
845: switch (aa->base) {
846: case CAST: aa = aa->e1; goto ll;
847: case ANAME: return aval(Pname(aa));
848: default: return aa;
849: }
850: }
851:
852: #define putcond() putch('('); e->print(); putch(')')
853:
854: static loc csloc = { 0, 0 }; // loc of last stmt with line!=0
855:
856: void stmt::print()
857: {
858: //error('d',"S::print %d:%k s %d s_list %d",this,base,s,s_list);
859: if (where.line == 0) {
860: if (csloc.line) csloc.putline();
861: } else {
862: csloc = where;
863: if (where.line!=last_line.line)
864: if (last_ll = where.line)
865: where.putline();
866: else
867: last_line.putline();
868: }
869:
870: if (memtbl && base!=BLOCK) { /* also print declarations of temporaries */
871: puttok(LC);
872: Ptable tbl = memtbl;
873: memtbl = 0;
874: int i;
875: int bl = 1;
876: for (Pname n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i)){
877: if (n->tp == any_type) continue;
878: /* avoid double declarartion of temporaries from inlines */
879: char* s = n->string;
880: if (s[0]!='_' || s[1]!='_' || s[2]!='X') {
881: n->dcl_print(0);
882: bl = 0;
883: }
884: Pname cn;
885: if (bl
886: && (cn=n->tp->is_cl_obj())
887: && Pclass(cn->tp)->has_dtor()) bl = 0;
888: }
889: if ( last_ll==0 && (last_ll = where.line) )
890: where.putline();
891: if (bl) {
892: Pstmt sl = s_list;
893: s_list = 0;
894: print();
895: memtbl = tbl;
896: puttok(RC);
897: if (sl) {
898: s_list = sl;
899: sl->print();
900: }
901: }
902: else {
903: print();
904: memtbl = tbl;
905: puttok(RC);
906: }
907: return;
908: }
909:
910: switch (base) {
911: default:
912: error('i',"S::print(base=%k)",base);
913:
914: case ASM:
915: fprintf(out_file,"asm(\"%s\");\n",(char*)e);
916: break;
917:
918: case DCL:
919: d->dcl_print(SM);
920: break;
921:
922: case BREAK:
923: case CONTINUE:
924: puttok(base);
925: puttok(SM);
926: break;
927:
928: case DEFAULT:
929: puttok(base);
930: //puttok(COLON);
931: putch(':');
932: s->print();
933: break;
934:
935: case SM:
936: if (e) {
937: e->print();
938: if (e->base==ICALL && e->e2) break; /* a block: no SM */
939: }
940: puttok(SM);
941: break;
942:
943: case WHILE:
944: puttok(WHILE);
945: putcond();
946: if (s->s_list) {
947: puttok(LC);
948: s->print();
949: puttok(RC);
950: }
951: else
952: s->print();
953: break;
954:
955: case DO:
956: puttok(DO);
957: s->print();
958: puttok(WHILE);
959: putcond();
960: puttok(SM);
961: break;
962:
963: case SWITCH:
964: puttok(SWITCH);
965: putcond();
966: s->print();
967: break;
968:
969: case RETURN:
970: {
971: puttok(RETURN);
972: if (e) {
973: //error('d',"print return rt %t etp %t",ret_tp,e->tp);
974: if (ret_tp && ret_tp!=e->tp) {
975: Ptype tt = ret_tp;
976: gook:
977: switch (tt->base) {
978: case TYPE:
979: tt = Pbase(tt)->b_name->tp;
980: goto gook;
981: case COBJ:
982: break; // cannot cast to struct
983: case RPTR:
984: case PTR:
985: if (Pptr(tt)->typ==Pptr(e->tp)->typ) break;
986: if (Pptr(tt)->memof) break;
987: default:
988: if (e->tp==0 || ret_tp->check(e->tp,0)) {
989: int oc = Cast;
990: putch('(');
991: Cast = 1;
992: ret_tp->print();
993: Cast = oc;
994: putch(')');
995: }
996: }
997: }
998: eprint(e);
999: }
1000: puttok(SM);
1001: }
1002: while (s_list && s_list->base==SM) s_list = s_list->s_list; // FUDGE!!
1003: break;
1004:
1005: case CASE:
1006: puttok(CASE);
1007: eprint(e);
1008: putch(':');
1009: s->print();
1010: break;
1011:
1012: case GOTO:
1013: puttok(GOTO);
1014: d->print();
1015: puttok(SM);
1016: break;
1017:
1018: case LABEL:
1019: d->print();
1020: putch(':');
1021: s->print();
1022: break;
1023:
1024: case IF:
1025: { int val = QUEST;
1026: if (e->base == ANAME) {
1027: Pname a = Pname(e);
1028: Pexpr arg = aval(a);
1029: //error('d',"arg %d%k %d (%d)",arg,arg?arg->base:0,arg?arg->base:0,arg?arg->e1:0);
1030: if (arg)
1031: switch (arg->base) {
1032: case ZERO: val = 0; break;
1033: case ADDROF:
1034: case G_ADDROF: val = 1; break;
1035: case IVAL: val = arg->i1!=0;
1036: }
1037: }
1038: //error('d',"val %d",val);
1039: switch (val) {
1040: case 1:
1041: s->print();
1042: break;
1043: case 0:
1044: if (else_stmt)
1045: else_stmt->print();
1046: else
1047: puttok(SM); /* null statement */
1048: break;
1049: default:
1050: puttok(IF);
1051: putcond();
1052: if (s->s_list) {
1053: puttok(LC);
1054: s->print();
1055: puttok(RC);
1056: }
1057: else
1058: s->print();
1059: if (else_stmt) {
1060: if (else_stmt->where.line == 0) {
1061: if (csloc.line) csloc.putline();
1062: } else {
1063: csloc = else_stmt->where;
1064: if (else_stmt->where.line!=last_line.line)
1065: if (last_ll = else_stmt->where.line)
1066: else_stmt->where.putline();
1067: else
1068: last_line.putline();
1069: }
1070: puttok(ELSE);
1071: if (else_stmt->s_list) {
1072: puttok(LC);
1073: else_stmt->print();
1074: puttok(RC);
1075: }
1076: else
1077: else_stmt->print();
1078: }
1079: }
1080: break;
1081: }
1082:
1083: case FOR:
1084: {
1085: // int fi = for_init && ((for_init->base!=SM || for_init->memtbl || for_init->s_list);
1086: int fi = 0; // is the initializer statement an expression?
1087: if (for_init) {
1088: fi = 1;
1089: if (for_init->memtbl==0 && for_init->s_list==0)
1090: if (for_init->base==SM)
1091: if (for_init->e->base!=ICALL || for_init->e->e1)
1092: fi = 0;
1093: }
1094: //error('d',"for(; %d%k; %d%k)",e,e->base,e2,e2->base);
1095: if (fi) {
1096: puttok(LC);
1097: for_init->print();
1098: }
1099: putstring("for(");
1100: if (fi==0 && for_init) for_init->e->print();
1101: putch(';'); // to avoid newline: not puttok(SM)
1102: if (e) e->print();
1103: putch(';');
1104: if (e2) e2->print();
1105: puttok(RP);
1106: s->print();
1107: if (fi) puttok(RC);
1108: break;
1109: }
1110:
1111: case PAIR:
1112: if (s&&s2) {
1113: puttok(LC);
1114: s->print();
1115: s2->print();
1116: puttok(RC);
1117: }
1118: else {
1119: if (s) s->print();
1120: if (s2) s2->print();
1121: }
1122: break;
1123:
1124: case BLOCK:
1125: puttok(LC);
1126: //error('d',"block %d d %d memtbl %d own_tbl %d",this,d,memtbl,own_tbl);
1127: if (d) d->dcl_print(SM);
1128: if (memtbl && own_tbl) {
1129: Pname n;
1130: int i;
1131: for (n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) {
1132: if (n->tp && n->n_union==0 && n->tp!=any_type)
1133: switch (n->n_scope) {
1134: case ARGT:
1135: case ARG:
1136: break;
1137: default:
1138: // error('d', "n: %s %k n_key: %k", n->string, n->base, n->n_key);
1139: if ( n->base == TNAME && n->n_key == NESTED )
1140: continue; // printed from nested class
1141: n->dcl_print(0);
1142: }
1143: }
1144: if (last_ll==0 && s && (last_ll=s->where.line))
1145: s->where.putline();
1146: }
1147: if (s) s->print();
1148: if (where2.line == 0) {
1149: if (csloc.line) csloc.putline();
1150: } else {
1151: csloc = where2;
1152: if (where2.line!=last_line.line)
1153: if (last_ll = where2.line)
1154: where2.putline();
1155: else
1156: last_line.putline();
1157: }
1158: putstring("}\n");
1159: if (last_ll && where.line) last_line.line++;
1160: }
1161:
1162: if (s_list) s_list->print();
1163: }
1164:
1165: /*
1166: void table::dcl_print(TOK s, TOK pub)
1167:
1168: // print the declarations of the entries in the order they were inserted
1169: // ignore labels (tp==0)
1170:
1171: {
1172: register Pname* np;
1173: register int i;
1174:
1175: if (this == 0) return;
1176:
1177: np = entries;
1178: for (i=1; i<free_slot; i++) {
1179: register Pname n = np[i];
1180: switch (s) {
1181: case 0:
1182: n->dcl_print(0);
1183: break;
1184: case EQ:
1185: if (n->tp && n->n_scope == pub) n->dcl_print(0);
1186: break;
1187: case NE:
1188: if (n->tp && n->n_scope != pub) n->dcl_print(0);
1189: break;
1190: }
1191: }
1192: }
1193: */
1194:
1195: struct ptbl_rec {
1196: char* pname;
1197: char* vname;
1198: ptbl_rec* next;
1199: };
1200:
1201: static char* ptbl_name;
1202: static ptbl_rec* ptbl_rec_lookup_head = 0;
1203: static ptbl_rec* ptbl_rec_pair_head = 0;
1204:
1205: void ptbl_init(int flag)
1206: {
1207: if (!flag) {
1208: char *p = st_name( "__ptbl_vec__" );
1209: ptbl_name = new char[strlen(p)+1];
1210: strcpy(ptbl_name, p);
1211: delete p;
1212: fprintf(out_file, "extern struct __mptr* %s[];\n", ptbl_name);
1213: if (last_ll) last_line.line++;
1214: }
1215: else {
1216: ptbl_rec *r, *p = ptbl_rec_lookup_head;
1217: if ( p == 0 ) return; // don't generate an empty object
1218: fprintf(out_file, "struct __mptr* %s[] = {\n", ptbl_name);
1219: if (last_ll) last_line.line++;
1220: int i = 0;
1221: while (p != 0) {
1222: r = ptbl_rec_pair_head;
1223: while (r && strcmp(r->pname, p->pname))
1224: r = r->next;
1225: fprintf(out_file, "%s,\n", r->vname);
1226: if (last_ll) last_line.line++;
1227: p = p->next;
1228: }
1229: // fprintf(out_file, "0\n};\n");
1230: fprintf(out_file, "\n};\n");
1231: if (last_ll) last_line.line += 2;
1232: }
1233: }
1234:
1235: char* ptbl_lookup(char *name)
1236: {
1237: ptbl_rec *r, *s, *p = ptbl_rec_lookup_head;
1238: int i = 0;
1239:
1240: while (p && strcmp(name, p->pname)) {
1241: r = p;
1242: p = p->next;
1243: i++;
1244: }
1245:
1246: if (p == 0) {
1247: s = new ptbl_rec;
1248: s->pname = new char[strlen(name) + 1];
1249: s->vname = 0;
1250: s->next = 0;
1251: strcpy(s->pname, name);
1252: if (ptbl_rec_lookup_head == 0)
1253: ptbl_rec_lookup_head = s;
1254: else r->next = s;
1255: }
1256:
1257: char *pp = new char[ strlen(ptbl_name) + 10 ];
1258: sprintf(pp, "%s[%d]", ptbl_name, i);
1259: return(pp);
1260: }
1261:
1262: void ptbl_add_pair(char* ptbl, char* vtbl)
1263: {
1264: // error('d', "ptbl_add_pair: ptbl: %s, vtbl: %s", ptbl, vtbl );
1265: ptbl_rec *p = new ptbl_rec;
1266:
1267: p->pname = new char[strlen(ptbl) + 1];
1268: strcpy(p->pname, ptbl);
1269: p->vname = new char[strlen(vtbl) + 1];
1270:
1271: strcpy(p->vname, vtbl);
1272: p->next = ptbl_rec_pair_head;
1273:
1274: ptbl_rec_pair_head = p;
1275: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.