double BasisAngle( const Epetra_MultiVector& S, const Epetra_MultiVector& T )
{
    //
    //  Computes the largest acute angle between the two orthogonal basis
    //
    if (S.NumVectors() != T.NumVectors()) {
        return acos( 0.0 );
    } else {
        int lwork, info = 0;
        int m = S.NumVectors(), n = T.NumVectors();
        int num_vecs = ( m < n ? m : n );
        double U[ 1 ], Vt[ 1 ];
        lwork = 3*m*n;
        std::vector<double> work( lwork );
        std::vector<double> theta( num_vecs );
        Epetra_LAPACK lapack;
        Epetra_LocalMap localMap( S.NumVectors(), 0, S.Map().Comm() );
        Epetra_MultiVector Pvec( localMap, T.NumVectors() );
        info = Pvec.Multiply( 'T', 'N', 1.0, S, T, 0.0 );
        //
        // Perform SVD on S^T*T
        //
        lapack.GESVD( 'N', 'N', num_vecs, num_vecs, Pvec.Values(), Pvec.Stride(),
                      &theta[0], U, 1, Vt, 1, &work[0], &lwork, &info );
        assert( info == 0 );
        return (acos( theta[num_vecs-1] ) );
    }
    //
    // Default return statement, should never be executed.
    //
    return acos( 0.0 );
}
    void processConstraints()
    {
	  LVec v=f.evaluate();
      mask.zero();
      Pvec.zero();
      for(unsigned i=0; i<L; i++)
        if(v(i)>0) //THIS EQUAL SIGN IS EVIL DO NOT TOUCH
        {
          mask(i)=1;
          Pvec(i)=this->t;

        }
      AtP=(f.getA().column_mult(Pvec)).transp();
    }
    void replaceConstraint(unsigned i, T t)
    {
	  //LVec v=f.evaluate();
      //mask.zero();
      //P.zero();
      //for(unsigned i=0; i<L; i++)
        //if(v(i)>1e-4) //THIS EQUAL SIGN IS EVIL DO NOT TOUCH
        {
          mask(i)=1;
          Pvec(i)=t;

        }
      AtP=(f.getA().column_mult(Pvec)).transp();
    }
