File contents
/*ident "@(#)cls4:src/print.c 1.21" */
/*******************************************************************************
C++ source for the C++ Language System, Release 3.0. This product
is a new release of the original cfront developed in the computer
science research center of AT&T Bell Laboratories.
Copyright (c) 1993 UNIX System Laboratories, Inc.
Copyright (c) 1991, 1992 AT&T and UNIX System Laboratories, Inc.
Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved.
THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System
Laboratories, Inc. The copyright notice above does not evidence
any actual or intended publication of such source code.
print.c:
print statements and expressions
****************************************************************************/
#include "cfront.h"
static int addrof_cm ;
extern void puttok(TOK);
#define eprint(e) if (e) Eprint(e)
static long lab_cnt = 0;
static long curr_lab = 0;
void Eprint(Pexpr e)
{
switch (e->base) {
case DOT:
case REF:
if (
Pref(e)->mem
&&
Pref(e)->mem->tp
&&
Pref(e)->mem->tp->base == FCT
) { // suppress ``this'' in ``this->f''
Pref(e)->mem->print();
break;
}
case NAME:
case MDOT:
case ID:
case ZERO:
case ICON:
case CCON:
case FCON:
case STRING:
case IVAL:
case TEXT:
case CM:
case G_CM:
case ELIST:
case COLON:
case ILIST:
case THIS:
case CALL:
case G_CALL:
case ICALL:
case ANAME:
e->print();
break;
case DTOR: // dummy type destructor
error('i',"T destructor in %cprint()",'E');
case DUMMY: // null or error
break;
default:
putch('(');
e->print();
putch(')');
}
}
void expr::print()
{
if (this == 0) error('i',"0->E::print()");
if ((this==e1 || this==e2)&&base!=NAME) error('i',"(%p%k)->E::print(%p %p)",this,base,e1,e2);
// error('d',"(%d %k)->expr::print(%d %d)",this,base,e1,e2);
switch (base) {
case MDOT:
{
// error('d',"mdot %s i1 %d %t",string2,i1,mem->tp);
int not_allocated = 0;
switch (i1) {
case 0:
putcat('O',string2);
puttok(DOT); // use sub-object directly
mem->print();
break;
case 1:
putcat('P',string2);
puttok(REF); // use through pointer
mem->print();
break;
case 2:
if (mem->tp->is_ptr_or_ref()==0) {
mem->print();
puttok(DOT);
putcat('O',string2);
}
else {
putch('('); // REF turns pointer into object: add &
putch('&'); // ``this'' is a pointer
putch('(');
eprint(mem);
puttok(REF); // call sub-object directly
putcat('O',string2);
putch(')');
putch(')');
}
break;
case 5:
not_allocated = 1;
// no break;
case 3:
if (mem->tp->is_ptr_or_ref()==0) {
putch('('); // Px is a pointer (T*) turn it back to a T
putch('*'); // *Px
putch('(');
eprint(mem); // mem->print();
puttok(DOT); // call through pointer
putcat('P',string2);
putch(')');
putch(')');
}
else {
TOK m = mem->base;
if (m == ADDROF || m == G_ADDROF) {
if (mem->e2->base == DEREF && !mem->e2->e2)
m = mem->e2->e1->base;
}
if (not_allocated) {
putch('(');
mem->print();
if ( m == NAME || m == ANAME || m==REF )
puttok(REF);
else
puttok(DOT);
putcat('O',string4);
putch(')');
}
else
eprint(mem);
if ((m == NAME || m == ANAME || m == REF) && not_allocated)
puttok(DOT);
else
puttok(REF); // call through pointer
putcat('P',string2);
}
break;
case 9: // vtbl entry: (p->_vtbl).f, (p->_vtbl).i, (p->_vtbl).d
// or memptr: mp.f, mp.i, mp.d
eprint(mem);
putch('.');
putstring(string2);
} // end switch(i1)
break;
} // end MDOT
case NAME:
{ Pname n = Pname(this);
if (n->n_evaluated && n->n_scope!=ARG) {
Ptype t = tp->skiptypedefs();
if (t->base == EOBJ)
t = Penum(Pbase(t)->b_name->tp)->e_type;
if (t->base!=INT || t->is_unsigned()) {
putstring("((");
bit oc = Cast;
Cast = 1;
t->print();
Cast = oc;
fprintf(out_file,")%d)",n->n_val);
}
else
fprintf(out_file,"%d",n->n_val);
}
else
n->print();
break;
}
case ANAME:
if (curr_icall) { // in expansion: look it up
Pname n = Pname(this);
int argno = n->argno;
for (Pin il=curr_icall; il; il=il->i_next)
if (n->n_table == il->i_table)
goto aok;
goto bok;
aok:
if (n = il->i_args[argno].local) {
n->print();
}
else {
Pexpr ee = il->i_args[argno].arg;
Ptype t = il->i_args[argno].tp;
if (ee==0 || ee==this)
error('i',"%p->E::print(A %p)",this,ee);
if (
ee->tp==0
||
(
t!=ee->tp
&&
t->check(ee->tp,0)
&&
t->is_cl_obj()==0
)
) {
putstring("((");
bit oc = Cast;
Cast = 1;
t->print();
Cast = oc;
putch(')');
eprint(ee);
putch(')');
}
else
eprint(ee);
}
}
else {
bok: /* in body: print it: */
Pname(this)->print();
}
break;
case ICALL:
{
if (il == 0)
error('i',"E::print: iline missing");
il->i_next = curr_icall;
curr_icall = il;
//error('d',"icall %n",il->fct_name);
eprint(e1);
if (e2) {
long save = curr_lab;
curr_lab = ++lab_cnt;
Pstmt(e2)->print();
curr_lab = save;
}
curr_icall = il->i_next;
break;
}
case REF:
case DOT:
eprint(e1);
puttok(base);
if (mem == 0) {
fprintf(out_file,"MEM0");
break;
}
if (mem->base == NAME)
Pname(mem)->print();
else
mem->print();
break;
case MEMPTR:
error("P toMF not called");
break;
case VALUE:
tp2->print();
puttok(LP);
if (e1)
e1->print();
puttok(RP);
break;
case SIZEOF:
puttok(SIZEOF);
if (e1 && e1!=dummy && e1->base != ILIST && ((e1->base != CAST && e1->base != G_CAST) || e1->e1->base != ILIST)) {
eprint(e1);
}
else if (tp2) {
putch('(');
if (tp2->base == CLASS) {
Pclass cl = Pclass(tp2);
putstring((cl->csu == UNION)?"union ":"struct ");
char *str = 0;
// nested local class does not encode name
if ( cl->lex_level && cl->nested_sig == 0 )
str = cl->local_sig;
// putstring(str?str:(cl->nested_sig?cl->nested_sig:cl->string));
if (str)
putstring(str);
else if (cl->nested_sig)
fprintf(out_file,"__%s",cl->nested_sig);
else putstring(cl->string);
}
else
tp2->print();
putch(')');
}
else {
error('i', "missingE for sizeof");
}
break;
case CAST:
case G_CAST:
if (e1->base == ILIST) {
eprint(e1);
break;
}
putch('(');
//error('d',"print cast %t",tp2);
if (tp2 != mptr_type && (tp2->base != VOID || ansi_opt) && tp2->memptr() == 0 ) {
// when VOID is represented as CHAR not everything
// can be cast to VOID
putch('(');
bit oc = Cast;
Cast = 1;
if (tp2->base==TYPE || tp2->base==VEC)
TCast = 1;
else TCast = 0;
tp2->print();
TCast=0;
Cast = oc;
putch(')');
}
eprint(e1);
putch(')');
break;
case ICON:
case FCON:
case CCON:
case ID:
if (string)
putst(string);
break;
case STRING:
// avoid printing very long lines
ntok += 4;
fprintf(out_file,"\"%s\"",string);
break;
case THIS:
case ZERO:
putstring("0 ");
break;
case IVAL:
fprintf(out_file,"%d",i1);
break;
case TEXT:
{
int oo = vtbl_opt; // make `simulated static' name
vtbl_opt = -1;
char* s = vtbl_name(string,string2);
vtbl_opt = oo;
s[2] = 'p'; // pointer, not tbl itself
char* t = ptbl_lookup(s);
fprintf(out_file, " %s",t);
delete t;
char *str = 0;
if ( string ) {
str = new char[ strlen(string) + strlen(string2) + 1 ];
strcpy( str, string );
strcat( str, string2 );
}
if (
ptbl->look( str?str:string2, 0 ) == 0
&&
ptbl->look( str?str:string2, HIDDEN ) == 0
) {
Pname nn = ptbl->insert(new name(str?str:string2),0);
nn->string2 = new char[strlen(s)+1];
strcpy(nn->string2,s);
}
delete str;
delete s;
}
break;
case DTOR: // dummy type destructor
error('i',"T destructor in expr::print()");
case DUMMY: // null or error
break;
case G_CALL:
case CALL:
{ Pname fn = fct_name;
Pname at;
int m_ptr = 0;
int comflag = 0;
if (fn) {
Pfct f = Pfct(fn->tp);
if (f->base==OVERLOAD) { // overloaded after call
fct_name = fn = Pgen(f)->fct_list->f;
f = Pfct(fn->tp);
}
if (e1->base == CM || e1->base == G_CM) {
comflag = 1;
puttok(LP);
e1->e1->print();
puttok(CM);
}
fn->print();
at = f->f_args;
}
else {
Pfct f = Pfct(e1->tp);
if (f) { // pointer to fct
Pexpr exex = e1;
if ( exex->base == DEREF ) {
exex = exex->e1;
while ( exex->base == CAST ||
exex->base == G_CAST)
exex = exex->e1;
if ( exex->base == MDOT )
m_ptr = 1;
}
if (f->base == OVERLOAD) { // overloaded after call
fct_name = fn = Pgen(f)->fct_list->f;
f = Pfct(fn->tp);
}
f = Pfct(f->skiptypedefs());
if (f->base == PTR) {
putstring("(*(");
e1->print();
putstring("))");
f = Pfct(Pptr(f)->typ->skiptypedefs());
}
else
eprint(e1);
at = f->f_args;
}
else { // virtual: argtype encoded
// f_this already linked to f_result and/or argtype
at = (e1->base==QUEST) ? Pname(e1->e1->tp2) : Pname(e1->tp2);
eprint(e1);
}
}
puttok(LP);
if (e2) {
if (at) {
Pexpr e = e2;
while (at) {
Pexpr ex;
Ptype t = at->tp;
if (t == 0)
error('i',"T ofA missing for%n",fn);
if (e == 0)
error('i',"%tA missing for%n",t,fn);
if (e->base == ELIST) {
ex = e->e1;
e = e->e2;
}
else
ex = e;
if (ex == 0)
error('i',"A ofT%t missing",t);
if (
t!=ex->tp
&&
ex->tp
&&
t->check(ex->tp,0)
&&
t->is_cl_obj()==0
&&
eobj==0
&&
m_ptr == 0
&&
(
t->is_ptr()==0
||
Mptr==0
)
) {
putch('(');
bit oc = Cast;
Cast = 1;
t->print();
Cast = oc;
putch(')');
#ifdef sun
if (ex->base == DIV) { // defend against perverse SUN cc bug
putstring("(0+");
eprint(ex);
putch(')');
}
else {
#endif
if (ex->tp->is_cl_obj() &&
((ex->base!=NAME && ex->base!=ANAME) || Pname(ex)->n_xref==0) && // beware of reference arguments
(t->is_ptr()||t->is_ref())) {
// trying to cast a class object to its pointer type
// add `&' to compensate from use of constructor call
// rewritten to use temporaty in ?: expression.
//error('d',"t %t ex->tp %t",t,ex->tp);
ex = ex->address();
}
eprint(ex);
#ifdef sun
}
#endif
}
else
ex->print();
// if m_ptr is set, then don't advance at
// at does not know about generated `this'
if ( m_ptr ) {
m_ptr = 0;
if (at)
puttok(CM);
continue;
}
at = at->n_list;
if (at)
puttok(CM);
}
if (e) {
puttok(CM);
e->print();
}
}
else
e2->print();
}
puttok(RP);
if (comflag)
puttok(RP);
break;
}
case ASSIGN:
if (
e1->base==ANAME
&&
Pname(e1)->n_assigned_to==FUDGE111
) { // suppress assignment to "this"
// that has been optimized away
Pname n = Pname(e1);
int argno = int(n->n_val);
for (Pin il=curr_icall; il; il=il->i_next)
if (il->i_table == n->n_table)
goto akk;
goto bkk;
akk:
if (il->i_args[argno].local == 0) {
e2->print();
break;
}
}
//no break
case EQ:
case NE:
case GT:
case GE:
case LE:
case LT:
bkk:
{
eprint(e1);
puttok(base);
if (
e1->tp
&&
e1->tp!=e2->tp
&&
e2->base!=ZERO
) { // cast, but beware of int!=long etc.
Ptype t1 = e1->tp->skiptypedefs();
switch (t1->base) {
default:
break;
case PTR:
case RPTR:
case VEC:
{
Ptype t2 = e2->tp->skiptypedefs();
if (
e2->tp==0
||
( !ansi_opt
&&
Pptr(t1)->typ
&&
Pptr(t1)->typ->skiptypedefs()->base==VEC
&&
e2->base != G_CAST
&&
e2->base != CAST
)
||
(
Pptr(t1)->typ!=Pptr(t2)->typ
&&
t1->check(t2,0)
&& (
t1->memptr() == 0
||
t2->memptr() == 0
||
t1->check(t2,COERCE)
)
)
) {
putch('(');
bit oc = Cast;
Cast = 1;
e1->tp->print();
Cast = oc;
putch(')');
}
}
}
}
eprint(e2);
break;
}
case DEREF:
if (e2) {
eprint(e1);
putch('[');
eprint(e2);
putch(']');
}
else {
putch('(');
putch('*');
eprint(e1);
putch(')');
}
break;
case ILIST: {
static int level = 0;
level++;
bit flag = (level > 1 && tp && (tp == zero_type || tp->memptr()));
if (!flag)
puttok(LC);
if (e1)
e1->print();
if (e2) { // member pointer initiliazers
puttok(CM);
e2->print();
}
if (!flag)
puttok(RC);
level--;
break;
}
case ELIST:
{ Pexpr e = this;
for(;;) {
if (e->base == ELIST) {
e->e1->print();
if (e = e->e2) {
puttok(CM);
}
else
return;
}
else {
e->print();
return;
}
}
}
case QUEST:
{ // look for (&a == 0) etc.
Neval = 0;
binary_val = 1;
long i = cond->eval();
binary_val = 0;
if (Neval == 0)
(i?e1:e2)->print();
else {
eprint(cond);
putch('?');
if (!ansi_opt) {
if ((e1->base == CAST || e1->base == G_CAST) &&
e1->tp && !e1->tp->check(void_type, 0)) {
e1 = new expr(G_CM, e1->e1, zero);
e1->tp = zero_type;
}
if ((e2->base == CAST || e2->base == G_CAST) &&
e2->tp && !e2->tp->check(void_type, 0)) {
e2 = new expr(G_CM, e2->e1, zero);
e2->tp = zero_type;
}
}
eprint(e1);
putch(':');
eprint(e2);
}
break;
}
case CM: // do &(a,b) => (a,&b) for previously checked inlines
case G_CM:
puttok(LP);
switch (e1->base) {
case ZERO:
case IVAL:
case ICON:
case NAME:
case DUMMY:
case MDOT:
case DOT:
case REF:
case FCON:
case STRING:
goto le2; // suppress constant a: &(a,b) => (&b)
case DTOR:
error('i',"T destructor in expr::print()");
default:
{
int oo = addrof_cm; // &(a,b) does not affect a
addrof_cm = 0;
eprint(e1);
addrof_cm = oo;
}
puttok(CM);
le2:
if (addrof_cm) {
switch (e2->base) {
case CAST:
case G_CAST:
if (e2->e2)
switch (e2->e2->base) {
case CM:
case G_CM:
case ICALL: goto ec;
}
case NAME:
case MDOT:
case DOT:
case DEREF:
case REF:
case ANAME:
if (e2->base != ADDROF &&
e2->base != G_ADDROF)
puttok(ADDROF);
addrof_cm--;
eprint(e2);
addrof_cm++;
break;
case ICALL:
case CM:
case G_CM:
ec:
eprint(e2);
break;
case G_CALL:
/* & ( e, ctor() ) with temporary optimized away */
if (e2->fct_name && e2->fct_name->n_oper==CTOR) {
addrof_cm--;
eprint(e2);
addrof_cm++;
break;
}
default:
error('i',"& inlineF call (%k)",e2->base);
}
}
else
eprint(e2);
puttok(RP);
}
break;
case ADDROF:
case G_ADDROF:
{
switch (e2->base) { // & *e1 or &e1[e2]
case DEREF:
if (e2->e2 == 0) { // &*e == e
e2->e1->print();
return;
}
break;
case ICALL:
addrof_cm++; // assumes inline expanded into ,-expression
eprint(e2);
addrof_cm--;
return;
case ASSIGN: // &(a=b) ??? works on many cc s
eprint(e2); // make sure it breaks!
return;
case ANAME:
case NAME: {
Pname n = Pname (e2);
if(n->n_evaluated) {
n->n_evaluated=0;
if (e2->base != ADDROF &&
e2->base != G_ADDROF)
puttok(ADDROF);
eprint(e2);
n->n_evaluated=1;
return;
}
if ((e2->tp) && (e2->tp->is_cl_obj()) &&
n->n_xref) {
eprint (e2);
return;
}
if (!ansi_opt && (e2->tp &&
e2->tp->skiptypedefs()->base==VEC ) ) {
//no "ADDROF" ('&') if not ANSI C generation.
eprint(e2);
return;
}
break;
}
}
// suppress cc warning on &fct
if ((e2->base != ADDROF && e2->base != G_ADDROF) &&
(e2->tp==0 || (e2->tp->base!=FCT && e2->tp->base!=OVERLOAD)))
puttok(ADDROF);
if (e2->tp && e2->tp->base==OVERLOAD)
e2->tp = Pfct((Pgen(e2->tp)->fct_list->f)->tp);
eprint(e2);
}
break;
case PLUS:
case MINUS:
case MUL:
case DIV:
case MOD:
case LS:
case RS:
case AND:
case OR:
case ER:
case ANDAND:
case OROR:
case DECR:
case INCR:
case ASOR:
case ASER:
case ASAND:
case ASPLUS:
case ASMINUS:
case ASMUL:
case ASMOD:
case ASDIV:
case ASLS:
case ASRS:
eprint(e1);
// no break
case UPLUS: // only preserved for ansi_opt==1
case UMINUS:
case NOT:
case COMPL:
puttok(base);
eprint(e2);
break;
default:
error('i',"%p->E::print%k",this,base);
}
}
Pexpr aval(Pname a)
{
int argno = a->argno;
Pin il;
for (il=curr_icall; il; il=il->i_next)
if (il->i_table == a->n_table)
goto aok;
return 0;
aok:
Pexpr aa = il->i_args[argno].arg;
ll:
switch (aa->base) {
case G_CAST:
case CAST: aa = aa->e1; goto ll;
case ANAME: return aval(Pname(aa));
default: return aa;
}
}
static void reprint(Plist ll)
/* prints a name list in reverse order */
{
if (ll->l)
reprint(ll->l);
ll->f->dcl_print(0);
}
#define putcond(e) putch('('); e->print(); putch(')')
static loc csloc = { 0, 0 }; // loc of last stmt with line!=0
void stmt::print()
{
//error('d',"S::print %d:%k s %d s_list %d",this,base,s,s_list);
if (where.line == 0) {
if (csloc.line)
csloc.putline();
}
else {
csloc = where;
if (where.line!=last_line.line)
if (last_ll = where.line)
where.putline();
else
last_line.putline();
}
if (memtbl && base!=BLOCK) { /* also print declarations of temporaries */
puttok(LC);
Ptable tbl = memtbl;
memtbl = 0;
int i;
int bl = 1;
for (Pname n=tbl->get_mem(i=1); n; NEXT_NAME(tbl,n,i)) {
if (n->tp == any_type)
continue;
/* avoid double declarartion of temporaries from inlines */
char* s = n->string;
if (
s[0]!='_'
||
s[1]!='_'
||
s[2]!='X'
) {
n->dcl_print(0);
bl = 0;
}
Pname cn;
if (
bl
&&
(cn=n->tp->is_cl_obj())
&&
Pclass(cn->tp)->has_dtor()
)
bl = 0;
}
if ( last_ll==0 && (last_ll = where.line) )
where.putline();
if (bl) {
Pstmt sl = s_list;
s_list = 0;
print();
memtbl = tbl;
puttok(RC);
if (sl) {
s_list = sl;
sl->print();
}
}
else {
print();
memtbl = tbl;
puttok(RC);
}
return;
}
switch (base) {
default:
error('i',"S::print(base=%k)",base);
case ASM:
fprintf(out_file,"asm(\"%s\");\n",(char*)e);
break;
case DCL:
d->dcl_print(SM);
break;
case BREAK:
case CONTINUE:
puttok(base);
puttok(SM);
break;
case DEFAULT:
puttok(base);
putch(':');
s->print();
break;
case SM: {
Pexpr ee = e;
while (ee && (ee->base == CAST || ee->base == G_CAST))
ee = ee->e1;
if (ee && ee->base == ILIST) {
puttok(SM);
break;
}
if (e) {
DB(if(Pdebug>=4)display_expr(e,"SM_e"););
e->print();
if (e->base==ICALL && e->e2) break; /* a block: no SM */
}
puttok(SM);
break;
}
case WHILE:
puttok(WHILE);
putcond(e);
if (s->s_list) {
puttok(LC);
s->print();
puttok(RC);
}
else
s->print();
break;
case DO:
puttok(DO);
s->print();
puttok(WHILE);
putcond(e);
puttok(SM);
break;
case SWITCH:
puttok(SWITCH);
putcond(e);
s->print();
break;
case RETURN:
if (gt) {
gt->print();
break;
}
puttok(RETURN);
if (e) {
//error('d',"print return rt %t etp %t",ret_tp,e->tp);
if (ret_tp && ret_tp!=e->tp) {
Ptype tt = ret_tp->skiptypedefs();
switch (tt->base) {
case COBJ:
break; // cannot cast to struct
case RPTR:
case PTR:
if (Pptr(tt)->typ==Pptr(e->tp)->typ)
break;
if (Pptr(tt)->memof)
break;
default:
if (e->tp==0 || ret_tp->check(e->tp,0)) {
int oc = Cast;
putch('(');
Cast = 1;
ret_tp->print();
Cast = oc;
putch(')');
}
}
}
eprint(e);
}
puttok(SM);
while (s_list && s_list->base==SM)
s_list = s_list->s_list; // FUDGE!!
break;
case CASE:
puttok(CASE);
eprint(e);
putch(':');
s->print();
break;
case GOTO:
puttok(GOTO);
if (curr_lab)
printf("_%ld__", curr_lab);
d->print();
puttok(SM);
break;
case LABEL:
if (curr_lab)
printf("_%ld__", curr_lab);
d->print();
putch(':');
s->print();
break;
case IF:
{ int val = QUEST;
if (e->base == ANAME) {
Pname a = Pname(e);
Pexpr arg = aval(a);
//error('d',"arg %d%k %d (%d)",arg,arg?arg->base:0,arg?arg->base:0,arg?arg->e1:0);
if (arg)
switch (arg->base) {
case ZERO: val = 0; break;
case ADDROF:
case G_ADDROF: val = 1; break;
case IVAL: val = arg->i1!=0;
}
}
//error('d',"val %d",val);
switch (val) {
case 1:
s->print();
break;
case 0:
if (else_stmt)
else_stmt->print();
else
puttok(SM); /* null statement */
break;
default:
puttok(IF);
putcond(e);
if (s->s_list) {
puttok(LC);
s->print();
puttok(RC);
}
else
s->print();
if (else_stmt) {
puttok(ELSE);
if (else_stmt->where.line == 0) {
if (csloc.line)
csloc.putline();
}
else {
csloc = else_stmt->where;
if (else_stmt->where.line!=last_line.line)
if (last_ll = else_stmt->where.line)
else_stmt->where.putline();
else
last_line.putline();
}
if (else_stmt->s_list) {
puttok(LC);
else_stmt->print();
puttok(RC);
}
else
else_stmt->print();
}
}
break;
}
case FOR:
{
int fi = 0; // is the initializer statement an expression?
if (for_init) {
fi = 1;
if (for_init->memtbl==0 && for_init->s_list==0)
if (for_init->base==SM)
if (for_init->e->base!=ICALL || for_init->e->e1)
fi = 0;
}
//error('d',"for(; %d%k; %d%k)",e,e->base,e2,e2->base);
if (fi) {
puttok(LC);
for_init->print();
}
putstring("for(");
if (fi==0 && for_init)
for_init->e->print();
putch(';'); // to avoid newline: not puttok(SM)
if (e)
e->print();
putch(';');
if (e2)
e2->print();
puttok(RP);
s->print();
if (fi)
puttok(RC);
break;
}
case PAIR:
if (s&&s2) {
puttok(LC);
s->print();
s2->print();
puttok(RC);
}
else {
if (s)
s->print();
if (s2)
s2->print();
}
break;
case BLOCK:
puttok(LC);
//error('d',"block %d d %d memtbl %d own_tbl %d",this,d,memtbl,own_tbl);
if (d)
d->dcl_print(SM);
if (memtbl && own_tbl) {
Pname n;
int i;
Plist aglist=0;
for (n=memtbl->get_mem(i=1); n; NEXT_NAME(memtbl,n,i)) {
DB(if(Pdebug>=1)error('d',&n->where,"print local%n base%k tp%t scope%k",n,n->base,n->tp,n->n_scope));
if (
n->tp
&&
n->n_anon==0
&&
n->tp!=any_type
)
switch (n->n_scope) {
case ARGT:
case ARG:
break;
default:
// error('d', "n: %s %k n_key: %k", n->string, n->base, n->n_key);
if ( n->base == TNAME
&& n->tpdef
&& n->tpdef->nested_sig
)
continue; // printed from nested class
if (ansi_opt==0 || !n->n_initializer)
n->dcl_print(0);
else
aglist=new name_list(n,aglist);
}
}
if (aglist)
reprint(aglist);
if (
last_ll==0
&&
s
&&
(last_ll=s->where.line)
)
s->where.putline();
}
if (s)
s->print();
if (where2.line == 0) {
if (csloc.line)
csloc.putline();
}
else {
csloc = where2;
if (where2.line!=last_line.line)
if (last_ll = where2.line)
where2.putline();
else
last_line.putline();
}
putstring("}\n");
if (last_ll && where.line)
last_line.line++;
}
if (s_list)
s_list->print();
}
struct ptbl_rec {
char* pname;
char* vname;
ptbl_rec* next;
};
static char* ptbl_name;
static ptbl_rec* ptbl_rec_lookup_head = 0;
static ptbl_rec* ptbl_rec_pair_head = 0;
void ptbl_init(int flag)
{
if (!flag) {
char *p = st_name( "__ptbl_vec__" );
ptbl_name = new char[strlen(p)+1];
strcpy(ptbl_name, p);
delete p;
Loc old = curloc;
curloc.file = 0;
curloc.line = 1;
curloc.putline();
curloc = old;
fprintf(out_file, "extern struct __mptr* %s[];\n", ptbl_name);
if (last_ll)
last_line.line++;
}
else {
ptbl_rec *r, *p = ptbl_rec_lookup_head;
if ( p == 0 )
return; // don't generate an empty object
fprintf(out_file, "struct __mptr* %s[] = {\n", ptbl_name);
if (last_ll)
last_line.line++;
while (p != 0) {
r = ptbl_rec_pair_head;
while (r && strcmp(r->pname, p->pname))
r = r->next;
fprintf(out_file, "%s,\n", r->vname);
if (last_ll)
last_line.line++;
p = p->next;
}
fprintf(out_file, "\n};\n");
if (last_ll)
last_line.line += 2;
}
}
char* ptbl_lookup(char *name)
{
ptbl_rec *r, *s, *p = ptbl_rec_lookup_head;
int i = 0;
while (p && strcmp(name, p->pname)) {
r = p;
p = p->next;
i++;
}
if (p == 0) {
s = new ptbl_rec;
s->pname = new char[strlen(name) + 1];
s->vname = 0;
s->next = 0;
strcpy(s->pname, name);
if (ptbl_rec_lookup_head == 0)
ptbl_rec_lookup_head = s;
else
r->next = s;
}
char *pp = new char[ strlen(ptbl_name) + 10 ];
sprintf(pp, "%s[%d]", ptbl_name, i);
return(pp);
}
void ptbl_add_pair(char* ptbl, char* vtbl)
{
// error('d', "ptbl_add_pair: ptbl: %s, vtbl: %s", ptbl, vtbl );
ptbl_rec *p = new ptbl_rec;
p->pname = new char[strlen(ptbl) + 1];
strcpy(p->pname, ptbl);
p->vname = new char[strlen(vtbl) + 1];
strcpy(p->vname, vtbl);
p->next = ptbl_rec_pair_head;
ptbl_rec_pair_head = p;
}