#include <invalid.h>
#include <assert.h>
#include <c/string.h>

#ifdef DEBUG
# include <iostream.h>
# define D(X) X
#else
# define D(X) /**/
#endif

inline int invalid_c::length() const {return s?strlen(s)+1:0;}

invalid_c::invalid_c(const void *pp, char *ss)
 : p(pp), s(ss)
{D(cerr << "i_c::i_c="<<ss<<endl);}

static char *pastem(const char *x, const char *y)
{
 ENTER_FCN("pastem");
 assert(x && y);
 char *rv = new char[strlen(x)+strlen(y)
 					+strlen("(")+strlen(")")+strlen(") and (")+1];
 assert(rv);
 return strcat(strcat(strcat(strcat(strcpy(rv, "("), x), ") and ("), y), ")");
}

invalid_c
invalid_c::operator|(const invalid_c& y)
{
 ENTER_FCN("invalid_c::op|");
 if(y.p && p)
 	return invalid_c(p, pastem(s, y.s));
 else if(p)
 	return *this;
 return y;
}

const invalid_c&
invalid_c::operator|=(const invalid_c& x)
{
 ENTER_FCN("invalid_c::op|=");
 if(p && x.p)
 	(*this) = invalid_c(p, pastem(s, x.s));
 else if(!p)
 	(*this) = x;
 return *this;
}

const invalid_c&
invalid_c::operator&=(const invalid_c& x)
{
 ENTER_FCN("invalid_c::op&=");
 (*this) = (*this) & x;
 return *this;
}

invalid_c
invalid_c::operator&(const invalid_c& y)
{
 ENTER_FCN("invalid_c::op&");
 if(y.p && p)	return invalid_c(p, pastem(s, y.s));
 return invalid_c();
}

invalid_c::invalid_c(const char * ss, const void *pp)
 : s(ss ? strcpy(new char[strlen(ss)+1], ss) : 0), p(pp?pp:&s)
{ENTER_FCN("invalid_c::2");
 D(cerr<<"i_c::i_c(2)"<<ss<<endl;assert(s));}

#ifdef DEBUG
# define NOERROR	"NO ERROR"
#else
# define NOERROR	"?"
#endif

invalid_c::invalid_c()
 : p(0), s(strcpy(new char[strlen(NOERROR)+1], NOERROR))
{}

invalid_c invalid_c::mark(const char *marker) const
{
 ENTER_FCN("invalid_c::mark");
 assert(s && marker);
 char *x = new char[strlen(marker)+strlen(":[")+strlen(s)+strlen("]")+1];
 MARK_LINE;
 assert(x);
 return invalid_c(p, 
 				  strcat(strcat(strcat(strcpy(x, marker), ":["), s), "]"));
}

invalid_c::~invalid_c()
{
 delete [length()] s;
}

invalid_c::invalid_c(const invalid_c& x)
 : p(x.p), s(strcpy(new char[x.length()], x.s))
{D(cerr<<"i_c::i_c(3)="<<x.s<<endl);assert(x.s); assert(s);}

const invalid_c& invalid_c::operator=(const invalid_c& x)
{
 D(cerr << "i_c::op=" << x.s << endl);
 assert(x.s);
 if(s != x.s)	{
	delete [length()] s;
	s = strcpy(new char[x.length()], x.s);
 	}
 p = x.p;
 assert(s);
 return *this;
}