Esempio n. 4
0
Ptype fct.normalize(Ptype ret)
/*
	normalize return type
*/
{
	register Ptype t = returns;

	if (this==0 || ret==0) error('i',"%d->fct.normalize(%d)",this,ret);

	returns = ret;
	if (t == 0) return this;

	if (argtype) {
		if (argtype->base != NAME) {
			error('i',"syntax: ANX");
			argtype = 0;
			nargs = 0;
			nargs_known = 0;
		}
/*
		else {
			Pname n;
			for (n=argtype; n; n=n->n_list) {
				if (n->string) {
					error("N inATL");
					n->string = 0;
				}
			}
		}
*/
		
	}

xx:
	switch (t->base) {
	case PTR:
	case RPTR:	return Pptr(t)->normalize(this);
	case VEC:	return Pvec(t)->normalize(this);
	case FCT:	return Pfct(t)->normalize(this);
	case TYPE:	t = Pbase(t)->b_name->tp;	goto xx;
	default:	error('i',"badFT:%k",t->base);
	}

}
Esempio n. 5
0
Ptype vec.normalize(Ptype vecof)
/*
*/
{
	Ptype t = typ;
	if (this == 0) error('i',"0->vec.normalize()");
	typ = vecof;

	if (t == 0) return this;

xx:
	switch (t->base) {
	case TYPE:	t = Pbase(t)->b_name->tp;	goto xx;
	case PTR:
	case RPTR:	return Pptr(t)->normalize(this);
	case VEC:	return Pvec(t)->normalize(this);
	case FCT:	return Pfct(t)->normalize(this);
	default:	error('i',"bad vectorT(%d)",t->base);
	}
}
Esempio n. 6
0
Ptype ptr.normalize(Ptype ptrto)
{
	Ptype t = typ;
	if (this == 0) error('i',"0->ptr.normalize()");
	typ = ptrto;

	if (t == 0) {
		Pbase b = (Pbase) ptrto;
		if (Pfctvec_type
		&& rdo==0
		&& b->b_unsigned==0
		&& b->b_const==0
		&& base==PTR) {
			switch (b->base) {
			case INT:
				delete this;
				return Pint_type;
			case CHAR:
				delete this;
				return Pchar_type;
			case VOID:
				delete this;
				return Pvoid_type;
			case TYPE:
				break;
			}
		}
		if (base==RPTR && b->base==VOID) error("void& is not a validT");
		return this;
	}

xx:
	switch (t->base) {
	case TYPE:	t = Pbase(t)->b_name->tp; goto xx;
	case PTR:
	case RPTR:	return Pptr(t)->normalize(this);
	case VEC:	return Pvec(t)->normalize(this);
	case FCT:	return Pfct(t)->normalize(this);
	default:	error('i',"badPT(%d)",t->base);
	}
}
Esempio n. 7
0
Pname type.is_cl_obj()
/*
	returns this->b_name if this is a class object
	returns 0 and sets cl_obj_vec to this->b_name
		if this is a vector of class objects
	returns 0 and sets eobj to this->b_name
		if this is an enum object
	else returns 0
*/
{
	bit v = 0;
	register Ptype t = this;

	eobj = 0;
	cl_obj_vec = 0;
xx:
	switch (t->base) {
	case TYPE:
		t = Pbase(t)->b_name->tp;
		goto xx;

	case COBJ:
		if (v) {
			cl_obj_vec = Pbase(t)->b_name;
			return 0;
		}
		else
			return Pbase(t)->b_name;

	case VEC:
		t = Pvec(t)->typ;
		v=1;
		goto xx;

	case EOBJ:
		eobj = Pbase(t)->b_name;
	default:	
		return 0;
	}
}
Esempio n. 8
0
void list_check(Pname nn, Ptype t, Pexpr il)
/*
	see if the list "lll" can be assigned to something of type "t"
	"nn" is the name of the variable for which the assignment is taking place.
	"il" is the last list element returned by next_elem()
*/
{
	Pexpr e;
	bit lst = 0;
	int i;
	Pclass cl;
//error('d',"list_check%n: %t (%d)",nn,t,il);
	switch ( (int)il ) {
	case 0:		break;
	case 1:		lst = 1; break;
	default:	list_put_back(il);
	}

zzz:
	switch (t->base) {
	case TYPE:
		t = Pbase(t)->b_name->tp;
		goto zzz;

	case VEC:
	{	Pvec v = (Pvec)t;
		Ptype vt = v->typ;

		if (v->size) {	/* get at most v->size initializers */
			if (v->typ->base == CHAR) {
				e = next_elem();
				if (e->base == STRING) {	// v[size] = "..."
					int isz = Pvec(e->tp)->size;
					if (v->size < isz) error("Ir too long (%d characters) for%n[%d]",isz,nn,v->size);
					break;
				}
				else
					list_put_back(e);
			}
			for (i=0; i<v->size; i++) { // check next list element type
			ee:
				e = next_elem();
				if (e == 0) goto xsw; // too few initializers are ok
			vtz:
//error('d',"vtz: %d",vt->base);
				switch (vt->base) {
				case TYPE:
					vt = Pbase(vt)->b_name->tp;
					goto vtz;
				case VEC:
				case COBJ:
					list_check(nn,vt,e);
					break;
				default:
					if (e == (Pexpr)1) {
						error("unXIrL");
						goto ee;
					}
					if (vt->check(e->tp,ASSIGN))
						error("badIrT for%n:%t (%tX)",nn,e->tp,vt);
				}
			}
			if ( lst && (e=next_elem()) ) error("end ofIrLX after vector");
		xsw:;
		}
		else {		/* determine v->size */
			i = 0;
		xx:
			while ( e=next_elem() ) {	// get another initializer
				i++;
			vtzz:
//error('d',"vtzz: %d",vt->base);
				switch (vt->base) {
				case TYPE:
					vt = Pbase(vt)->b_name->tp;
					goto vtzz;
				case VEC:
				case COBJ:
					list_check(nn,vt,e);
					break;
				default:
					if (e == (Pexpr)1) {
						error("unXIrL");
						goto xx;
					}
					if (vt->check(e->tp,ASSIGN))
						error("badIrT for%n:%t (%tX)",nn,e->tp,vt);
				}
			}
			v->size = i;
		}
		break;
	}

	case CLASS:
		cl = (Pclass)t;
		goto ccc;

	case COBJ:	/* initialize members */
		cl = Pclass(Pbase(t)->b_name->tp);
	ccc:
	{	Ptable tbl = cl->memtbl;
		Pname m;

		if (cl->clbase) list_check(nn,cl->clbase->tp,0);

		for (m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i)) {
			Ptype mt = m->tp;
			switch (mt->base) {
			case FCT:
			case OVERLOAD:
			case CLASS:
			case ENUM:
				continue;
			}
			if (m->n_stclass == STATIC) continue;
			/* check assignment to next member */
		dd:
			e = next_elem();
			if (e == 0) return; //break;
		mtz:
//error('d',"mtz%n: %d",m,mt->base);
			switch (mt->base) {
			case TYPE:
				mt = Pbase(mt)->b_name->tp;
				goto mtz;
			case CLASS:
			case ENUM:
				break;
			case VEC:
			case COBJ:
				list_check(nn,m->tp,e);
				break;
			default:
				if (e == (Pexpr)1) {
					error("unXIrL");
					goto dd;
				}
				if (mt->check(e->tp,ASSIGN))
					error("badIrT for%n:%t (%tX)",m,e->tp,m->tp);
			}
		}
		if (lst && (e=next_elem()) ) error("end ofIrLX afterCO");
		break;
	}
	default:
		e = next_elem();

		if (e == 0) {
			error("noIr forO");
			break;
		}
		
		if (e == (Pexpr)1) {
			error("unXIrL");
			break;
		}
		if (t->check(e->tp,ASSIGN)) error("badIrT for%n:%t (%tX)",nn,e->tp,t);
		if (lst && (e=next_elem()) ) error("end ofIrLX afterO");
		break;
	}
}
Esempio n. 9
0
bit type::check(Ptype t, TOK oper, bit level)
/*
	check if "this" can be combined with "t" by the operator "oper"

	used for check of
			assignment types		(oper==ASSIGN)
			declaration compatability	(oper==0)
			decl. compatibility without "const"ness (oper=254) 
						(oper == IGNORE_CONST)
			parameterized type formals	(oper==255)
			  as for (oper==0) but
			  special checking for ANY types
			argument types			(oper==ARG)
			return types			(oper==RETURN)
			overloaded function name match	(oper==OVERLOAD)
			overloaded function coercion	(oper==COERCE)
			virtual function match		(oper==VIRTUAL)

	NOT for arithmetic operators

	return 1 if the check failed
*/
{

	register Ptype t1 = this, t2 = t;
	bit cnst1 = 0, cnst2 = 0;
	TOK b1, b2;
	bit vv=0, over=0, strict_any_check = 0;
	TOK rec_oper;		// value of oper for recursive calls to type::check
				//	oper, 255, or PT_OVERLOAD
	TOK rec_oper0;		// value of oper for recursive calls to type::check
				//	0, 255, or PT_OVERLOAD

	if (t1==0 || t2==0)
		error('i',"check(%p,%p,%d)",t1,t2,oper);

	if(t1==t2)
		return 0;

	switch(oper) {
	case VIRTUAL:
		vv = 1;
		Vcheckerror = 0;
		oper = 0;
		break;
	case OVERLOAD:
		over = 1;
		oper = 0;
		break;
	case PT_OVERLOAD:
		over = 1;
		// no break
	case 255:
		oper = 0;
		strict_any_check=1;
		break;
	}

	if(level==0) {
		const_problem = 0;
		return_error = 0;
		pt_ptm = 0;
		pt_over = over;
	}

	rec_oper = strict_any_check ? ( over ? PT_OVERLOAD : 255 ) : oper;
	rec_oper0 = strict_any_check ? ( over ? PT_OVERLOAD : 255 ) : 0;

	t1 = t1->skiptypedefs(cnst1);

/*
**	GLOG: the following test on ANY must be done before unrolling
**	t2, to accommodate templates (in a way I don't yet understand)
*/
	if (t1->base == ANY || t2->base == ANY)
		if (over==0 || strict_any_check==0) 
			return strict_any_check ? t1!=t2 : 0;

	t2 = t2->skiptypedefs(cnst2);

	if(t1==t2)
		goto const_check;

	b1 = t1->base;
	b2 = t2->base;

	if (b1 != b2) {
		switch (b1) {
		case PTR:
			switch (b2) {
			case VEC:
				if (
					level>0
					||
					(oper == 0 || oper == IGNORE_CONST)  
					&&
					over==0
					||
					Pptr(t1)->memof
					||
					Pptr(t1)->ptname
					||
					Pptr(t1)->typ->check(Pvec(t2)->typ,rec_oper,level+1)
				)
					return 1;

				goto const_check;

			case FCT:
				if (
					level>0
					||
					Pptr(t1)->typ->check(t2,rec_oper,level+1)
				)
					return 1;
				goto const_check;
			}
			break;

		case FCT:
			if( b2==PTR ) {
				if (
					level>0
					||
					t1->check(Pptr(t2)->typ,rec_oper,level+1)
				)
					return 1;
				goto const_check;
			}
			break;

		case VEC:
			if (b2==PTR) {
				if (
					level>0
					||
					(oper==0 || oper == IGNORE_CONST)  
					&&
					over==0
					||
					Pptr(t2)->memof
					||
					Pptr(t2)->ptname
					||
					Pvec(t1)->typ->check(Pptr(t2)->typ,rec_oper,level+1)
				)
					return 1;

				goto const_check;
			}
			break;
		}

		if(level>0) {
			if((oper != 0 && oper != IGNORE_CONST) && b1==VOID && level==1) {
				if(b2==FCT) {
					Pfct f = Pfct(t2);
					if(f->memof && f->f_static==0)
						return 1;
				}
				goto const_check;
			}
			return 1;
		}

		switch (oper) {
		case 0:
		case IGNORE_CONST:	
			if (
				b2 == ZTYPE && b1==INT && Pbase(t1)->b_unsigned==0
				||
				b1 == ZTYPE && b2==INT && Pbase(t2)->b_unsigned==0
			)
				goto const_check;
			return 1;
		case ARG:
		case ASSIGN:
		case RETURN:
		case COERCE:
			switch (b1) {
			case ZTYPE:
			case CHAR:
			case SHORT:
			case INT:
			case LONG:
			case LLONG:
			case FLOAT:
			case DOUBLE:
			case LDOUBLE:
			case FIELD:
				switch (b2) {
				case LONG:
				case LLONG:
				case FLOAT:
				case DOUBLE:
				case LDOUBLE:
				case EOBJ:
				case ZTYPE:
				case CHAR:
				case SHORT:
				case INT:
				case FIELD:
					if(oper==COERCE)
						Nstd++;
					goto const_check;
				}
				return 1;
			case PTR:
			case VEC:
				if (b2==ZTYPE) {
					if(oper==COERCE)
						Nstd++;
					goto const_check;
				}
			case RPTR:
			case COBJ:
			case FCT:
			case EOBJ:
			default:
				return 1;
			}
		}
		goto const_check;
	}

	switch (b1) {
	case VEC:
		if (
			Pvec(t1)->size!=Pvec(t2)->size
			&&
			(
			level>0
			||
			(oper==0 || oper==IGNORE_CONST)	
			&&
			strict_any_check==0
			&&
			Pvec(t1)->size
			&&
			Pvec(t2)->size
			)
		)
			return 1;

		if(Pvec(t1)->typ->check(Pvec(t2)->typ,rec_oper,level+1))
			return 1;
		break;

	case PTR:
	case RPTR:
	{
		Pptr p1 = Pptr(t1);
		Pptr p2 = Pptr(t2);

		if ((p1->ptname && p2->ptname) && (!p1->memof || !p2->memof))
			return 1;

		if (!same_class(p1->memof,p2->memof)) {
			
			// T::* requires we defer setting up memof
			// until instantiation of the Template type T
			// ptname holds the formal parameter T
			// can't merge with other if because of memof usage
			if(
				p1->memof==0 && p1->ptname
				||
				p2->memof==0 && p2->ptname
			)
			 	pt_ptm = 1; 
			else	
			if(
				p1->memof==0 
				||
				p2->memof==0
				||
				(p1->memof->baseof(p2->memof)==0 &&
				 same_class(p1->memof,p2->memof,1)==0)
			)
				return 1;

			if (pt_ptm == 0 && (oper==0 || oper==IGNORE_CONST) && 
			    same_class(p1->memof,p2->memof)==0)
				return 1;

			if(oper==COERCE)
				Nstd++;
		}

#if 0
		if (!level && (oper == 0 || oper == ASSIGN || oper == COERCE ||
		    oper == ARG || oper == RETURN)) {
			Ptype t11;
			Ptype t22;
			Ptype ta;
			Ptype tb;
			int i = 0;
			int j = 0;
			int k = 0;
			ta = t1;
			while ((ta->base == PTR || ta->base == RPTR) &&
			    (tb = ta->is_ptr_or_ref())) {
				ta = Pptr(tb)->typ;
				i++;
				k += ta->tconst();
			}
			t11 = ta;
			ta = t2;
			while ((ta->base == PTR || ta->base == RPTR) &&
			    (tb = ta->is_ptr_or_ref())) {
				ta = Pptr(tb)->typ;
				j++;
			}
			t22 = ta;
			if (i >= 2 && j == i && t11->tconst() &&
			    !t22->tconst() && k != i)
				return const_problem = 1;
		}
#endif

		if(p1->typ->check(p2->typ,rec_oper,level+1))
			return 1;

		break;
	}

	case FCT:
	{
		Pfct f1 = Pfct(t1);
		Pfct f2 = Pfct(t2);
		Pname a1 = f1->argtype;
		Pname a2 = f2->argtype;
		TOK k1 = f1->nargs_known;
		TOK k2 = f2->nargs_known;
		int n1 = f1->nargs;
		int n2 = f2->nargs;
		// if pt_ptm, want to check arguments and return type
		// but template ptm has no memof until instantiation
		if (!same_class(f1->memof,f2->memof) && pt_ptm == 0) {
			if (f1->memof==0 && f2->f_static)
				goto sss;
			if (vv == 0)	// match even if private base class
				if (
					f1->memof==0
					||
					f2->memof==0
					||
					(
					    level > 1
					    ||
					    f1->memof->baseof(f2->memof)==0
					)
					&&
					same_class(f1->memof,f2->memof)==0
				)
					return 1;
			if(oper==COERCE)
				Nstd++;
			sss:;	//SSS
		}

		if (k1 != k2)
			return 1;

		if (n1!=n2 && k1 && k2) {
			goto aaa;
		}
		else if (a1 && a2) {
			while (a1 && a2) {
				if (a1->tp->check(a2->tp,rec_oper0,level+1))
					return 1;
				a1 = a1->n_list;
				a2 = a2->n_list;
			}
			if (a1 || a2)
				goto aaa;
		}
		else if (a1 || a2) {
		aaa:
			if (k1 == ELLIPSIS) {
				switch (oper) {
				case 0:
				case IGNORE_CONST:	
					if (a2 && k2==0)
						break;
					return 1;
				case ASSIGN:
					if (a2 && k2==0)
						break;
					return 1;
				case ARG:
					if (a1)
						return 1;
					break;
				case COERCE:
					return 1;
				}
			}
			else if (k2 == ELLIPSIS) {
				return 1;
			}
			else if (k1 || k2) {
				return 1;
			}
		}

		cnst1 = f2->f_const;
		cnst2 = f1->f_const;

		if(f1->returns->check(f2->returns,rec_oper0,level+1)) {
			if(vv && cnst1==cnst2) {
				bit fail = 1;
				Ptype t1 = f1->returns;
				Ptype t2 = f2->returns;
				if ((t1->is_ptr() && t2->is_ptr()) ||
				    (t1->is_ref() && t2->is_ref())) {
					t1 = Pptr(t1->is_ptr_or_ref())->typ;
					t2 = Pptr(t2->is_ptr_or_ref())->typ;
					if (!t1->is_ptr_or_ref() &&
					    !t2->is_ptr_or_ref()) {
						t1 = t1->skiptypedefs();
						t2 = t2->skiptypedefs();
						if (t1->base == COBJ &&
						    t2->base == COBJ) {
							Pclass c1 = t1->classtype();
							Pclass c2 = t2->classtype();
							Nvis = 0;
							if (c2->has_base(c1,0,1) && !Nvis)
								fail = 0;
						}
					}
				}
				if (fail)
					Vcheckerror = 1;
				else
					break;
			}
			if (rec_oper0 == PT_OVERLOAD && level == 0)
				return_error = 1;
			return 1;
		}

		break;
	}

	case FIELD:
		switch (oper) {
		case 0:
		case IGNORE_CONST:	
		case ARG:
			error('i',"check field?");
		}
		return 0;

	case FLOAT:
	case DOUBLE:
	case LDOUBLE:
	case CHAR:
	case SHORT:
	case INT:
	case LONG:
	case LLONG:
		if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) {
			if (level>0 || (oper==0 || oper==IGNORE_CONST))
				return 1;
			if (oper==COERCE)
				Nstd++;
		}
		goto const_check;

	case EOBJ:
		if (Pbase(t1)->b_name->tp != Pbase(t2)->b_name->tp)
			return 1;
		goto const_check;

	case CLASS:
	case COBJ:
	{
		Pname n1, n2;
		if (b1 == COBJ) {
			n1 = Pbase(t1)->b_name;
			n2 = Pbase(t2)->b_name;
			if (n1 == n2)
				goto const_check;
		}

		// once again, a more comprehensive check for classes,
		// since they may be parameterized.
		// same_class: handles class templates: instantiated
		// fm_same_class: handles matching uninstantiated templates
		// 	used as formal arguments for template functions

		// hack: see comment on classdef::same_class in template.c
		extern int is_arg;
		int access = template_hier || pt_over;
		if (
			same_class(Pclass(b1==COBJ?n1->tp:t1),Pclass(b1==COBJ?n2->tp:t2),access||is_arg)
			||
			rec_oper==PT_OVERLOAD
			&&
			fm_same_class(Pclass(b1==COBJ?n1->tp:t1),Pclass(b1==COBJ?n2->tp:t2))
		)
			goto const_check;

		// permit a derived class to match public base class
		if (template_hier != 0)
			goto pt_hack;

		switch (oper) {
		case ARG:
		case ASSIGN:
		case RETURN:
		case COERCE:
		{
		pt_hack:
			ppbase = PUBLIC;
			if (level<=1 && ((Pclass(b1==COBJ?n2->tp:t2))->is_base(b1==COBJ?n1->string:Pclass(t1)->string))) {
				if (ppbase!=PUBLIC) {
					const_problem = 0;
					return 1;	// private or protected base
				}
				if(oper==COERCE)
					Nstd++;
				goto const_check;
			}
		}
			// no break
		case 0:
		case IGNORE_CONST:	
			const_problem = 0;
			return 1;
		}

		goto const_check;
	}

	case ZTYPE:
	case VOID:
		goto const_check;
	default:
		error('i',"T::check(o=%d %d %d)",oper,b1,b2);
	}

const_check:


	if(cnst1==cnst2)
		return 0;

	switch(oper) {
	case IGNORE_CONST:	
		return 0;//ignore "const"ness for oper=IGNORE_CONST

	case 0:
		const_problem=1;
		return 1;

	case ASSIGN:
	case COERCE:
	case ARG:
	case RETURN:
		if(level>0) {
			if(cnst2)
				const_problem=1;
			return cnst2;
		}
		return 0;
	default:
		error('i',"oper = %k in type::check()",oper);
	}
	return 0;
}
Esempio n. 10
0
void type::dcl(Ptable tbl)
/*
	go through the type (list) and
	(1) evaluate vector dimensions
	(2) evaluate field sizes
	(3) lookup struct tags, etc.
	(4) handle implicit tag declarations
*/
{
	Ptype t = this;

	// processing_sizeof suppresses errors for refs to names in the arg 
	// to sizeof.  Turn errors back on for exprs within type specs
	// (such as array subscripts)
	int os = processing_sizeof;
	processing_sizeof = 0;

	if (this == 0)
		error('i',"T::dcl(this==0)");
	if (tbl->base != TABLE)
		error('i',"T::dcl(%d)",tbl->base);

xx:
	switch (t->base) {
	case TYPE:
		t = Pbase(t)->b_name->tp;
		goto xx;
	case PTR:
	case RPTR:
	{
		Pptr p = Pptr(t);
		if(p->memof == 0 && p->ptname) { // T::*, where T is a template formal
			Ptype tp = p->ptname->tp->skiptypedefs();
			switch (tp->base) {
			    case COBJ:
				{
				p->memof = tp->classtype();
				if (p->typ)
				{
					Ptype t = p->typ->skiptypedefs();
					if (t && t->base==FCT)
					{
						Pfct(t)->memof = p->memof;
					}
				}
				break;
				}
			    case CLASS:
				{
				p->memof = Pclass(tp);
				Ptype t = p->typ->skiptypedefs();
				Pfct f = Pfct(t); // safe???
				f->memof = p->memof;
				break;
				}	
			    default:
				error("illegalZizedP toM %t::*",tp);
				break;
			}
		}
		t = p->typ;
		if (t->base == TYPE) {
			Ptype tt = Pbase(t)->b_name->tp;
			if (tt->base == FCT)
				p->typ = tt;
			goto done;
		}
		goto xx;
	}

	case VEC:
	{
		Pvec v = Pvec(t);
		Pexpr e = v->dim;
		if (e) {
			Ptype et;
			v->dim = e = e->typ(tbl);
			if (e->tp->skiptypedefs()->base == COBJ) {
				e = check_cond(e,DEREF,tbl);
				v->dim = e;
			}
			et = e->tp;
			if (et->integral(0) == 'A') {
				error("UN in array dimension");
			}
			else {
				long long i;
				Neval = 0;
				i = e->eval();
				if (Neval == 0) {
					if (largest_int<i)
						error("array dimension too large");
					v->size = int(i);

					DEL(v->dim);
					v->dim = 0;
				}

				if (new_type) {
					if (Neval)
						;
					else if (i == 0)
						v->dim = zero;
					else if (i < 0) {
						error("negative array dimension");
						i = 1;
					}
				}
				else {
					if (Neval)
						error("%s",Neval);
					else if (i == 0) {
						error("array dimension == 0");
						v->dim=e;
					}
					else if (i < 0) {
						error("negative array dimension");
						i = 1;
					}
				}
			}
		}
		t = v->typ;
	llx:
		switch (t->base) {
		case TYPE:
			t = Pbase(t)->b_name->tp;
			goto llx;
		case FCT:
			v->typ = t;
			break;
		case VEC:				
			if (Pvec(t)->dim==0 && Pvec(t)->size==0)
				error("null dimension (something like [][] seen)");
		}
		goto xx;
	}

	case FCT:
	{
		Pfct f = Pfct(t);
		void dargs(Pname, Pfct, Ptable);

		if (f->argtype)
			dargs(0,f,tbl);
		for (Pname n=f->argtype; n; n = n->n_list) {
			Ptype t = n->tp;
			n->tp->dcl(tbl);
			while(t->base==TYPE)
				t = Pbase(t)->b_name->tp;
			if(t->base==VEC)
				n->tp = new ptr(PTR,Pvec(t)->typ);
		}
		Pname cn = f->returns->is_cl_obj();
		if (cn && Pclass(cn->tp)->has_itor())
			make_res(f);
		else if (f->f_this == 0)
			f->f_args = f->argtype;

		t = f->returns;
		goto xx;
	}

	case FIELD:
	{
		Pbase f = Pbase(t);
		Pexpr e = Pexpr(f->b_name);
		long long i;
		Ptype et;
		e = e->typ(tbl);
		f->b_name = Pname(e);
		et = e->tp;
		if (et->integral(0) == 'A') {
			error("UN in field size");
			i = 1;
		}
		else {
			Neval = 0;
			i = e->eval();
			if (Neval)
				error("%s",Neval);
			else if (i < 0) {
				error("negative field size");
				i = 1;
			}
			else if (f->b_fieldtype->tsizeof()*BI_IN_BYTE < i)
				error("field size > sizeof(%t)",f->b_fieldtype);
			DEL(e);
		}
		f->b_bits = int(i);
		f->b_name = 0;
		break;
	}
	}
done:
	processing_sizeof = os;
	return;
}
Esempio n. 11
0
Pname name.normalize(Pbase b, Pblock bl, bit cast)
/*
	if (bl) : a function definition (check that it really is a type

	if (cast) : no name string

	for each name on the name list
	invert the declarator list(s) and attatch basetype
	watch out for class object initializers

	convert
		struct s { int a; } a;
	into
		struct s { int a; }; struct s a;
*/
{
	Pname n;
	Pname nn;
	TOK stc = b->b_sto;
	bit tpdf = b->b_typedef;
	bit inli = b->b_inline;
	bit virt = b->b_virtual;
	Pfct f;
	Pname nx;

	if (b == 0) error('i',"%d->N.normalize(0)",this);
	if (this == 0) error('i',"0->N.normalize(%k)",base);

	if (inli && stc==EXTERN)  {
		error("both extern and inline");
		inli = 0;
	}
//fprintf(stderr,"name.norm(%d %s) tp (%d %d)\n",this,string,tp,tp->base);

	if (stc==FRIEND && tp==0) {
			/*	friend x;
				must be handled during syntax analysis to cope with
					class x { friend y; y* p; };
				"y" is not local to "x":
					class x { friend y; ... }; y* p;
				is legal
			*/
		if (b->base) error(0,"T specified for friend");
		if (n_list) {
			error("L of friends");
			n_list = 0;
		}
		Pname nx = tname(CLASS);
		modified_tn = modified_tn->l;	/* global */
		n_sto = FRIEND;
		tp = nx->tp;
		return this;
	}

	if (tp
	&& n_oper==TNAME
	&& tp->base==FCT) {	/* HORRIBLE FUDGE: fix the bad grammar */
		Pfct f = (Pfct)tp;
		Pfct f2 = (Pfct)f->returns;
		if (f2 && f2->base==FCT) {
			Pexpr e = f2->argtype;
//error('d',"%s: mis-analyzedP toF",string);
			if  (e->base == ELIST) {
				//	get the real name, fix its type
				if (e->e2 || e->e1->base!=DEREF) goto zse1;
				Pname rn = (Pname)e->e1->e1;
				if (rn->base!=NAME) goto zse1;
				f->returns = new ptr(PTR,0);
				b = new basetype(TYPE,ktbl->look(string,0));
				n_oper = 0;
				string = rn->string;
				base = NAME;
//error('d',"realN %n b==%t",rn,b);
			}
		}
	}
zse1:
	if (cast) string = "";
	b = b->check(this);

	switch (b->base) {	//	separate class definitions
				//	from object and function type declarations
	case COBJ:
		nn = b->b_name;
//fprintf(stderr,"COBJ (%d %s) -> (%d %d body=%d)\n",nn,nn->string,nn->tp,nn->tp->base,Pclass(nn->tp)->c_body);
		if (Pclass(nn->tp)->c_body==2) {	/* first occurrence */
			if (tp && tp->base==FCT) {
				error('s',&this->where,"%k%n defined as returnT for%n (did you forget a ';' after '}' ?)",Pclass(nn->tp)->csu,nn,this);
				nn = this;
				break;
			}
			nn->n_list = this;
			Pclass(nn->tp)->c_body = 1;	/* other occurences */
		}
		else
			nn = this;
		break;
	case EOBJ:
		nn = b->b_name;
		if (Penum(nn->tp)->e_body==2) {
			if (tp && tp->base==FCT) {
				error('s',"enum%n defined as returnT for%n (did you forget a ';'?)",nn,this);
				nn = this;
				break;
			}
			nn->n_list = this;
			Penum(nn->tp)->e_body = 1;
		}
		else
			nn = this;
		break;
	default:
		nn = this;
	}

	for (n=this; n; n=nx) {
		Ptype t = n->tp;
		nx = n->n_list;
		n->n_sto = stc;
/*
		if (t
		&& n_oper==TNAME
		&& t->base==FCT) {	// HORRIBLE FUDGE: fix the bad grammar
			Pfct f = (Pfct)t;
			Pfct f2 = (Pfct)f->returns;
			if (f2 && f2->base==FCT) {
				Pexpr e = f2->argtype;
				if  (e->base == ELIST) {
					// get the real name, fix its type
					if (e->e2 || e->e1->base!=DEREF) goto zse;
					Pname rn = (Pname)e->e1->e1;
					if (rn->base!=NAME) goto zse;
					f->returns = new ptr(PTR,0);
					b = new basetype(TYPE,ktbl->look(n->string,0));
					n->n_oper = 0;
					n->string = rn->string;
					n->base = NAME;
				}
			}
		}
zse:
*/
		if (n->base == TNAME) error('i',"redefinition ofTN%n",n);

		if (t == 0) {
			if (bl == 0)
				n->tp = t = b;
			else {
				error("body of nonF%n",n);
				t = new fct(defa_type,0,0);
			}
		}

		switch (t->base) {
		case PTR:
		case RPTR:
			n->tp = Pptr(t)->normalize(b);
			break;
		case VEC:
			n->tp = Pvec(t)->normalize(b);
			break;
		case FCT:
			n->tp = Pfct(t)->normalize(b);
			break;
		case FIELD:
			if (n->string == 0) n->string = make_name('F');
			n->tp = t;
			Pbase tb = b;
		flatten:
//error('d',"flatten %d %d %d",tb->base,b->b_unsigned,b->b_const);
			switch (tb->base) {
			case TYPE:   /* chase typedefs */
				tb = (Pbase)tb->b_name->tp;
				goto flatten;
			case INT:
				Pbase(t)->b_fieldtype = (b->b_unsigned) ? uint_type : int_type;
				goto iii;
			case CHAR:
				Pbase(t)->b_fieldtype = (b->b_unsigned) ? uchar_type : char_type;
				goto iii;
			case SHORT:
				Pbase(t)->b_fieldtype = (b->b_unsigned) ? ushort_type : short_type;
				goto iii;
			iii:
				Pbase(t)->b_unsigned = b->b_unsigned;
				Pbase(t)->b_const = b->b_const;
				break;
			default:
				error("non-int field");
				n->tp = defa_type;
			}
			break;
		}

		f = (Pfct) n->tp;

		if (f->base != FCT) {
			if (bl) {
				error("body for nonF%n",n);
				n->tp = f = new fct(defa_type,0,0);
				continue;
			}
			if (inli) error("inline nonF%n",n);
			if (virt) error("virtual nonF%n",n);
				
			if (tpdf) {
				if (n->n_initializer) {
					error("Ir for typedefN%n",n);
					n->n_initializer = 0;
				}
				n->tdef();
			}
			continue;
		}

		f->f_inline = inli;
		f->f_virtual = virt;	

		if (tpdf) {
			if (f->body = bl) error("typedef%n { ... }",n);
			n->tdef();
			continue;
		}
		
		if (f->body = bl) continue;

		/*
			Check function declarations.
			Look for class object instansiations
			The real ambiguity:		; class x fo();
				is interpreted as an extern function
				declaration NOT a class object with an
				empty initializer
		*/
		{	Pname cn = f->returns->is_cl_obj();
			bit clob = (cn || cl_obj_vec);
//error('d',"%n: fr%t cn%n",n,f->returns,cn);
			if (f->argtype) { /* check argument/initializer list */
				Pname nn;

				for (nn=f->argtype; nn; nn=nn->n_list) {
					if (nn->base != NAME) {
						if (!clob) {
							error("ATX for%n",n);
							goto zzz;
						}
						goto is_obj;
					}
/*
					if (nn->string) {
						error("AN%n inD of%n",nn,n);
						nn->string = 0;
					}
*/
					if (nn->tp) goto ok;
				}
				if (!clob) {
					error("FALX");
					goto zzz;
				}
		is_obj:
//fprintf(stderr,"is_obj: %d %s tp = %d %d\n",this,string,f->returns,f->returns->base); fflush(stderr);
				/* it was an initializer: expand to constructor */
				n->tp = f->returns;
				if (f->argtype->base != ELIST) f->argtype = (Pname)new expr(ELIST,(Pexpr)f->argtype,0);
				n->n_initializer = new texpr(VALUE,cn->tp,(Pexpr)f->argtype);
				goto ok;
			zzz:
				if (f->argtype) {
					DEL(f->argtype);
					f->argtype = 0;
					f->nargs = 0;
					f->nargs_known = !fct_void;
				}
			}
			else {	/* T a(); => function declaration */
/*
				if (clob) {
					DEL(n->tp);
					n->tp = f->returns;
				}
*/
			}
		ok:
			;
		}
	}
	return nn;
}