--- /dev/null
+#include <stdlib.h>
+#include "Action.h"
+#include "omodel.h"
+#include "model.h"
+#include "dmodel.h"
+#include "set.h"
+#include "normalizer.h"
+
+char * Action::calculatebound(Constraint *c, Label *clabel) {
+ return getset(c,clabel->label());
+}
+
+char * Action::getset(Constraint *c, char *v) {
+ char *set=NULL;
+ if (c==NULL||v==NULL)
+ return NULL;
+ for(int i=0;i<c->numquants();i++) {
+ if(equivalentstrings(c->getquant(i)->getlabel()->label(),v)) {
+ if (c->getquant(i)->getset()->gettype()==SET_label)
+ set=c->getquant(i)->getset()->getname();
+ break;
+ }
+ }
+ return set;
+}
+
+bool Action::possiblysameset(char *v1, Constraint *c1, char *v2, Constraint *c2) {
+ return possiblysameset(getset(c1,v1),getset(c2,v2));
+}
+
+bool Action::comparepredicates(Constraint *c1, CoercePredicate *cp1, Constraint *c2, CoercePredicate *cp2) {
+ if (cp1->getcoercebool()!=cp2->getcoercebool())
+ return false;
+ Predicate *p1=cp1->getpredicate();
+ Predicate *p2=cp2->getpredicate();
+ if (p1->gettype()!=p2->gettype())
+ return false;
+ int type=p1->gettype();
+ if (type==PREDICATE_LT ||
+ type==PREDICATE_LTE ||
+ type==PREDICATE_EQUALS ||
+ type==PREDICATE_GTE ||
+ type==PREDICATE_GT) {
+ char *v1=p1->getvalueexpr()->getlabel()->label();
+ char *v2=p2->getvalueexpr()->getlabel()->label();
+ if (!equivalentstrings(p1->getvalueexpr()->getrelation()->getname(),
+ p2->getvalueexpr()->getrelation()->getname()))
+ return false;
+ if (!(compareee(p1->geteleexpr(),v1,p2->geteleexpr(),v2)))
+ return false;
+ else
+ return true;
+ }
+ if (type==PREDICATE_SET) {
+ char *v1=p1->getlabel()->label();
+ char *v2=p2->getlabel()->label();
+ return comparesetexpr(p1->getsetexpr(),v1,p2->getsetexpr(),v2);
+ }
+ if (type==PREDICATE_EQ1||type==PREDICATE_GTE1) {
+ if(p1->getsetexpr()->gettype()!=p2->getsetexpr()->gettype())
+ return false;
+ switch(p1->getsetexpr()->gettype()) {
+ case SETEXPR_LABEL: {
+ return equivalentstrings(p1->getsetexpr()->getsetlabel()->getname(), p2->getsetexpr()->getsetlabel()->getname());
+ }
+ case SETEXPR_REL:
+ case SETEXPR_INVREL: {
+ /* these can't interfere....*/
+ return equivalentstrings(p1->getsetexpr()->getrelation()->getname(), p2->getsetexpr()->getrelation()->getname());
+ }
+ }
+ }
+ return false; /* by default */
+}
+
+bool Action::comparesetexpr(Setexpr *s1,char *v1,Setexpr *s2,char *v2) {
+ if (s1->gettype()!=s2->gettype())
+ return false;
+ switch(s1->gettype()) {
+ case SETEXPR_LABEL:
+ if (!equivalentstrings(s1->getsetlabel()->getname(),
+ s2->getsetlabel()->getname()))
+ return false;
+ else return true;
+ case SETEXPR_REL:
+ case SETEXPR_INVREL:
+ if (!equivalentstrings(v1, s1->getlabel()->label()))
+ return false;
+ if (!equivalentstrings(v2, s2->getlabel()->label()))
+ return false;
+ if (!equivalentstrings(s1->getrelation()->getname(),
+ s2->getrelation()->getname()))
+ return false;
+ else return true;
+ default:
+ return false;
+ }
+}
+
+bool Action::compareee(Elementexpr *ee1,char *v1,Elementexpr *ee2,char *v2) {
+ if (ee1->gettype()!=ee2->gettype())
+ return false;
+ switch(ee1->gettype()) {
+ case ELEMENTEXPR_LABEL:
+ if (!equivalentstrings(ee1->getlabel()->label(),v1))
+ return false;
+ if (!equivalentstrings(ee2->getlabel()->label(),v2))
+ return false;
+ return true;
+ case ELEMENTEXPR_SUB:
+ if (compareee(ee1->getleft(),v1,ee2->getleft(),v2) &&
+ compareee(ee1->getright(),v1,ee2->getright(),v2))
+ return true;
+ else return false;
+ case ELEMENTEXPR_RELATION:
+ if (compareee(ee1->getleft(),v1,ee2->getleft(),v2) &&
+ equivalentstrings(ee1->getrelation()->getname(),ee2->getrelation()->getname()))
+ return true;
+ else return false;
+ case ELEMENTEXPR_ADD:
+ case ELEMENTEXPR_MULT:
+ if ((compareee(ee1->getleft(),v1,ee2->getleft(),v2) &&
+ compareee(ee1->getright(),v1,ee2->getright(),v2))||
+ (compareee(ee1->getleft(),v1,ee2->getright(),v2) &&
+ compareee(ee1->getright(),v1,ee2->getleft(),v2)))
+ return true;
+ else return false;
+ case ELEMENTEXPR_LIT:
+ if (ee1->getliteral()->gettype()!=
+ ee2->getliteral()->gettype())
+ return false;
+ switch(ee1->getliteral()->gettype()) {
+ case LITERAL_NUMBER:
+ return (ee1->getliteral()->number()==ee2->getliteral()->number());
+ case LITERAL_TOKEN:
+ return (equivalentstrings(ee1->getliteral()->token(),ee2->getliteral()->token()));
+ default:
+ return false;
+ }
+ case ELEMENTEXPR_SETSIZE:
+ return comparesetexpr(ee1->getsetexpr(),v1,ee2->getsetexpr(),v2);
+ default:
+ return false;
+ }
+}
+
+bool Action::possiblysameset(char *set1, char *v2, Constraint *c2) {
+ return possiblysameset(set1,getset(c2,v2));
+}
+
+bool Action::possiblysameset(char *set1,char *set2) {
+ if (set1==NULL||set2==NULL)
+ return true; /* At least one variable isn't spanning over a set...could be from any set*/
+ DomainSet *dset1=domrelation->getset(set1);
+ DomainSet *dset2=domrelation->getset(set2);
+ WorkSet *ws=new WorkSet(true);
+ while(dset1!=NULL) {
+ ws->addobject(dset1);
+ dset1=domrelation->getsuperset(dset1);
+ }
+ bool sameset=false;
+ if (!ws->contains(dset2)) {
+ while(dset2!=NULL) {
+ if (ws->contains(dset2)) {
+ if (dset2->gettype()==DOMAINSET_PARTITION&&
+ dset2!=dset1)
+ sameset=false;
+ else
+ sameset=true;
+ break;
+ }
+ dset2=domrelation->getsuperset(dset2);
+ }
+ }
+ delete(ws);
+ return sameset;
+}
+
+bool Action::conflictwithaddtoset(char *set, Constraint *c, CoercePredicate *p) {
+ /* Test for conflict with abstraction function */
+ if (!p->isrule()&&
+ equivalentstrings(p->gettriggerset(),set))
+ return true;
+
+ /* Test for add new constraint */
+ if (c!=NULL) {
+ for(int i=0;i<c->numquants();i++) {
+ if (c->getquant(i)->getset()->gettype()==SET_label)
+ if (equivalentstrings(c->getquant(i)->getset()->getname(),set)) {
+ return true; /*we're adding this constraint because of inclusion*/
+ }
+ }
+ }
+ /* Test for conflict with a \notin set */
+ if (p->isrule()&&
+ (p->getcoercebool()==false)&&
+ (p->getpredicate()->gettype()==PREDICATE_SET)&&
+ (p->getpredicate()->getsetexpr()->gettype()==SETEXPR_LABEL)) {
+ char *psetname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
+ if (equivalentstrings(psetname,set)) {
+ return true;
+ }
+ }
+ /* Test for conflict with setsize=1 */
+ if (p->isrule()&&
+ (p->getcoercebool()==true)&&
+ (p->getpredicate()->gettype()==PREDICATE_EQ1)&&
+ (p->getpredicate()->getsetexpr()->gettype()==SETEXPR_LABEL)) {
+ char *psetname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
+ if (equivalentstrings(psetname,set))
+ return true;
+ }
+ return false;
+}
+
+bool Action::conflictwithremovefromset(WorkSet * checkother,char *set, Constraint *c, CoercePredicate *p) {
+ /* Check for conflict with set size predicate */
+ if (p->isrule() &&
+ (p->getcoercebool()==true)&&
+ ((p->getpredicate()->gettype()==PREDICATE_EQ1)||
+ (p->getpredicate()->gettype()==PREDICATE_GTE1)) &&
+ (p->getpredicate()->getsetexpr()->gettype()==SETEXPR_LABEL)) {
+ char *psetname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
+ if (equivalentstrings(psetname,set))
+ return true;
+ }
+
+ /* Check for conflict with a in SET */
+ if (p->isrule() &&
+ (p->getcoercebool()==true)&&
+ (p->getpredicate()->gettype()==PREDICATE_SET)&&
+ (p->getpredicate()->getsetexpr()->gettype()==SETEXPR_LABEL)) {
+ char *psetname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
+ if (equivalentstrings(psetname,set))
+ return true;
+ }
+
+ /* Check for domain's of relation */
+ DomainRelation *domrelation=globalmodel->getdomainrelation();
+ for(int i=0;i<domrelation->getnumrelation();i++) {
+ DRelation *drelation=domrelation->getrelation(i);
+ char *domain=drelation->getdomain();
+ if(equivalentstrings(domain,set)) {
+ testforconflictremove(set,NULL,drelation->getname(),c,p);
+ if(drelation->isstatic()) {
+ bool flag=false;
+ if(checkother==NULL) {
+ flag=true;
+ checkother=new WorkSet((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
+ }
+ if(!checkother->contains(drelation->getrange())) {
+ checkother->addobject(drelation->getrange());
+ if (conflictwithremovefromset(checkother, drelation->getrange(),c,p))
+ return true;
+ checkother->removeobject(drelation->getrange());
+ }
+ if(flag)
+ delete(checkother);
+ }
+ }
+ }
+ /* Check for range's of relation */
+ for(int i=0;i<domrelation->getnumrelation();i++) {
+ DRelation *drelation=domrelation->getrelation(i);
+ char *range=drelation->getrange();
+ if (equivalentstrings(range,set)) {
+ testforconflictremove(NULL,set,drelation->getname(),c,p);
+ }
+ }
+ return false;
+}
+
+/* remove <v,a> from r */
+bool Action::testforconflictremove(char *setv, char *seta, char *rel, Constraint *c, CoercePredicate *p) {
+ /* check for conflict with v.r=? */
+ if (p->isrule()) {
+ int type=p->getpredicate()->gettype();
+ if ((type==PREDICATE_LT||type==PREDICATE_LTE||type==PREDICATE_EQUALS||type==PREDICATE_GT||type==PREDICATE_GTE) &&
+ possiblysameset(setv,p->getpredicate()->getvalueexpr()->getlabel()->label(),c) &&
+ equivalentstrings(rel,p->getpredicate()->getvalueexpr()->getrelation()->getname()))
+ return true;
+
+ /* check for conflict with |v'.r|?=1 */
+ if ((p->getpredicate()->gettype()==PREDICATE_EQ1||p->getpredicate()->gettype()==PREDICATE_GTE1)&&
+ p->getpredicate()->getsetexpr()->gettype()==SETEXPR_REL&&
+ possiblysameset(setv,p->getpredicate()->getsetexpr()->getlabel()->label(),c)&&
+ equivalentstrings(rel,p->getpredicate()->getsetexpr()->getrelation()->getname()))
+ return true;
+
+ /* check for conflict with |a'.~r|?=1 */
+ if ((p->getpredicate()->gettype()==PREDICATE_EQ1||p->getpredicate()->gettype()==PREDICATE_GTE1) &&
+ p->getpredicate()->getsetexpr()->gettype()==SETEXPR_INVREL &&
+ possiblysameset(seta,p->getpredicate()->getsetexpr()->getlabel()->label(),c)&&
+ equivalentstrings(rel,p->getpredicate()->getsetexpr()->getrelation()->getname()))
+ return true;
+
+ /* check for conflit with (a' in v'.r)*/
+ if (p->getcoercebool()&&
+ p->getpredicate()->gettype()==PREDICATE_SET&&
+ p->getpredicate()->getsetexpr()->gettype()==SETEXPR_REL&&
+ possiblysameset(seta,p->getpredicate()->getlabel()->label(),c)&&
+ possiblysameset(setv,p->getpredicate()->getsetexpr()->getlabel()->label(),c)&&
+ equivalentstrings(rel,p->getpredicate()->getsetexpr()->getrelation()->getname()))
+ return true;
+
+ /* check for conflict with (a' in v'.~r)*/
+ if (p->getcoercebool()&&
+ p->getpredicate()->gettype()==PREDICATE_SET&&
+ p->getpredicate()->getsetexpr()->gettype()==SETEXPR_INVREL &&
+ possiblysameset(seta,p->getpredicate()->getsetexpr()->getlabel()->label(),c) &&
+ possiblysameset(setv,p->getpredicate()->getlabel()->label(),c) &&
+ equivalentstrings(rel,p->getpredicate()->getsetexpr()->getrelation()->getname()))
+ return true;
+ }
+ return false;
+}
+
+
+/* add <v,a> to r */
+bool Action::testforconflict(char *setv, char *seta, char *rel, Constraint *c, CoercePredicate *p) {
+ /* check for conflict with valueexpr*/
+ if (p->isrule()&&
+ (p->getpredicate()->gettype()==PREDICATE_LT ||
+ p->getpredicate()->gettype()==PREDICATE_LTE ||
+ p->getpredicate()->gettype()==PREDICATE_EQUALS ||
+ p->getpredicate()->gettype()==PREDICATE_GTE ||
+ p->getpredicate()->gettype()==PREDICATE_GT) &&
+ possiblysameset(setv,p->getpredicate()->getvalueexpr()->getlabel()->label(),c) &&
+ equivalentstrings(rel,p->getpredicate()->getvalueexpr()->getrelation()->getname()))
+ return true;
+
+ /* check for conflict with |v'.r'|=1 */
+ if (p->isrule() &&
+ p->getpredicate()->gettype()==PREDICATE_EQ1&&
+ p->getpredicate()->getsetexpr()->gettype()==SETEXPR_REL&&
+ possiblysameset(setv,p->getpredicate()->getsetexpr()->getlabel()->label(),c)&&
+ equivalentstrings(rel,p->getpredicate()->getsetexpr()->getrelation()->getname()))
+ return true;
+
+ /* try to catch case of |a'.~r|=1 */
+ if (p->isrule() &&
+ p->getpredicate()->gettype()==PREDICATE_EQ1 &&
+ p->getpredicate()->getsetexpr()->gettype()==SETEXPR_INVREL &&
+ possiblysameset(seta,p->getpredicate()->getsetexpr()->getlabel()->label(),c)&&
+ equivalentstrings(rel,p->getpredicate()->getsetexpr()->getrelation()->getname()))
+ return true;
+
+ /* try to catch case of !(a' in v'.r)*/
+ if (p->isrule() &&
+ !p->getcoercebool()&&
+ p->getpredicate()->gettype()==PREDICATE_SET&&
+ p->getpredicate()->getsetexpr()->gettype()==SETEXPR_REL&&
+ possiblysameset(seta,p->getpredicate()->getlabel()->label(),c)&&
+ possiblysameset(setv,p->getpredicate()->getsetexpr()->getlabel()->label(),c)&&
+ equivalentstrings(rel,p->getpredicate()->getsetexpr()->getrelation()->getname()))
+ return true;
+
+
+ /* try to catch case of !(a' in v'.~r)*/
+ if (p->isrule() &&
+ !p->getcoercebool()&&
+ p->getpredicate()->gettype()==PREDICATE_SET&&
+ p->getpredicate()->getsetexpr()->gettype()==SETEXPR_INVREL&&
+ possiblysameset(seta,p->getpredicate()->getsetexpr()->getlabel()->label(),c)&&
+ possiblysameset(setv,p->getpredicate()->getlabel()->label(),c)&&
+ equivalentstrings(rel,p->getpredicate()->getsetexpr()->getrelation()->getname()))
+ return true;
+
+ return false;
+}
--- /dev/null
+#ifndef Action_H
+#define Action_H
+
+#include "classlist.h"
+class Action {
+ public:
+ virtual void repairpredicate(Hashtable *env, CoercePredicate *p)=0;
+ virtual void breakpredicate(Hashtable *env, CoercePredicate *p)=0;
+ virtual bool conflict(Constraint *c1, CoercePredicate *p1, Constraint *c2, CoercePredicate *p2)=0;
+ virtual bool canrepairpredicate(CoercePredicate *p)=0;
+
+ protected:
+ char * getset(Constraint *c, char *v);
+ char * calculatebound(Constraint *c, Label *clabel);
+ bool comparepredicates(Constraint *c1, CoercePredicate *cp1, Constraint *c2, CoercePredicate *cp2);
+ bool comparesetexpr(Setexpr *s1,char *v1,Setexpr *s2,char *v2);
+ bool compareee(Elementexpr *ee1,char *v1,Elementexpr *ee2,char *v2);
+ bool testforconflict(char *setv, char *seta, char *rel, Constraint *c, CoercePredicate *p);
+ bool testforconflictremove(char *setv, char *seta, char *rel, Constraint *c, CoercePredicate *p);
+ DomainRelation *domrelation;
+ model * globalmodel;
+ bool possiblysameset(char *v1, Constraint *c1, char *v2, Constraint *c2);
+ bool possiblysameset(char *set1, char *v2, Constraint *c2);
+ bool possiblysameset(char *set1, char *set2);
+ bool conflictwithaddtoset(char *set, Constraint *c, CoercePredicate *p);
+ bool conflictwithremovefromset(WorkSet *,char *set, Constraint *c, CoercePredicate *p);
+};
+#endif
--- /dev/null
+// handles prediate of the following forms: VE<E, VE<=E, VE=E, VE>=E, VE>E
+
+#include <stdlib.h>
+#include <assert.h>
+#include "ActionAssign.h"
+#include "dmodel.h"
+#include "normalizer.h"
+#include "omodel.h"
+#include "Relation.h"
+#include "set.h"
+#include "Hashtable.h"
+#include "model.h"
+#include "processobject.h"
+#include "element.h"
+#include "common.h"
+
+
+ActionAssign::ActionAssign(DomainRelation *drel, model *m) {
+ domrelation=drel;
+ globalmodel=m;
+}
+
+char * ActionAssign::gettype(Constraint *c,Elementexpr *ee) {
+ switch(ee->gettype()) {
+ case ELEMENTEXPR_LABEL:
+ return getset(c,ee->getlabel()->label());
+ case ELEMENTEXPR_SUB:
+ case ELEMENTEXPR_ADD:
+ case ELEMENTEXPR_MULT:
+ return "int";
+ case ELEMENTEXPR_LIT: {
+ Literal *lit=ee->getliteral();
+ switch(lit->gettype()) {
+ case LITERAL_NUMBER:
+ return "int";
+ case LITERAL_TOKEN:
+ return "token";
+ case LITERAL_BOOL:
+ printf("ERROR in gettype\n");
+ exit(-1);
+ }
+ }
+ case ELEMENTEXPR_SETSIZE:
+ return "int";
+ case ELEMENTEXPR_RELATION: {
+ Relation *r=ee->getrelation();
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ return drel->getrelation(r->getname())->getrange();
+ }
+ }
+}
+
+
+// repairs the given predicate
+void ActionAssign::repairpredicate(Hashtable *env, CoercePredicate *cp) {
+ Predicate *p=cp->getpredicate();
+ Element *ele=evaluateexpr(p->geteleexpr(),env,globalmodel); //ele=E
+ Element *index=(Element *) env->get(p->getvalueexpr()->getlabel()->label()); // index=V
+ char *rel=p->getvalueexpr()->getrelation()->getname(); // rel=R
+ WorkRelation *relation=domrelation->getrelation(rel)->getrelation();
+ Element *old=(Element *)relation->getobj(index); // old=V.R
+ if (old!=NULL)
+ relation->remove(index,old);
+ DRelation *drel=domrelation->getrelation(rel);
+
+ if(!equivalentstrings(drel->getdomain(),"int")) {
+ DomainSet *domain=domrelation->getset(drel->getdomain());
+ if (!domain->getset()->contains(index))
+ domrelation->addtoset(index,domain,globalmodel);
+ }
+
+
+ switch (p->gettype()) {
+ case PREDICATE_LT: {
+ Element *ele2=new Element(ele->intvalue()-1);
+ delete(ele);
+ relation->put(index,ele2);
+ break;
+ }
+ case PREDICATE_LTE: {
+ relation->put(index,ele);
+ break;
+ }
+ case PREDICATE_EQUALS: {
+ relation->put(index,ele);
+ if(!equivalentstrings(drel->getrange(),"int")&&
+ !equivalentstrings(drel->getrange(),"token")) {
+ DomainSet *range=domrelation->getset(drel->getrange());
+ if (!range->getset()->contains(ele))
+ domrelation->addtoset(ele,range,globalmodel);
+ }
+ break;
+ }
+ case PREDICATE_GTE: {
+ relation->put(index,ele);
+ break;
+ }
+ case PREDICATE_GT: {
+ Element *ele2=new Element(ele->intvalue()+1);
+ delete(ele);
+ relation->put(index,ele2);
+ break;
+ }
+ }
+}
+
+
+
+void ActionAssign::breakpredicate(Hashtable *env, CoercePredicate *cp)
+{
+#ifdef DEBUGMESSAGES
+ printf("ActionAssign::breakpredicate CALLED\n");
+ cp->getpredicate()->print(); printf("\n");
+#endif
+
+ Predicate *p = cp->getpredicate();
+ Element *ele = evaluateexpr(p->geteleexpr(),env,globalmodel); //ele=E
+ Element *index = (Element *) env->get(p->getvalueexpr()->getlabel()->label()); // index=V
+
+
+#ifdef DEBUGMESSAGES
+ printf("index=%s\n", p->getvalueexpr()->getlabel()->label());
+ if (index == NULL)
+ printf("index - bad\n");
+ else printf("index - ok\n");
+#endif
+
+ char *rel = p->getvalueexpr()->getrelation()->getname(); // rel=R
+ WorkRelation *relation = domrelation->getrelation(rel)->getrelation();
+
+#ifdef DEBUGMESSAGES
+ if (relation == NULL)
+ printf("relation - bad\n");
+ else printf("relation - ok\n");
+ fflush(NULL);
+#endif
+
+ Element *old_ve = (Element *)relation->getobj(index); // old_ve=V.R
+
+ if (old_ve!=NULL)
+ relation->remove(index,old_ve);
+ DRelation *drel = domrelation->getrelation(rel);
+
+ if(!equivalentstrings(drel->getdomain(),"int"))
+ {
+ DomainSet *domain = domrelation->getset(drel->getdomain());
+ if (!domain->getset()->contains(index))
+ domrelation->addtoset(index,domain,globalmodel);
+ }
+
+#ifdef DEBUGMESSAGES
+ printf("p->gettype() = %d\n", p->gettype());
+ fflush(NULL);
+#endif
+
+
+ switch (p->gettype()) {
+ // VE<E
+ case PREDICATE_LT:
+ {
+ // set VE=E which breaks VE<E
+ Element *newele=new Element(ele->intvalue());
+ delete(ele);
+ relation->put(index,newele);
+ break;
+ }
+
+ // VE<=E
+ case PREDICATE_LTE:
+ {
+ // set VE=E+1, which breaks VE<=E
+ Element *newele=new Element(ele->intvalue()+1);
+ delete(ele);
+ relation->put(index,newele);
+ break;
+ }
+
+ // VE=E
+ case PREDICATE_EQUALS:
+ {
+ DRelation *drel=domrelation->getrelation(rel);
+
+ // if the V.R is an integer, set VE=E+1, which breaks VE=E
+ if (equivalentstrings(drel->getrange(),"int"))
+ {
+ Element *newele=new Element(ele->intvalue()+1);
+ delete(ele);
+ relation->put(index,newele);
+ }
+ else
+ {
+ Element *newele = NULL;
+ printf("PREDICATE_EQUALS for tokens\n");
+ //printf("range name = %s\n", drel->getrange()); fflush(NULL);
+ //printf("Current value: "); old_ve->print(); printf("\n");
+
+ /* find a value in the actual range that is different from the
+ current value of V.R */
+ char* old_token = old_ve->gettoken();
+ WorkSet *ws = drel->gettokenrange();
+ bool found = false;
+ char *token = (char*) ws->firstelement();
+ while (token)
+ {
+ printf("Token: %s\n", token);
+ if (!equivalentstrings(token, old_token))
+ {
+ found = true;
+ newele = new Element(token);
+ break;
+ }
+ token = (char*) ws->getnextelement(token);
+ }
+
+ if (!found)
+ {
+ printf("The following predicate cannot be broken:");
+ cp->getpredicate()->print(); printf("\n");
+ }
+ else relation->put(index, newele);
+
+ fflush(NULL);
+ printf("\n\n");
+ }
+ break;
+ }
+
+ // VE>=E
+ case PREDICATE_GTE:
+ {
+ // set VE=E-1, which breaks VE>=E
+ Element *newele=new Element(ele->intvalue()-1);
+ delete(ele);
+ relation->put(index,newele);
+ break;
+ }
+
+ // VE>E
+ case PREDICATE_GT:
+ {
+ // set VE=E, which breaks VE>E
+ Element *newele=new Element(ele->intvalue());
+ delete(ele);
+ relation->put(index,newele);
+ break;
+ }
+ }
+}
+
+
+
+bool ActionAssign::conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2) {
+ assert(canrepairpredicate(p1));
+ if(comparepredicates(c1,p1,c2,p2))
+ return false; /*same predicates don't conflict*/
+ /* we have v.r?a */
+ /* add <v,?> to r */
+
+ /* Compute bounding set if there is one */
+
+
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(p1->getpredicate()->getvalueexpr()->getrelation()->getname())->getrange();
+
+ char *boundset=gettype(c1,p1->getpredicate()->geteleexpr());
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,NULL,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, NULL);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ return testforconflict(getset(c1,p1->getpredicate()->getvalueexpr()->getlabel()->label()), NULL,
+ p1->getpredicate()->getvalueexpr()->getrelation()->getname(),c2,p2)||
+ testforconflictremove(getset(c1,p1->getpredicate()->getvalueexpr()->getlabel()->label()), NULL,
+ p1->getpredicate()->getvalueexpr()->getrelation()->getname(),c2,p2);
+}
+
+bool ActionAssign::canrepairpredicate(CoercePredicate *cp) {
+ if (cp->getcoercebool()==false)
+ return false;
+ Predicate *p=cp->getpredicate();
+ if (p==NULL)
+ return false;
+ if (p->gettype()==PREDICATE_LT||
+ p->gettype()==PREDICATE_LTE||
+ p->gettype()==PREDICATE_EQUALS||
+ p->gettype()==PREDICATE_GTE||
+ p->gettype()==PREDICATE_GT) {
+ Valueexpr *ve=p->getvalueexpr();
+ DRelation *dr=domrelation->getrelation(ve->getrelation()->getname());
+ if (dr->isstatic()) /* can't change static relations */
+ return false;
+ else
+ return true;
+ }
+ /* Coercing set membership */
+ return false;
+}
--- /dev/null
+// handles prediate of the following forms: VE<E, VE<=E, VE=E, VE>=E, VE>E
+
+
+#ifndef ActionAssign_H
+#define ActionAssign_H
+#include "classlist.h"
+#include "Action.h"
+class ActionAssign:public Action {
+ public:
+ ActionAssign(DomainRelation *drel, model *);
+ void repairpredicate(Hashtable *env, CoercePredicate *p);
+ void breakpredicate(Hashtable *env, CoercePredicate *p);
+ bool conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2);
+ bool canrepairpredicate(CoercePredicate *p);
+ private:
+ char * gettype(Constraint *c,Elementexpr *ee);
+};
+#endif
--- /dev/null
+// Repairs and destroys size propositions of the form "size(SE)=1"
+
+#include <assert.h>
+#include "ActionEQ1.h"
+#include "dmodel.h"
+#include "normalizer.h"
+#include "omodel.h"
+#include "model.h"
+#include "Relation.h"
+#include "set.h"
+#include "Hashtable.h"
+#include "Guidance.h"
+
+ActionEQ1::ActionEQ1(DomainRelation *drel, model *m) {
+ domrelation=drel;
+ globalmodel=m;
+}
+
+void ActionEQ1::repairpredicate(Hashtable *env,CoercePredicate *p) {
+ switch(p->getpredicate()->getsetexpr()->gettype()) {
+ // size(S)=1
+ case SETEXPR_LABEL: {
+ char *setname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
+ DomainSet *ds=domrelation->getset(setname);
+ if (ds->getset()->size()>1) {
+ Guidance *g=globalmodel->getguidance();
+ WorkSet *ws=ds->getset();
+ while(ws->size()>1) {
+ Element *e=(Element *)ws->firstelement();
+ domrelation->delfromsetmovetoset(e,domrelation->getset(setname), globalmodel);
+ }
+ } else
+ this->ActionGEQ1::repairpredicate(env,p);
+ }
+ break;
+
+ // size(V.R)=1
+ case SETEXPR_REL: {
+ DRelation *dr=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname());
+ WorkRelation *wr=dr->getrelation();
+ Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
+ WorkSet *ws=wr->getset(key);
+
+ if (ws!=NULL&&ws->size()>1) {
+ //Remove elements
+ int size=ws->size();
+ for(int i=0;i<(size-1);i++) {
+ void *objtoremove=ws->firstelement();
+ wr->remove(key,objtoremove);
+ }
+ } else
+ this->ActionGEQ1::repairpredicate(env,p);
+ }
+ break;
+
+ // size(R.V)=1
+ case SETEXPR_INVREL: {
+ DRelation *dr=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname());
+ WorkRelation *wr=dr->getrelation();
+ Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
+ WorkSet *ws=wr->invgetset(key);
+
+ if (ws!=NULL&&ws->size()>1) {
+ //Remove elements
+ int size=ws->size();
+ for(int i=0;i<(size-1);i++) {
+ void *objtoremove=ws->firstelement();
+ wr->remove(objtoremove,key);
+ }
+ } else
+ this->ActionGEQ1::repairpredicate(env,p);
+ }
+ break;
+ }
+}
+
+
+
+
+void ActionEQ1::breakpredicate(Hashtable *env, CoercePredicate *p)
+{
+#ifdef DEBUGMESSAGES
+ printf("ActionEQ1::breakpredicate CALLED\n");
+ p->getpredicate()->print(); printf("\n");
+#endif
+
+ this->ActionGEQ1::breakpredicate(env, p);
+}
+
+
+
+
+bool ActionEQ1::conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2) {
+ assert(canrepairpredicate(p1));
+ Setexpr *pse=p1->getpredicate()->getsetexpr();
+ if(comparepredicates(c1,p1,c2,p2))
+ return false; /*same predicates don't conflict*/
+
+ switch(pse->gettype()) {
+ case SETEXPR_LABEL: {
+ char *boundname=NULL;
+ Guidance *g=globalmodel->getguidance();
+ //DomainSet *fromset=domrelation->getsource(domrelation->getset(pse->getsetlabel()->getname()));
+ char *setname=pse->getsetlabel()->getname();
+
+ DomainSet *fromset=domrelation->getset(setname);
+
+ {
+ Source s=g->sourceforsetsize(fromset->getname());
+ if (s.setname!=NULL)
+ boundname=s.setname;
+ }
+
+ {
+ /* See what additional addsets we get*/
+
+ WorkSet *ws=domrelation->conflictaddsets(pse->getsetlabel()->getname(),boundname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ {
+ /* What additions do we get from removal */
+ WorkSet *ws=domrelation->removeconflictaddsets(pse->getsetlabel()->getname(),globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+
+ /* Check what removals addition into set can cause */
+ if (boundname!=NULL) {
+ WorkSet *ws=domrelation->conflictdelsets(pse->getsetlabel()->getname(), boundname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* What sets will removal cause removal from */
+ {
+ WorkSet *ws=domrelation->removeconflictdelsets(pse->getsetlabel()->getname());
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ return false;
+ }
+ case SETEXPR_REL: {
+ char *fromname=NULL;
+ /* we have a in v.r */
+ /* add <v,a> to r */
+ if (p2->isrule()&&
+ (p2->getpredicate()->gettype()==PREDICATE_GTE1||
+ p2->getpredicate()->gettype()==PREDICATE_EQ1)&&
+ p2->getpredicate()->getsetexpr()->gettype()==SETEXPR_REL) {
+ return false;
+ }
+
+ /* Compute bounding set if there is one */
+
+
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(pse->getrelation()->getname())->getrange();
+ Guidance *g=globalmodel->getguidance();
+ Source s=g->sourceforsetsize(insertset);
+
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,s.setname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, s.setname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+
+
+ return testforconflict(getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()), fromname,
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2)||testforconflictremove(getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()), fromname,
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
+ }
+ case SETEXPR_INVREL: {
+ char *fromname=NULL;
+ /* we have a in v.r */
+ /* add <a,v> to r */
+ if (p2->isrule()&&
+ (p2->getpredicate()->gettype()==PREDICATE_GTE1||
+ p2->getpredicate()->gettype()==PREDICATE_EQ1)&&
+ p2->getpredicate()->getsetexpr()->gettype()==SETEXPR_INVREL) {
+ return false;
+ }
+
+ /* Compute bounding set if there is one */
+
+
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(pse->getrelation()->getname())->getdomain();
+ Guidance *g=globalmodel->getguidance();
+ Source s=g->sourceforsetsize(insertset);
+
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,s.setname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, s.setname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+
+ return testforconflict(fromname,
+ getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2)||
+ testforconflictremove(fromname,
+ getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
+ }
+ }
+}
+
+
+
+
+bool ActionEQ1::canrepairpredicate(CoercePredicate *cp) {
+ if (cp->getcoercebool()==false)
+ return false;
+ Predicate *p=cp->getpredicate();
+
+
+ if (p->gettype()!=PREDICATE_EQ1)
+ return false;
+
+ /* Coercing set membership */
+ Setexpr *se=p->getsetexpr();
+ int setexprtype=se->gettype();
+ if (setexprtype==SETEXPR_REL||
+ setexprtype==SETEXPR_INVREL) {
+ DRelation *dr=domrelation->getrelation(se->getrelation()->getname());
+ if (dr->isstatic())
+ return false; /* Can't change static domain relations */
+ }
+
+ return true;
+}
--- /dev/null
+#ifndef ActionEQ1_H
+#define ActionEQ1_H
+#include "classlist.h"
+#include "ActionGEQ1.h"
+class ActionEQ1:public ActionGEQ1 {
+ public:
+ ActionEQ1(DomainRelation *drel,model *);
+ void repairpredicate(Hashtable *env, CoercePredicate *p);
+ void breakpredicate(Hashtable *env, CoercePredicate *p);
+ bool conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2);
+ bool canrepairpredicate(CoercePredicate *p);
+ protected:
+};
+#endif
--- /dev/null
+#include <stdlib.h>
+#include <assert.h>
+#include "ActionGEQ1.h"
+#include "dmodel.h"
+#include "normalizer.h"
+#include "omodel.h"
+#include "model.h"
+#include "Relation.h"
+#include "set.h"
+#include "element.h"
+#include "Hashtable.h"
+#include "Guidance.h"
+
+
+ActionGEQ1::ActionGEQ1(DomainRelation *drel, model *m) {
+ domrelation=drel;
+ globalmodel=m;
+}
+
+void ActionGEQ1::repairpredicate(Hashtable *env,CoercePredicate *p) {
+#ifdef DEBUGMESSAGES
+ printf("ActionGEQ1::repairpredicate CALLED\n");
+ fflush(NULL);
+#endif
+ switch(p->getpredicate()->getsetexpr()->gettype()) {
+ case SETEXPR_LABEL: {
+ /* Set should be too small if we are doing a repair
+ We need to add 1 element */
+ Guidance *g=globalmodel->getguidance();
+ char * newsetname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
+ Source s=g->sourceforsetsize(newsetname);
+ if (s.setname!=NULL) {
+ /* just pick an element from s.setname */
+ char *setname=s.setname;
+ if (equivalentstrings(s.setname,"int")) {
+ /* special case for ints*/
+ WorkSet *wsnew=domrelation->getset(newsetname)->getset();
+ for(int i=0;;i++) {
+ Element *e=new Element(i);
+ if (!wsnew->contains(e)) {
+ /* Got our element */
+ domrelation->addtoset(e,domrelation->getset(newsetname),globalmodel);
+ return;
+ }
+ delete(e);
+ }
+ } else {
+ WorkSet *ws=domrelation->getset(setname)->getset();
+ WorkSet *wsnew=domrelation->getset(newsetname)->getset();
+ Element *e=(Element *)ws->firstelement();
+ while(e!=NULL) {
+ if (!wsnew->contains(e)) {
+ /* Got our element */
+ domrelation->addtoset(e,domrelation->getset(newsetname),globalmodel);
+ //printf("HERE?!\n"); fflush(NULL);
+ return;
+ }
+ e=(Element *)ws->getnextelement(e);
+ }
+ printf("Error...set %s doesn't have enough elements for %s\n",setname,newsetname);
+ exit(-1);
+ }
+ } else {
+ /* call functionpointer */
+ DomainSet *newset=domrelation->getset(newsetname);
+ char *type=newset->getelementtype();
+ structure *st=globalmodel->getstructure(type);
+ Element *ele=s.functionptr(st,globalmodel);
+ if (ele==NULL) {
+ printf("Error...allocation function doesn't return structure for %s\n",newsetname);
+ exit(-1);
+ }
+ domrelation->addtoset(ele,newset,globalmodel);
+ return;
+ }
+ }
+ break;
+
+
+
+ case SETEXPR_REL: {
+ /* Set should be too small if we are doing a repair
+ We need to add 1 element */
+ Guidance *g=globalmodel->getguidance();
+ char * relationname=p->getpredicate()->getsetexpr()->getrelation()->getname();
+ Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
+ DRelation *relation=domrelation->getrelation(relationname);
+ char *rangeset=relation->getrange();
+ Source s=g->sourceforrelation(rangeset);
+ if (s.setname!=NULL) {
+ /* just pick an element from s.setname */
+ char *setname=s.setname;
+ if (equivalentstrings(s.setname,"int")) {
+ /* special case for ints*/
+ for(int i=0;;i++) {
+ WorkSet *wsnew=domrelation->getrelation(relationname)->getrelation()->getset(key);
+ Element *e=new Element(i);
+ if (wsnew==NULL||!wsnew->contains(e)) {
+ /* Got our element */
+ domrelation->addtoset(e,domrelation->getset(rangeset),globalmodel);
+ relation->getrelation()->put(key,e);
+ return;
+ }
+ delete(e);
+ }
+ } else {
+ WorkSet *ws=domrelation->getset(s.setname)->getset();
+ Element *e=(Element *)ws->firstelement();
+ while(e!=NULL) {
+ WorkSet *wsnew=domrelation->getrelation(relationname)->getrelation()->getset(key);
+ if (wsnew==NULL||!wsnew->contains(e)) {
+ /* Got our element */
+ domrelation->addtoset(e,domrelation->getset(rangeset),globalmodel);
+ relation->getrelation()->put(key,e);
+ return;
+ }
+ e=(Element *)ws->getnextelement(e);
+ }
+ printf("Error...set %s doesn't have enough elements for relation\n",setname);
+ exit(-1);
+ }
+ } else {
+ /* call functionpointer */
+ DomainSet *newset=domrelation->getset(rangeset);
+ char *type=newset->getelementtype();
+ structure *st=globalmodel->getstructure(type);
+ Element *ele=s.functionptr(st,globalmodel);
+ if (ele==NULL) {
+ printf("Error...allocation function doesn't return structure for %s\n",rangeset);
+ exit(-1);
+ }
+ domrelation->addtoset(ele,domrelation->getset(rangeset),globalmodel);
+ relation->getrelation()->put(key,ele);
+ return;
+ }
+ }
+
+
+ break;
+ case SETEXPR_INVREL: {
+ /* Set should be too small if we are doing a repair
+ We need to add 1 element */
+ Guidance *g=globalmodel->getguidance();
+ char * relationname=p->getpredicate()->getsetexpr()->getrelation()->getname();
+ Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
+ DRelation *relation=domrelation->getrelation(relationname);
+ char *domainset=relation->getdomain();
+ Source s=g->sourceforrelation(domainset);
+ if (s.setname!=NULL) {
+ /* just pick an element from s.setname */
+ char *setname=s.setname;
+ if (equivalentstrings(s.setname,"int")) {
+ /* special case for ints*/
+ for(int i=0;;i++) {
+ Element *e=new Element(i);
+ WorkSet *wsnew=domrelation->getrelation(relationname)->getrelation()->invgetset(key);
+ if (wsnew==NULL||!wsnew->contains(e)) {
+ /* Got our element */
+ domrelation->addtoset(e,domrelation->getset(domainset),globalmodel);
+ relation->getrelation()->put(e,key);
+ return;
+ }
+ delete(e);
+ }
+ } else {
+ WorkSet *ws=domrelation->getset(s.setname)->getset();
+ Element *e=(Element *)ws->firstelement();
+ while(e!=NULL) {
+ WorkSet *wsnew=domrelation->getrelation(relationname)->getrelation()->invgetset(key);
+ if (wsnew==NULL||!wsnew->contains(e)) {
+ /* Got our element */
+ domrelation->addtoset(e,domrelation->getset(domainset),globalmodel);
+ relation->getrelation()->put(e,key);
+ return;
+ }
+ e=(Element *)ws->getnextelement(e);
+ }
+ printf("Error...set %s doesn't have enough elements for relation\n",setname);
+ exit(-1);
+ }
+ } else {
+ /* call functionpointer */
+ DomainSet *newset=domrelation->getset(domainset);
+ char *type=newset->getelementtype();
+ structure *st=globalmodel->getstructure(type);
+ Element *ele=s.functionptr(st,globalmodel);
+ if (ele==NULL) {
+ printf("Error...allocation function doesn't return structure for %s\n",domainset);
+ exit(-1);
+ }
+ domrelation->addtoset(ele,domrelation->getset(domainset),globalmodel);
+ relation->getrelation()->put(ele,key);
+ return;
+ }
+ }
+ break;
+ }
+}
+
+
+
+
+void ActionGEQ1::breakpredicate(Hashtable *env, CoercePredicate *p)
+{
+#ifdef DEBUGMESSAGES
+ printf("ActionGEQ1::breakpredicate CALLED\n");
+ p->getpredicate()->print(); printf("\n");
+#endif
+
+ switch(p->getpredicate()->getsetexpr()->gettype()) {
+ // size(S)>=1
+ case SETEXPR_LABEL:
+ {
+#ifdef DEBUGMESSAGES
+ printf("LABEL\n");
+#endif
+
+ char *setname=p->getpredicate()->getsetexpr()->getsetlabel()->getname();
+ DomainSet *ds=domrelation->getset(setname); //S
+
+ // simply delete all elements that S currently contains
+ Guidance *g=globalmodel->getguidance();
+ WorkSet *ws=ds->getset();
+ while(ws->size()>0)
+ {
+ Element *e=(Element *)ws->firstelement();
+ domrelation->delfromsetmovetoset(e,domrelation->getset(setname), globalmodel);
+ }
+ }
+ break;
+
+
+ // size(V.R)>=1
+ case SETEXPR_REL:
+ {
+#ifdef DEBUGMESSAGES
+ printf("REL\n");
+#endif
+
+ DRelation *dr=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname());
+ WorkRelation *wr=dr->getrelation(); //R
+ Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label()); //V
+ WorkSet *ws=wr->getset(key); //V.R
+
+ // simply delete all elements that V.R currently contains
+ int size=ws->size();
+ for(int i=0; i<size; i++)
+ {
+ void *objtoremove=ws->firstelement();
+ wr->remove(key, objtoremove);
+ }
+ }
+ break;
+
+ // size(R.V)=1
+ case SETEXPR_INVREL:
+ {
+#ifdef DEBUGMESSAGES
+ printf("INVREL\n");
+#endif
+
+ DRelation *dr=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname());
+ //dr->print(); printf("\n");
+ WorkRelation *wr=dr->getrelation(); //R
+ Element *key=(Element *)env->get(p->getpredicate()->getsetexpr()->getlabel()->label()); //V
+ WorkSet *ws=wr->invgetset(key); //R.V
+
+#ifdef DEBUGMESSAGES
+ printf("ws size = %d\n", ws->size());
+#endif
+
+ // simply delete all elements that R.V currently contains
+ int size=ws->size();
+ for(int i=0; i<size; i++)
+ {
+ void *objtoremove = ws->firstelement();
+ wr->remove(objtoremove, key);
+ }
+
+#ifdef DEBUGMESSAGES
+ printf("INVREL finished\n");
+#endif
+ }
+ break;
+ }
+}
+
+
+
+bool ActionGEQ1::conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2) {
+ assert(canrepairpredicate(p1));
+ Setexpr *pse=p1->getpredicate()->getsetexpr();
+ if(comparepredicates(c1,p1,c2,p2))
+ return false; /*same predicates don't conflict*/
+ char *fromname=NULL;
+ DomainSet *fromset=domrelation->getsource(domrelation->getset(pse->getsetlabel()->getname()));
+ if (fromset!=NULL)
+ fromname=fromset->getname();
+ /* FIXME: fromname should cycle through set of possibilities ...
+ if it is null, it should be replaced with the type name the object will have for the REL tests...this is okay already for the label tests...
+ */
+
+ switch(pse->gettype()) {
+ case SETEXPR_LABEL: {
+ char *boundname=NULL;
+ Guidance *g=globalmodel->getguidance();
+ DomainSet *fromset=domrelation->getsource(domrelation->getset(pse->getsetlabel()->getname()));
+
+ if (fromset!=NULL) {
+ Source s=g->sourceforsetsize(fromset->getname());
+ if (s.setname!=NULL)
+ boundname=s.setname;
+ }
+ char *setname=pse->getsetlabel()->getname();
+
+ {
+ WorkSet *ws=domrelation->conflictaddsets(pse->getsetlabel()->getname(),boundname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(pse->getsetlabel()->getname(), boundname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ return false;
+ }
+
+ case SETEXPR_REL: {
+ /* we have a in v.r */
+ /* add <v,a> to r */
+ if (p2->isrule()&&
+ (p2->getpredicate()->gettype()==PREDICATE_GTE1||
+ p2->getpredicate()->gettype()==PREDICATE_EQ1)&&
+ p2->getpredicate()->getsetexpr()->gettype()==SETEXPR_REL) {
+ return false;
+ }
+ /* Compute bounding set if there is one */
+
+
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(pse->getrelation()->getname())->getrange();
+ Guidance *g=globalmodel->getguidance();
+ Source s=g->sourceforsetsize(insertset);
+
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,s.setname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, s.setname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+
+
+ return testforconflict(getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
+ fromname,
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
+ }
+ case SETEXPR_INVREL: {
+ /* we have a in v.r */
+ /* add <a,v> to r */
+ if (p2->isrule()&&
+ (p2->getpredicate()->gettype()==PREDICATE_GTE1||
+ p2->getpredicate()->gettype()==PREDICATE_EQ1)&&
+ p2->getpredicate()->getsetexpr()->gettype()==SETEXPR_INVREL) {
+ return false;
+ }
+ /* Compute bounding set if there is one */
+
+
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(pse->getrelation()->getname())->getdomain();
+ Guidance *g=globalmodel->getguidance();
+ Source s=g->sourceforsetsize(insertset);
+
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,s.setname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, s.setname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+
+ return testforconflict(fromname,
+ getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
+ }
+ }
+}
+
+bool ActionGEQ1::canrepairpredicate(CoercePredicate *cp) {
+ if (cp->getcoercebool()==false)
+ return false;
+ Predicate *p=cp->getpredicate();
+
+ if (p->gettype()!=PREDICATE_GTE1)
+ return false;
+
+ Setexpr *se=p->getsetexpr();
+ int setexprtype=se->gettype();
+ if (setexprtype==SETEXPR_REL||
+ setexprtype==SETEXPR_INVREL) {
+ DRelation *dr=domrelation->getrelation(se->getrelation()->getname());
+ if (dr->isstatic())
+ return false; /* Can't change static domain relations */
+ }
+
+ /* Coercing set membership */
+ return true;
+}
--- /dev/null
+#ifndef ActionGEQ1_H
+#define ActionGEQ1_H
+#include "classlist.h"
+#include "Action.h"
+class ActionGEQ1:public Action {
+ public:
+ ActionGEQ1() {
+ }
+ ActionGEQ1(DomainRelation *drel, model *);
+ void repairpredicate(Hashtable *env, CoercePredicate *p);
+ void breakpredicate(Hashtable *env, CoercePredicate *p);
+ bool conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2);
+ bool canrepairpredicate(CoercePredicate *p);
+ protected:
+};
+#endif
--- /dev/null
+#include <assert.h>
+#include "ActionInSet.h"
+#include "dmodel.h"
+#include "model.h"
+#include "normalizer.h"
+#include "omodel.h"
+#include "Relation.h"
+#include "set.h"
+#include "Hashtable.h"
+#include "ActionNotInSet.h"
+
+ActionInSet::ActionInSet(DomainRelation *drel,model *m) {
+ domrelation=drel;
+ globalmodel=m;
+}
+
+void ActionInSet::repairpredicate(Hashtable *env,CoercePredicate *p) {
+ Element *ele=(Element*) env->get(p->getpredicate()->getlabel()->label());
+ switch(p->getpredicate()->getsetexpr()->gettype()) {
+ case SETEXPR_LABEL:
+ domrelation->addtoset(ele, domrelation->getset(p->getpredicate()->getsetexpr()->getsetlabel()->getname()),
+ globalmodel);
+ break;
+ case SETEXPR_REL: {
+ Element *key=(Element*) env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
+ domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname())->getrelation()->put(key,ele);
+ char *rangename=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname())->getrange();
+ if (!equivalentstrings(rangename,"int")) {
+ DomainSet *range=domrelation->getset(rangename);
+ if (!range->getset()->contains(ele))
+ domrelation->addtoset(ele,range,globalmodel);
+ }
+ }
+ break;
+ case SETEXPR_INVREL: {
+ Element *key=(Element*) env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
+ domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname())->getrelation()->put(ele,key);
+ char *domainname=domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname())->getdomain();
+ if (!equivalentstrings(domainname,"int")) {
+ DomainSet *domain=domrelation->getset(domainname);
+ if (!domain->getset()->contains(ele))
+ domrelation->addtoset(ele,domain,globalmodel);
+ }
+ }
+ break;
+ }
+}
+
+
+
+void ActionInSet::breakpredicate(Hashtable *env,CoercePredicate *p)
+{
+#ifdef DEBUGMESSAGES
+ printf("ActionInSet::breakpredicate CALLED\n");
+ p->getpredicate()->print(); printf("\n");
+#endif
+
+ ActionNotInSet *a = new ActionNotInSet(domrelation, globalmodel);
+ a->repairpredicate(env, p);
+}
+
+
+
+bool ActionInSet::conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2) {
+ assert(canrepairpredicate(p1));
+ if(comparepredicates(c1,p1,c2,p2))
+ return false; /*same predicates don't conflict*/
+ Setexpr *pse=p1->getpredicate()->getsetexpr();
+ switch(pse->gettype()) {
+ case SETEXPR_LABEL: {
+ /* Compute bounding set if there is one */
+ char *boundname=calculatebound(c1,p1->getpredicate()->getlabel());
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(pse->getsetlabel()->getname(),boundname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(pse->getsetlabel()->getname(), boundname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ return false;
+ }
+ case SETEXPR_REL: {
+
+ /* Compute bounding set if there is one */
+ char *boundname=calculatebound(c1,p1->getpredicate()->getlabel());
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(pse->getrelation()->getname())->getrange();
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,boundname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, boundname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+
+ /* we have a in v.r */
+ /* add <v,a> to r */
+ return testforconflict(getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
+ getset(c1,p1->getpredicate()->getlabel()->label()),
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
+ }
+ case SETEXPR_INVREL: {
+ /* Compute bounding set if there is one */
+ char *boundname=calculatebound(c1,p1->getpredicate()->getlabel());
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(pse->getrelation()->getname())->getdomain();
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,boundname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, boundname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* add <a,v> to r */
+ return testforconflict(getset(c1,p1->getpredicate()->getlabel()->label()),
+ getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
+ }
+ }
+}
+
+bool ActionInSet::canrepairpredicate(CoercePredicate *cp) {
+ if (cp->getcoercebool()==false)
+ return false;
+ Predicate *p=cp->getpredicate();
+ if (p==NULL)
+ return false;
+ if (p->gettype()!=PREDICATE_SET)
+ return false;
+ Setexpr *se=p->getsetexpr();
+ int setexprtype=se->gettype();
+ if (setexprtype==SETEXPR_REL||
+ setexprtype==SETEXPR_INVREL) {
+ DRelation *dr=domrelation->getrelation(se->getrelation()->getname());
+ if (dr->isstatic())
+ return false; /* Can't change static domain relations */
+ }
+
+ /* Coercing set membership */
+ return true;
+}
--- /dev/null
+#ifndef ActionInSet_H
+#define ActionInSet_H
+#include "classlist.h"
+#include "Action.h"
+class ActionInSet:public Action {
+ public:
+ ActionInSet(DomainRelation *drel,model *);
+ void repairpredicate(Hashtable *env, CoercePredicate *p);
+ void breakpredicate(Hashtable *env, CoercePredicate *p);
+ bool conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2);
+ bool canrepairpredicate(CoercePredicate *p);
+ private:
+ bool testforinvconflictwithinvsetsize(Constraint *c1,CoercePredicate *cp1, Constraint *c2,CoercePredicate *cp2);
+ bool testforinvconflictwithsetsize(Constraint *c1,CoercePredicate *cp1, Constraint *c2,CoercePredicate *cp2);
+ bool testforinvconflictwithinvrelset(Constraint *c1,CoercePredicate *cp1, Constraint *c2,CoercePredicate *cp2);
+ bool testforinvconflictwithrelset(Constraint *c1,CoercePredicate *cp1, Constraint *c2,CoercePredicate *cp2);
+ bool testforconflictwithsetsize(Constraint *c1,CoercePredicate *cp1, Constraint *c2,CoercePredicate *cp2);
+ bool testforconflictwithinvsetsize(Constraint *c1,CoercePredicate *cp1, Constraint *c2,CoercePredicate *cp2);
+ bool testforconflictwithrelset(Constraint *c1,CoercePredicate *cp1, Constraint *c2,CoercePredicate *cp2);
+ bool testforconflictwithinvrelset(Constraint *c1,CoercePredicate *cp1, Constraint *c2,CoercePredicate *cp2);
+ bool testforconflictwithvalueexpr(Constraint *c1, CoercePredicate *cp1,Constraint *c2, CoercePredicate *cp2);
+ bool testforinvconflictwithvalueexpr(Constraint *c1, CoercePredicate *cp1,Constraint *c2, CoercePredicate *cp2);
+};
+#endif
--- /dev/null
+#include <assert.h>
+#include "ActionNormal.h"
+#include "dmodel.h"
+#include "normalizer.h"
+#include "omodel.h"
+#include "Relation.h"
+#include "set.h"
+#include "Hashtable.h"
+#include "model.h"
+
+ActionNormal::ActionNormal(model *m) {
+ globalmodel=m;
+ domrelation=m->getdomainrelation();
+}
+
+void ActionNormal::repairpredicate(Hashtable *env,CoercePredicate *p) {
+ /* Don't actually repair stuff */
+}
+
+
+void ActionNormal::breakpredicate(Hashtable *env, CoercePredicate *p)
+{
+ /* Don't actually break stuff */
+}
+
+
+bool ActionNormal::conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2) {
+ if(!p1->isrule()&&
+ !p1->istuple()) {
+ /* Compute bounding set if there is one */
+ char *boundname=p1->getltype();
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(p1->getrelset(),boundname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(p1->getrelset(), boundname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ return false;
+ }
+
+ if(!p1->isrule()&&
+ p1->istuple()) {
+
+ {
+ /* Compute bounding set if there is one */
+ char *boundname=getset(c1,p1->getrtype());
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(p1->getrelset())->getrange();
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,boundname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, boundname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ }
+ /* Compute bounding set if there is one */
+ char *boundname=getset(c1,p1->getltype());
+ DomainRelation *drel=globalmodel->getdomainrelation();
+ char *insertset=drel->getrelation(p1->getrelset())->getdomain();
+
+ /* Check conflicts arrising from addition to set */
+ {
+ WorkSet *ws=domrelation->conflictaddsets(insertset,boundname,globalmodel);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ /* Check conflicts arrising from deletions from set */
+ {
+ WorkSet *ws=domrelation->conflictdelsets(insertset, boundname);
+ DomainSet *ds=(DomainSet *) ws->firstelement();
+ while (ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *) ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+
+ /* we have a in v.r */
+ /* add <v,a> to r */
+ return testforconflict(getset(c1,p1->getltype()),
+ getset(c1,p1->getrtype()),
+ p1->getrelset(),c2,p2);
+ }
+}
+
+
+bool ActionNormal::canrepairpredicate(CoercePredicate *cp) {
+ return false; /* Doesn't repair stuff */
+}
--- /dev/null
+#ifndef ActionNormal_H
+#define ActionNormal_H
+#include "classlist.h"
+#include "Action.h"
+class ActionNormal:public Action {
+ public:
+ ActionNormal(model *);
+ void repairpredicate(Hashtable *env, CoercePredicate *p);
+ void breakpredicate(Hashtable *env, CoercePredicate *p);
+ bool conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2);
+ bool canrepairpredicate(CoercePredicate *p);
+ private:
+};
+#endif
--- /dev/null
+#include <assert.h>
+#include "ActionNotInSet.h"
+#include "dmodel.h"
+#include "normalizer.h"
+#include "omodel.h"
+#include "Relation.h"
+#include "set.h"
+#include "Hashtable.h"
+#include "ActionInSet.h"
+
+ActionNotInSet::ActionNotInSet(DomainRelation *drel, model *m) {
+ domrelation=drel;
+ globalmodel=m;
+}
+
+void ActionNotInSet::repairpredicate(Hashtable *env,CoercePredicate *p) {
+ Element *ele=(Element*) env->get(p->getpredicate()->getlabel()->label());
+ switch(p->getpredicate()->getsetexpr()->gettype()) {
+ case SETEXPR_LABEL:
+ domrelation->delfromsetmovetoset(ele, domrelation->getset(p->getpredicate()->getsetexpr()->getsetlabel()->getname()),globalmodel);
+ break;
+ case SETEXPR_REL: {
+ Element *key=(Element*) env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
+ domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname())->getrelation()->remove(key,ele);
+ }
+ break;
+ case SETEXPR_INVREL: {
+ Element *key=(Element*) env->get(p->getpredicate()->getsetexpr()->getlabel()->label());
+ domrelation->getrelation(p->getpredicate()->getsetexpr()->getrelation()->getname())->getrelation()->remove(ele,key);
+ }
+ break;
+ }
+}
+
+
+
+
+void ActionNotInSet::breakpredicate(Hashtable *env, CoercePredicate *p)
+{
+#ifdef DEBUGMESSAGES
+ printf("ActionNotInSet::breakpredicate CALLED\n");
+ p->getpredicate()->print(); printf("\n");
+#endif
+
+ ActionInSet *a = new ActionInSet(domrelation, globalmodel);
+ a->repairpredicate(env, p);
+}
+
+
+
+
+bool ActionNotInSet::conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2) {
+ assert(canrepairpredicate(p1));
+ if(comparepredicates(c1,p1,c2,p2))
+ return false; /*same predicates don't conflict*/
+ Setexpr *pse=p1->getpredicate()->getsetexpr();
+ switch(pse->gettype()) {
+ case SETEXPR_LABEL: {
+ /* Go through the sets we add something to */
+ {
+ WorkSet *ws=domrelation->removeconflictaddsets(pse->getsetlabel()->getname(),globalmodel);
+ DomainSet *ds=(DomainSet *)ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithaddtoset(ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *)ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ {
+ WorkSet *ws=domrelation->removeconflictdelsets(pse->getsetlabel()->getname());
+ DomainSet *ds=(DomainSet *)ws->firstelement();
+ while(ds!=NULL) {
+ if (conflictwithremovefromset(NULL,ds->getname(),c2,p2)) {
+ delete(ws);
+ return true;
+ }
+ ds=(DomainSet *)ws->getnextelement(ds);
+ }
+ delete(ws);
+ }
+ return false;
+
+ }
+ case SETEXPR_REL:
+ /* we have !a in v.r */
+ /* remove <v,a> to r */
+ return testforconflictremove(getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
+ getset(c1,p1->getpredicate()->getlabel()->label()),
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
+ case SETEXPR_INVREL:
+ /* we have !a in v.r */
+ /* remove <v,a> to r */
+ return testforconflictremove(getset(c1,p1->getpredicate()->getlabel()->label()),
+ getset(c1,p1->getpredicate()->getsetexpr()->getlabel()->label()),
+ p1->getpredicate()->getsetexpr()->getrelation()->getname(),c2,p2);
+ }
+}
+
+bool ActionNotInSet::canrepairpredicate(CoercePredicate *cp) {
+ if (cp->getcoercebool()==true)
+ return false;
+ Predicate *p=cp->getpredicate();
+ if (p==NULL)
+ return false;
+ if (p->gettype()!=PREDICATE_SET)
+ return false;
+ Setexpr *se=p->getsetexpr();
+ int setexprtype=se->gettype();
+ if (setexprtype==SETEXPR_REL||
+ setexprtype==SETEXPR_INVREL) {
+ DRelation *dr=domrelation->getrelation(se->getrelation()->getname());
+ if (dr->isstatic())
+ return false; /* Can't change static domain relations */
+ }
+
+ /* Coercing set membership */
+ return true;
+}
--- /dev/null
+#ifndef ActionNotInSet_H
+#define ActionNotInSet_H
+#include "classlist.h"
+#include "Action.h"
+class ActionNotInSet:public Action {
+ public:
+ ActionNotInSet(DomainRelation *drel, model *);
+ void repairpredicate(Hashtable *env, CoercePredicate *p);
+ void breakpredicate(Hashtable *env, CoercePredicate *p);
+ bool conflict(Constraint *c1, CoercePredicate *p1,Constraint *c2, CoercePredicate *p2);
+ bool canrepairpredicate(CoercePredicate *p);
+ private:
+};
+#endif
--- /dev/null
+// for CIV
+
+#include <stdlib.h>
+#include "DefaultGuidance.h"
+#include "model.h"
+#include "dmodel.h"
+#include "tmodel.h"
+#include "element.h"
+#include "common.h"
+ /* This class tells the analysis stuff */
+ /* For each set:
+ 1. Source for atoms if the set is too small - can be another set or function call (assumed to be no set)
+ 2. Source for atoms if relation requires atom of this set - can be another set or function call (assumed to be no set)
+ 3. Removal from set - where to insert objects from this set
+ 4. Insertion into set - which subset to put objects in */
+
+DefGuidance::DefGuidance(model *m) {
+ globalmodel=m;
+}
+
+Source DefGuidance::sourceforsetsize(char *set) {
+ if (equivalentstrings(set,"TERRAINTYPES"))
+ return Source(copystr("water"));
+ if (equivalentstrings(set,"STILE"))
+ return Source(copystr("STILE"));
+ return Source(&allocatebytes);
+}
+
+Source DefGuidance::sourceforrelation(char *set) {
+ if (equivalentstrings(set,"TERRAINTYPES"))
+ return Source(copystr("water"));
+ if (equivalentstrings(set,"STILE"))
+ return Source(copystr("STILE"));
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ if (equivalentstrings(ds->getelementtype(),"int"))
+ return Source(copystr("int"));
+ return Source(&allocatebytes);
+}
+
+char * DefGuidance::removefromset(char * set) {
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ DomainSet *ss=dr->getsuperset(ds);
+ while(ss!=NULL&&ss->gettype()==DOMAINSET_PARTITION) {
+ for(int i=0;i<ss->getnumsubsets();i++) {
+ char *name=ss->getsubset(i);
+ if (!equivalentstrings(ds->getname(),name)&&
+ !equivalentstrings(ds->getname(),name)) {
+ /* Do search */
+ ss=dr->getset(name);
+ while(ss->gettype()==DOMAINSET_PARTITION) {
+ char *name=ss->getsubset(0);
+ ss=dr->getset(name);
+ }
+ return ss->getname();
+ }
+ }
+ ds=ss;
+ ss=dr->getsuperset(ss);
+ }
+ if (ss!=NULL)
+ return ss->getname();
+ else
+ return NULL;
+}
+
+char * DefGuidance::insertiontoset(char *set) {
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ while (ds->gettype()==DOMAINSET_PARTITION) {
+ ds=dr->getset(ds->getsubset(0));
+ /* have to look for subset; */
+ }
+ return ds->getname();
+}
+
+Element * allocatebytes(structure * st, model *m) {
+ int size=st->getsize(m->getbitreader(),m,m->gethashtable());
+ Element * e=new Element(new char[size],st);
+ return e;
+}
--- /dev/null
+// for CIV
+
+#ifndef DefGuidance_h
+#define DefGuidance_h
+#include "classlist.h"
+#include "Guidance.h"
+
+class DefGuidance:public Guidance {
+ /* This class tells the analysis stuff */
+ /* For each set:
+ 1. Source for atoms if the set is too small - can be another set or function call (assumed to be no set)
+ 2. Source for atoms if relation requires atom of this set - can be another set or function call (assumed to be no set)
+ 3. Removal from set - where to insert objects from this set
+ 4. Insertion into set - which subset to put objects in
+ */
+ public:
+ DefGuidance(model *m);
+ Source sourceforsetsize(char *set);
+ Source sourceforrelation(char *set);
+ char * removefromset(char * set);
+ char * insertiontoset(char *set);
+ private:
+ model * globalmodel;
+};
+
+Element * allocatebytes(structure * st, model *m);
+#endif
--- /dev/null
+// for the File System benchmark
+
+#include <stdlib.h>
+#include "DefaultGuidance2.h"
+#include "model.h"
+#include "dmodel.h"
+#include "tmodel.h"
+#include "element.h"
+#include "common.h"
+ /* This class tells the analysis stuff */
+ /* For each set:
+ 1. Source for atoms if the set is too small - can be another set or function call (assumed to be no set)
+ 2. Source for atoms if relation requires atom of this set - can be another set or function call (assumed to be no set)
+ 3. Removal from set - where to insert objects from this set
+ 4. Insertion into set - which subset to put objects in */
+
+DefGuidance2::DefGuidance2(model *m) {
+ globalmodel=m;
+}
+
+Source DefGuidance2::sourceforsetsize(char *set) {
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ while(dr->getsuperset(ds)!=NULL)
+ ds=dr->getsuperset(ds);
+ if(equivalentstrings(ds->getname(),"Block"))
+ return Source(copystr("FreeBlock"));
+ if(equivalentstrings(ds->getname(),"Inode"))
+ return Source(copystr("FreeInode"));
+}
+
+Source DefGuidance2::sourceforrelation(char *set) {
+ return Source(set);
+}
+
+char * DefGuidance2::removefromset(char * set) {
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ if (equivalentstrings(set,"token"))
+ return NULL;
+
+ if (equivalentstrings(dr->getsuperset(ds)->getname(),"UsedBlock"))
+ return "FreeBlock";
+ if (equivalentstrings(dr->getsuperset(ds)->getname(),"UsedInode"))
+ return "FreeInode";
+
+ DomainSet *ss=dr->getsuperset(ds);
+ while(ss!=NULL&&ss->gettype()==DOMAINSET_PARTITION) {
+ for(int i=0;i<ss->getnumsubsets();i++) {
+ char *name=ss->getsubset(i);
+ if (!equivalentstrings(ds->getname(),name)&&
+ !equivalentstrings(ds->getname(),name)) {
+ /* Do search */
+ ss=dr->getset(name);
+ while(ss->gettype()==DOMAINSET_PARTITION) {
+ char *name=ss->getsubset(0);
+ ss=dr->getset(name);
+ }
+ return ss->getname();
+ }
+ }
+ ds=ss;
+ ss=dr->getsuperset(ss);
+ }
+ if (ss!=NULL)
+ return ss->getname();
+ else
+ return NULL;
+}
+
+char * DefGuidance2::insertiontoset(char *set) {
+ if (equivalentstrings(set,"token"))
+ return NULL;
+ if (equivalentstrings(set,"UsedBlock"))
+ return "FileBlock";
+ if (equivalentstrings(set,"UsedInode"))
+ return "FileInode";
+
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ while (ds->gettype()==DOMAINSET_PARTITION) {
+ ds=dr->getset(ds->getsubset(0));
+ /* have to look for subset; */
+ }
+ return ds->getname();
+}
+
+Element * allocatebytes2(structure * st, model *m) {
+ int size=st->getsize(m->getbitreader(),m,m->gethashtable());
+ Element * e=new Element(new char[size],st);
+ return e;
+}
--- /dev/null
+// for the File System benchmark
+
+#ifndef DefGuidance2_h
+#define DefGuidance2_h
+#include "classlist.h"
+#include "Guidance.h"
+
+class DefGuidance2:public Guidance {
+ /* This class tells the analysis stuff */
+ /* For each set:
+ 1. Source for atoms if the set is too small - can be another set or function call (assumed to be no set)
+ 2. Source for atoms if relation requires atom of this set - can be another set or function call (assumed to be no set)
+ 3. Removal from set - where to insert objects from this set
+ 4. Insertion into set - which subset to put objects in
+ */
+ public:
+ DefGuidance2(model *m);
+ Source sourceforsetsize(char *set);
+ Source sourceforrelation(char *set);
+ char * removefromset(char * set);
+ char * insertiontoset(char *set);
+ private:
+ model * globalmodel;
+};
+
+Element * allocatebytes2(structure * st, model *m);
+#endif
--- /dev/null
+#include <stdlib.h>
+#include "DefaultGuidance3.h"
+#include "model.h"
+#include "dmodel.h"
+#include "tmodel.h"
+#include "element.h"
+#include "common.h"
+ /* This class tells the analysis stuff */
+ /* For each set:
+ 1. Source for atoms if the set is too small - can be another set or function call (assumed to be no set)
+ 2. Source for atoms if relation requires atom of this set - can be another set or function call (assumed to be no set)
+ 3. Removal from set - where to insert objects from this set
+ 4. Insertion into set - which subset to put objects in */
+
+DefGuidance3::DefGuidance3(model *m) {
+ globalmodel=m;
+}
+
+Source DefGuidance3::sourceforsetsize(char *set) {
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ while(dr->getsuperset(ds)!=NULL)
+ ds=dr->getsuperset(ds);
+ if(equivalentstrings(ds->getname(),"blocks"))
+ return Source(copystr("freeblocks"));
+}
+
+Source DefGuidance3::sourceforrelation(char *set) {
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ while(dr->getsuperset(ds)!=NULL)
+ ds=dr->getsuperset(ds);
+ if(equivalentstrings(ds->getname(),"blocks"))
+ return Source(copystr("freeblocks"));
+ return Source(set);
+}
+
+char * DefGuidance3::removefromset(char * set) {
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ if (equivalentstrings(set,"token"))
+ return NULL;
+
+ if (equivalentstrings(dr->getsuperset(ds)->getname(),"fatblocks"))
+ return "freeblocks";
+ if (equivalentstrings(dr->getsuperset(ds)->getname(),"usedblocks"))
+ return "freeblocks";
+
+ DomainSet *ss=dr->getsuperset(ds);
+ while(ss!=NULL&&ss->gettype()==DOMAINSET_PARTITION) {
+ for(int i=0;i<ss->getnumsubsets();i++) {
+ char *name=ss->getsubset(i);
+ if (!equivalentstrings(ds->getname(),name)&&
+ !equivalentstrings(ds->getname(),name)) {
+ /* Do search */
+ ss=dr->getset(name);
+ while(ss->gettype()==DOMAINSET_PARTITION) {
+ char *name=ss->getsubset(0);
+ ss=dr->getset(name);
+ }
+ return ss->getname();
+ }
+ }
+ ds=ss;
+ ss=dr->getsuperset(ss);
+ }
+ if (ss!=NULL)
+ return ss->getname();
+ else
+ return NULL;
+}
+
+char * DefGuidance3::insertiontoset(char *set) {
+ if (equivalentstrings(set,"token"))
+ return NULL;
+
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *ds=dr->getset(set);
+ while (ds->gettype()==DOMAINSET_PARTITION) {
+ ds=dr->getset(ds->getsubset(0));
+ /* have to look for subset; */
+ }
+ return ds->getname();
+}
--- /dev/null
+#ifndef DefGuidance3_h
+#define DefGuidance3_h
+#include "classlist.h"
+#include "Guidance.h"
+
+class DefGuidance3:public Guidance {
+ /* This class tells the analysis stuff */
+ /* For each set:
+ 1. Source for atoms if the set is too small - can be another set or function call (assumed to be no set)
+ 2. Source for atoms if relation requires atom of this set - can be another set or function call (assumed to be no set)
+ 3. Removal from set - where to insert objects from this set
+ 4. Insertion into set - which subset to put objects in
+ */
+ public:
+ DefGuidance3(model *m);
+ Source sourceforsetsize(char *set);
+ Source sourceforrelation(char *set);
+ char * removefromset(char * set);
+ char * insertiontoset(char *set);
+ private:
+ model * globalmodel;
+};
+
+#endif
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <values.h>
+#include "GenericHashtable.h"
+//#include "dmalloc.h"
+
+int genputtable(struct genhashtable *ht, void * key, void * object) {
+ unsigned int bin=genhashfunction(ht,key);
+ struct genpointerlist * newptrlist=(struct genpointerlist *) new genpointerlist;
+ newptrlist->src=key;
+ newptrlist->object=object;
+ newptrlist->next=ht->bins[bin];
+ newptrlist->inext=NULL;
+ /* maintain linked list of ht entries for iteration*/
+ if (ht->last==NULL) {
+ ht->last=newptrlist;
+ ht->list=newptrlist;
+ newptrlist->iprev=NULL;
+ } else {
+ ht->last->inext=newptrlist;
+ newptrlist->iprev=ht->last;
+ ht->last=newptrlist;
+ }
+ ht->bins[bin]=newptrlist;
+ ht->counter++;
+ if(ht->counter>ht->currentsize&&ht->currentsize!=MAXINT) {
+ /* Expand hashtable */
+ long newcurrentsize=(ht->currentsize<(MAXINT/2))?ht->currentsize*2:MAXINT;
+ long oldcurrentsize=ht->currentsize;
+ struct genpointerlist **newbins=(struct genpointerlist **) new genpointerlist*[newcurrentsize];
+ struct genpointerlist **oldbins=ht->bins;
+ for(long j=0;j<newcurrentsize;j++) newbins[j]=NULL;
+ long i;
+ ht->currentsize=newcurrentsize;
+ for(i=0;i<oldcurrentsize;i++) {
+ struct genpointerlist * tmpptr=oldbins[i];
+ while(tmpptr!=NULL) {
+ int hashcode=genhashfunction(ht, tmpptr->src);
+ struct genpointerlist *nextptr=tmpptr->next;
+ tmpptr->next=newbins[hashcode];
+ newbins[hashcode]=tmpptr;
+ tmpptr=nextptr;
+ }
+ }
+ ht->bins=newbins;
+ delete[](oldbins);
+ }
+ return 1;
+}
+
+int hashsize(struct genhashtable *ht) {
+ return ht->counter;
+}
+
+void * gengettable(struct genhashtable *ht, void * key) {
+ struct genpointerlist * ptr=ht->bins[genhashfunction(ht,key)];
+ while(ptr!=NULL) {
+ if (((ht->comp_function==NULL)&&(ptr->src==key))||((ht->comp_function!=NULL)&&(*ht->comp_function)(ptr->src,key)))
+ return ptr->object;
+ ptr=ptr->next;
+ }
+ printf("XXXXXXXXX: COULDN'T FIND ENTRY FOR KEY %p\n",key);
+ return NULL;
+}
+
+void * getnext(struct genhashtable *ht, void * key) {
+ struct genpointerlist * ptr=ht->bins[genhashfunction(ht,key)];
+ while(ptr!=NULL) {
+ if (((ht->comp_function==NULL)&&(ptr->src==key))||((ht->comp_function!=NULL)&&(*ht->comp_function)(ptr->src,key)))
+ if (ptr->inext!=NULL) {
+ return ptr->inext->src;
+ } else
+ return NULL;
+ ptr=ptr->next;
+ }
+ printf("XXXXXXXXX: COULDN'T FIND ENTRY FOR KEY %p...\n Likely concurrent removal--bad user!!!\n",key);
+ return NULL;
+}
+
+int gencontains(struct genhashtable *ht, void * key) {
+ struct genpointerlist * ptr=ht->bins[genhashfunction(ht,key)];
+ //printf("In gencontains2\n");fflush(NULL);
+ while(ptr!=NULL) {
+ if (((ht->comp_function==NULL)&&(ptr->src==key))||((ht->comp_function!=NULL)&&(*ht->comp_function)(ptr->src,key)))
+ return 1;
+ ptr=ptr->next;
+ }
+ return 0;
+}
+
+
+void genfreekey(struct genhashtable *ht, void * key) {
+ struct genpointerlist * ptr=ht->bins[genhashfunction(ht,key)];
+
+ if (((ht->comp_function==NULL)&&(ptr->src==key))||((ht->comp_function!=NULL)&&(*ht->comp_function)(ptr->src,key))) {
+ ht->bins[genhashfunction(ht,key)]=ptr->next;
+
+ if (ptr==ht->last)
+ ht->last=ptr->iprev;
+
+ if (ptr==ht->list)
+ ht->list=ptr->inext;
+
+ if (ptr->iprev!=NULL)
+ ptr->iprev->inext=ptr->inext;
+ if (ptr->inext!=NULL)
+ ptr->inext->iprev=ptr->iprev;
+
+ delete(ptr);
+ ht->counter--;
+ return;
+ }
+ while(ptr->next!=NULL) {
+ if (((ht->comp_function==NULL)&&(ptr->next->src==key))||((ht->comp_function!=NULL)&&(*ht->comp_function)(ptr->next->src,key))) {
+ struct genpointerlist *tmpptr=ptr->next;
+ ptr->next=tmpptr->next;
+ if (tmpptr==ht->list)
+ ht->list=tmpptr->inext;
+ if (tmpptr==ht->last)
+ ht->last=tmpptr->iprev;
+ if (tmpptr->iprev!=NULL)
+ tmpptr->iprev->inext=tmpptr->inext;
+ if (tmpptr->inext!=NULL)
+ tmpptr->inext->iprev=tmpptr->iprev;
+ delete(tmpptr);
+ ht->counter--;
+ return;
+ }
+ ptr=ptr->next;
+ }
+ printf("XXXXXXXXX: COULDN'T FIND ENTRY FOR KEY %p\n",key);
+}
+
+unsigned int genhashfunction(struct genhashtable *ht, void * key) {
+ if (ht->hash_function==NULL)
+ return ((long unsigned int)key) % ht->currentsize;
+ else
+ return ((*ht->hash_function)(key)) % ht->currentsize;
+}
+
+struct genhashtable * genallocatehashtable(unsigned int (*hash_function)(void *),int (*comp_function)(void *, void *)) {
+ struct genhashtable *ght=(struct genhashtable *) new genhashtable;
+ struct genpointerlist **gpl=(struct genpointerlist **) new genpointerlist *[geninitialnumbins];
+ for(int i=0;i<geninitialnumbins;i++)
+ gpl[i]=NULL;
+ ght->hash_function=hash_function;
+ ght->comp_function=comp_function;
+ ght->currentsize=geninitialnumbins;
+ ght->bins=gpl;
+ ght->counter=0;
+ ght->list=NULL;
+ ght->last=NULL;
+ return ght;
+}
+
+void genfreehashtable(struct genhashtable * ht) {
+ int i;
+ for (i=0;i<ht->currentsize;i++) {
+ if (ht->bins[i]!=NULL) {
+ struct genpointerlist *genptr=ht->bins[i];
+ while(genptr!=NULL) {
+ struct genpointerlist *tmpptr=genptr->next;
+ delete(genptr);
+ genptr=tmpptr;
+ }
+ }
+ }
+ delete[](ht->bins);
+ delete(ht);
+}
+
+struct geniterator * gengetiterator(struct genhashtable *ht) {
+ struct geniterator *gi=new geniterator();
+ gi->ptr=ht->list;
+ return gi;
+}
+
+void * gennext(struct geniterator *it) {
+ struct genpointerlist *curr=it->ptr;
+ if (curr==NULL)
+ return NULL;
+ if (it->finished&&(curr->inext==NULL))
+ return NULL;
+ if (it->finished) {
+ it->ptr=curr->inext;
+ return it->ptr->src;
+ }
+ if(curr->inext!=NULL)
+ it->ptr=curr->inext;
+ else
+ it->finished=true; /* change offsetting scheme */
+ return curr->src;
+}
+
+void genfreeiterator(struct geniterator *it) {
+ delete(it);
+}
--- /dev/null
+// implements a generic hash table
+
+#ifndef GENHASHTABLE
+#define GENHASHTABLE
+#define geninitialnumbins 10
+
+struct genhashtable {
+ unsigned int (*hash_function)(void *);
+ int (*comp_function)(void *,void *);
+ struct genpointerlist ** bins;
+ long counter;
+ int currentsize;
+ struct genpointerlist *list;
+ struct genpointerlist *last;
+};
+
+
+struct genpointerlist {
+ void * src;
+ void * object;
+ struct genpointerlist * next;
+
+ struct genpointerlist * inext;
+ struct genpointerlist * iprev;
+};
+
+
+struct geniterator {
+ struct genpointerlist * ptr;
+ bool finished;
+};
+
+struct genhashtable * genallocatehashtable(unsigned int (*hash_function)(void *),int (*comp_function)(void *,void *));
+void genfreehashtable(struct genhashtable * ht);
+
+void * getnext(struct genhashtable *,void *);
+int genputtable(struct genhashtable *, void *, void *);
+void * gengettable(struct genhashtable *, void *);
+int gencontains(struct genhashtable *, void *);
+unsigned int genhashfunction(struct genhashtable *,void *);
+
+int hashsize(struct genhashtable * ht);
+void genfreekey(struct genhashtable *ht, void *);
+struct geniterator * gengetiterator(struct genhashtable *ht);
+void * gennext(struct geniterator *it);
+void genfreeiterator(struct geniterator *it);
+#endif
+
+
+
--- /dev/null
+#include <stdlib.h>
+#include "Guidance.h"
+
+Source::Source(Element * (*fptr)(structure *,model *)) {
+ functionptr=fptr;
+ setname=NULL;
+}
+
+Source::Source(char *sname) {
+ functionptr=NULL;
+ setname=sname;
+}
--- /dev/null
+#ifndef Guidance_h
+#define Guidance_h
+#include "classlist.h"
+
+class Guidance {
+ /* This class tells the analysis stuff */
+ /* For each set:
+ 1. Source for atoms if the set is too small - can be another set or function call (assumed to be no set)
+ 2. Source for atoms if relation requires atom of this set - can be another set or function call (assumed to be no set)
+ 3. Removal from set - where to insert objects from this set
+ 4. Insertion into set - which subset to put objects in
+ */
+ public:
+ virtual Source sourceforsetsize(char *set)=0;
+ virtual Source sourceforrelation(char *set)=0;
+ virtual char * removefromset(char * set)=0;
+ virtual char * insertiontoset(char *set)=0;
+};
+
+
+class Source {
+ public:
+ Source(Element * (*fptr)(structure *, model *));
+ Source(char *sname);
+
+ Element * (*functionptr)(structure *,model *);
+ char * setname;
+};
+
+#endif
--- /dev/null
+#include <stdlib.h>
+#include "Hashtable.h"
+#include "element.h"
+
+Hashtable::Hashtable() {
+ forward=genallocatehashtable((unsigned int (*)(void *)) & hashelement,(int (*)(void *,void *)) & elementequals);
+ parent=NULL;
+}
+
+void Hashtable::setparent(Hashtable *parent) {
+ this->parent=parent;
+}
+
+Hashtable::Hashtable(unsigned int (*hash_function)(void *),int (*comp_function)(void *, void *)) {
+ forward=genallocatehashtable(hash_function,comp_function);
+ parent=NULL;
+}
+
+void Hashtable::put(void *key, void*object) {
+ if (contains(key))
+ remove(key);
+ genputtable(forward,key,object);
+}
+
+void Hashtable::remove(void *key) {
+ genfreekey(forward,key);
+}
+
+void* Hashtable::get(void *key) {
+ if (!gencontains(forward,key)) {
+ if (parent!=NULL)
+ return parent->get(key);
+ else
+ return NULL;
+ } else
+ return gengettable(forward,key);
+}
+
+bool Hashtable::contains(void *key) {
+ if (!gencontains(forward,key)) {
+ if (parent==NULL)
+ return false;
+ else
+ return parent->contains(key);
+ } else
+ return true;
+}
+
+Hashtable::~Hashtable() {
+ genfreehashtable(forward);
+}
--- /dev/null
+#ifndef Hashtable_H
+#define Hashtable_H
+
+#include "GenericHashtable.h"
+#include "classlist.h"
+
+class Hashtable {
+ public:
+ Hashtable();
+ Hashtable(unsigned int (*hash_function)(void *),int (*comp_function)(void *, void *));
+ ~Hashtable();
+ void put(void *key, void*object);
+ void remove(void *key);
+ void* get(void *key);
+ bool contains(void *key);
+ void setparent(Hashtable *parent);
+ private:
+ Hashtable *parent;
+ struct genhashtable *forward;
+};
+
+#endif
--- /dev/null
+# Makefile.in generated by automake 1.6.3 from Makefile.am.
+# checker/Makefile. Generated from Makefile.in by configure.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = /bin/sh
+
+srcdir = .
+top_srcdir = ..
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+
+bindir = ${exec_prefix}/bin
+sbindir = ${exec_prefix}/sbin
+libexecdir = ${exec_prefix}/libexec
+datadir = ${prefix}/share
+sysconfdir = ${prefix}/etc
+sharedstatedir = ${prefix}/com
+localstatedir = ${prefix}/var
+libdir = ${exec_prefix}/lib
+infodir = ${prefix}/info
+mandir = ${prefix}/man
+includedir = ${prefix}/include
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/freeciv
+pkglibdir = $(libdir)/freeciv
+pkgincludedir = $(includedir)/freeciv
+top_builddir = ..
+
+ACLOCAL = aclocal-1.6
+AUTOCONF = autoconf
+AUTOMAKE = automake-1.6
+AUTOHEADER = autoheader
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = s,x,x,
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias =
+host_triplet = i686-pc-linux-gnu
+
+EXEEXT =
+OBJEXT = o
+PATH_SEPARATOR = :
+AMTAR = tar
+ARFLAGS =
+AWK = gawk
+BUILD_INCLUDED_LIBINTL = no
+CATALOGS = da.gmo de.gmo en_GB.gmo es.gmo fi.gmo fr.gmo hu.gmo it.gmo ja.gmo nl.gmo no.gmo pl.gmo pt.gmo pt_BR.gmo ro.gmo ru.gmo sv.gmo
+CATOBJEXT = .gmo
+CC = gcc
+CLIENT_CFLAGS = -I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/X11R6/include -I/usr/X11R6/include
+CLIENT_LIBS = -L/usr/lib -lgdk_imlib -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm
+CPP = gcc -E
+CVS_DEPS = yes
+CXX = g++
+DATADIRNAME = share
+DEPDIR = .deps
+ESD_CFLAGS =
+ESD_CONFIG = /usr/bin/esd-config
+ESD_LIBS = -L/usr/lib -lesd -laudiofile -lm
+GDK_IMLIB_CFLAGS = -I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/X11R6/include -I/usr/X11R6/include
+GDK_IMLIB_LIBS = -L/usr/lib -lgdk_imlib -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm
+GENCAT = gencat
+GLIBC21 = yes
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_CONFIG = @GLIB_CONFIG@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GMOFILES = da.gmo de.gmo en_GB.gmo es.gmo fi.gmo fr.gmo hu.gmo it.gmo ja.gmo nl.gmo no.gmo pl.gmo pt.gmo pt_BR.gmo ro.gmo ru.gmo sv.gmo
+GMSGFMT = /usr/bin/msgfmt
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GTK_CFLAGS = -I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/X11R6/include
+GTK_CONFIG = /usr/bin/gtk-config
+GTK_LIBS = -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm
+IMLIB_CFLAGS = @IMLIB_CFLAGS@
+IMLIB_CONFIG = /usr/bin/imlib-config
+IMLIB_LIBS = @IMLIB_LIBS@
+INSTALL_STRIP_PROGRAM = ${SHELL} $(install_sh) -c -s
+INSTOBJEXT = .mo
+INTLBISON = bison
+INTLDEPS = @INTLDEPS@
+INTLLIBS =
+INTLOBJS =
+INTL_LIBTOOL_SUFFIX_PREFIX =
+LIBICONV =
+LN_S = ln -s
+MAINT = #
+MKINSTALLDIRS = ./mkinstalldirs
+MSGFMT = /usr/bin/msgfmt
+PACKAGE = freeciv
+PKG_CONFIG =
+POFILES = da.po de.po en_GB.po es.po fi.po fr.po hu.po it.po ja.po nl.po no.po pl.po pt.po pt_BR.po ro.po ru.po sv.po
+POSUB = po
+RANLIB = ranlib
+SDL_CFLAGS =
+SDL_CONFIG = no
+SDL_LIBS =
+SERVER_LIBS = -lreadline -lncurses -lm
+SOUND_CFLAGS =
+SOUND_LIBS = -L/usr/lib -lesd -laudiofile -lm
+STRIP =
+UNAME = uname
+UP = @UP@
+USE_INCLUDED_LIBINTL = no
+USE_NLS = yes
+VERSION = 1.13.0
+X_CFLAGS =
+X_EXTRA_LIBS =
+X_LIBS =
+X_PRE_LIBS =
+am__include = include
+am__quote =
+gui_sources = gui-gtk
+install_sh = /root/freeciv-1.13.0/install-sh
+noinst_LIBRARIES = libchecker.a
+
+libchecker_a_SOURCES = \
+ActionAssign.cc \
+ActionAssign.h \
+Action.cc \
+ActionEQ1.cc \
+ActionEQ1.h \
+ActionGEQ1.cc \
+ActionGEQ1.h \
+Action.h \
+ActionInSet.cc \
+ActionInSet.h \
+ActionNormal.cc \
+ActionNormal.h \
+ActionNotInSet.cc \
+ActionNotInSet.h \
+amodel.cc \
+amodel.h \
+aparser.cc \
+aparser.h \
+bitreader.cc \
+bitreader.h \
+bitwriter.cc \
+bitwriter.h \
+classlist.h \
+cmodel.cc \
+cmodel.h \
+common.c \
+common.h \
+cparser.cc \
+cparser.h \
+DefaultGuidance3.cc \
+DefaultGuidance3.h \
+DefaultGuidance2.cc \
+DefaultGuidance2.h \
+DefaultGuidance.cc \
+DefaultGuidance.h \
+dmodel.cc \
+dmodel.h \
+dparser.cc \
+dparser.h \
+element.cc \
+element.h \
+fieldcheck.cc \
+fieldcheck.h \
+file.cc \
+file.h \
+GenericHashtable.c \
+GenericHashtable.h \
+Guidance.cc \
+Guidance.h \
+Hashtable.cc \
+Hashtable.h \
+list.c \
+list.h \
+model.cc \
+model.h \
+normalizer.cc \
+normalizer.h \
+omodel.cc \
+omodel.h \
+oparser.cc \
+oparser.h \
+processabstract.cc \
+processabstract.h \
+processconcrete.cc \
+processconcrete.h \
+processobject.cc \
+processobject.h \
+Relation.cc \
+Relation.h \
+repair.cc \
+repair.h \
+set.cc \
+set.h \
+test.cc \
+test.h \
+tmodel.cc \
+tmodel.h \
+token.cc \
+token.h \
+typeparser.cc \
+typeparser.h \
+tmap.cc \
+tmap.h \
+redblack.c \
+redblack.h \
+cmemory.h
+
+subdir = checker
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+libchecker_a_AR = $(AR) cru
+libchecker_a_LIBADD =
+am_libchecker_a_OBJECTS = ActionAssign.$(OBJEXT) Action.$(OBJEXT) \
+ ActionEQ1.$(OBJEXT) ActionGEQ1.$(OBJEXT) ActionInSet.$(OBJEXT) \
+ ActionNormal.$(OBJEXT) ActionNotInSet.$(OBJEXT) \
+ amodel.$(OBJEXT) aparser.$(OBJEXT) bitreader.$(OBJEXT) \
+ bitwriter.$(OBJEXT) cmodel.$(OBJEXT) common.$(OBJEXT) \
+ cparser.$(OBJEXT) DefaultGuidance3.$(OBJEXT) \
+ DefaultGuidance2.$(OBJEXT) DefaultGuidance.$(OBJEXT) \
+ dmodel.$(OBJEXT) dparser.$(OBJEXT) element.$(OBJEXT) \
+ fieldcheck.$(OBJEXT) file.$(OBJEXT) GenericHashtable.$(OBJEXT) \
+ Guidance.$(OBJEXT) Hashtable.$(OBJEXT) list.$(OBJEXT) \
+ model.$(OBJEXT) normalizer.$(OBJEXT) omodel.$(OBJEXT) \
+ oparser.$(OBJEXT) processabstract.$(OBJEXT) \
+ processconcrete.$(OBJEXT) processobject.$(OBJEXT) \
+ Relation.$(OBJEXT) repair.$(OBJEXT) set.$(OBJEXT) \
+ test.$(OBJEXT) tmodel.$(OBJEXT) token.$(OBJEXT) \
+ typeparser.$(OBJEXT) tmap.$(OBJEXT) redblack.$(OBJEXT)
+libchecker_a_OBJECTS = $(am_libchecker_a_OBJECTS)
+
+DEFS = -DHAVE_CONFIG_H
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+CPPFLAGS =
+LDFLAGS =
+LIBS = -lz
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+DEP_FILES = ./$(DEPDIR)/Action.Po \
+ ./$(DEPDIR)/ActionAssign.Po \
+ ./$(DEPDIR)/ActionEQ1.Po ./$(DEPDIR)/ActionGEQ1.Po \
+ ./$(DEPDIR)/ActionInSet.Po \
+ ./$(DEPDIR)/ActionNormal.Po \
+ ./$(DEPDIR)/ActionNotInSet.Po \
+ ./$(DEPDIR)/DefaultGuidance.Po \
+ ./$(DEPDIR)/DefaultGuidance2.Po \
+ ./$(DEPDIR)/DefaultGuidance3.Po \
+ ./$(DEPDIR)/GenericHashtable.Po \
+ ./$(DEPDIR)/Guidance.Po ./$(DEPDIR)/Hashtable.Po \
+ ./$(DEPDIR)/Relation.Po ./$(DEPDIR)/amodel.Po \
+ ./$(DEPDIR)/aparser.Po ./$(DEPDIR)/bitreader.Po \
+ ./$(DEPDIR)/bitwriter.Po ./$(DEPDIR)/cmodel.Po \
+ ./$(DEPDIR)/common.Po ./$(DEPDIR)/cparser.Po \
+ ./$(DEPDIR)/dmodel.Po ./$(DEPDIR)/dparser.Po \
+ ./$(DEPDIR)/element.Po ./$(DEPDIR)/fieldcheck.Po \
+ ./$(DEPDIR)/file.Po ./$(DEPDIR)/list.Po \
+ ./$(DEPDIR)/model.Po ./$(DEPDIR)/normalizer.Po \
+ ./$(DEPDIR)/omodel.Po ./$(DEPDIR)/oparser.Po \
+ ./$(DEPDIR)/processabstract.Po \
+ ./$(DEPDIR)/processconcrete.Po \
+ ./$(DEPDIR)/processobject.Po \
+ ./$(DEPDIR)/redblack.Po ./$(DEPDIR)/repair.Po \
+ ./$(DEPDIR)/set.Po ./$(DEPDIR)/test.Po \
+ ./$(DEPDIR)/tmap.Po ./$(DEPDIR)/tmodel.Po \
+ ./$(DEPDIR)/token.Po ./$(DEPDIR)/typeparser.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = -g -O2 -Wall
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+CXXFLAGS = -g -O2
+DIST_SOURCES = $(libchecker_a_SOURCES)
+DIST_COMMON = README Makefile.am Makefile.in
+SOURCES = $(libchecker_a_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .o .obj
+$(srcdir)/Makefile.in: # Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu checker/Makefile
+Makefile: # $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+AR = ar
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libchecker.a: $(libchecker_a_OBJECTS) $(libchecker_a_DEPENDENCIES)
+ -rm -f libchecker.a
+ $(libchecker_a_AR) libchecker.a $(libchecker_a_OBJECTS) $(libchecker_a_LIBADD)
+ $(RANLIB) libchecker.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/Action.Po
+include ./$(DEPDIR)/ActionAssign.Po
+include ./$(DEPDIR)/ActionEQ1.Po
+include ./$(DEPDIR)/ActionGEQ1.Po
+include ./$(DEPDIR)/ActionInSet.Po
+include ./$(DEPDIR)/ActionNormal.Po
+include ./$(DEPDIR)/ActionNotInSet.Po
+include ./$(DEPDIR)/DefaultGuidance.Po
+include ./$(DEPDIR)/DefaultGuidance2.Po
+include ./$(DEPDIR)/DefaultGuidance3.Po
+include ./$(DEPDIR)/GenericHashtable.Po
+include ./$(DEPDIR)/Guidance.Po
+include ./$(DEPDIR)/Hashtable.Po
+include ./$(DEPDIR)/Relation.Po
+include ./$(DEPDIR)/amodel.Po
+include ./$(DEPDIR)/aparser.Po
+include ./$(DEPDIR)/bitreader.Po
+include ./$(DEPDIR)/bitwriter.Po
+include ./$(DEPDIR)/cmodel.Po
+include ./$(DEPDIR)/common.Po
+include ./$(DEPDIR)/cparser.Po
+include ./$(DEPDIR)/dmodel.Po
+include ./$(DEPDIR)/dparser.Po
+include ./$(DEPDIR)/element.Po
+include ./$(DEPDIR)/fieldcheck.Po
+include ./$(DEPDIR)/file.Po
+include ./$(DEPDIR)/list.Po
+include ./$(DEPDIR)/model.Po
+include ./$(DEPDIR)/normalizer.Po
+include ./$(DEPDIR)/omodel.Po
+include ./$(DEPDIR)/oparser.Po
+include ./$(DEPDIR)/processabstract.Po
+include ./$(DEPDIR)/processconcrete.Po
+include ./$(DEPDIR)/processobject.Po
+include ./$(DEPDIR)/redblack.Po
+include ./$(DEPDIR)/repair.Po
+include ./$(DEPDIR)/set.Po
+include ./$(DEPDIR)/test.Po
+include ./$(DEPDIR)/tmap.Po
+include ./$(DEPDIR)/tmodel.Po
+include ./$(DEPDIR)/token.Po
+include ./$(DEPDIR)/typeparser.Po
+
+distclean-depend:
+ -rm -rf ./$(DEPDIR)
+
+.c.o:
+ source='$<' object='$@' libtool=no \
+ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+ $(CCDEPMODE) $(depcomp) \
+ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
+
+.c.obj:
+ source='$<' object='$@' libtool=no \
+ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+ $(CCDEPMODE) $(depcomp) \
+ $(COMPILE) -c `cygpath -w $<`
+CCDEPMODE = depmode=gcc3
+
+.cc.o:
+ source='$<' object='$@' libtool=no \
+ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+ $(CXXDEPMODE) $(depcomp) \
+ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+.cc.obj:
+ source='$<' object='$@' libtool=no \
+ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' \
+ $(CXXDEPMODE) $(depcomp) \
+ $(CXXCOMPILE) -c -o $@ `cygpath -w $<`
+CXXDEPMODE = depmode=gcc3
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @list='$(DISTFILES)'; for file in $$list; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+uninstall-am: uninstall-info-am
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES distclean distclean-compile \
+ distclean-depend distclean-generic distclean-tags distdir dvi \
+ dvi-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic tags uninstall uninstall-am \
+ uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+noinst_LIBRARIES = libchecker.a
+
+libchecker_a_SOURCES =ActionAssign.cc bitreader.h DefaultGuidance.h model.cc repair.h\
+ActionAssign.h bitwriter.cc dmodel.cc model.h rparser.cc\
+Action.cc bitwriter.h dmodel.h normalizer.cc rparser.h\
+ActionEQ1.cc catcherror.c dparser.cc normalizer.h set.cc\
+ActionEQ1.h catcherror.h dparser.h omodel.cc set.h\
+ActionGEQ1.cc classlist.h element.cc omodel.h SimpleHash.cc\
+ActionGEQ1.h cmemory.h element.h oparser.cc SimpleHash.h\
+Action.h cmodel.cc fieldcheck.cc oparser.h stack.c\
+ActionInSet.cc cmodel.h fieldcheck.h processabstract.cc stack.h\
+ActionInSet.h common.cc processabstract.h test.cc\
+ActionNormal.cc common.h file.h processconcrete.cc test.h\
+ActionNormal.h cparser.cc GenericHashtable.cc processconcrete.h tmap.cc\
+ActionNotInSet.cc cparser.h GenericHashtable.h processobject.cc tmap.h\
+ActionNotInSet.h Guidance.cc processobject.h tmodel.cc\
+amodel.cc DefaultGuidance2.cc Guidance.h redblack.c tmodel.h\
+amodel.h DefaultGuidance2.h Hashtable.cc redblack.h token.cc\
+aparser.cc DefaultGuidance3.cc Hashtable.h Relation.cc token.h\
+aparser.h DefaultGuidance3.h list.cc Relation.h typeparser.cc\
+bitreader.cc DefaultGuidance.cc list.h repair.cc typeparser.h
--- /dev/null
+# Makefile.in generated by automake 1.6.3 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+AMTAR = @AMTAR@
+ARFLAGS = @ARFLAGS@
+AWK = @AWK@
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CLIENT_CFLAGS = @CLIENT_CFLAGS@
+CLIENT_LIBS = @CLIENT_LIBS@
+CPP = @CPP@
+CVS_DEPS = @CVS_DEPS@
+CXX = @CXX@
+DATADIRNAME = @DATADIRNAME@
+DEPDIR = @DEPDIR@
+ESD_CFLAGS = @ESD_CFLAGS@
+ESD_CONFIG = @ESD_CONFIG@
+ESD_LIBS = @ESD_LIBS@
+GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@
+GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@
+GENCAT = @GENCAT@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_CONFIG = @GLIB_CONFIG@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GTK_CFLAGS = @GTK_CFLAGS@
+GTK_CONFIG = @GTK_CONFIG@
+GTK_LIBS = @GTK_LIBS@
+IMLIB_CFLAGS = @IMLIB_CFLAGS@
+IMLIB_CONFIG = @IMLIB_CONFIG@
+IMLIB_LIBS = @IMLIB_LIBS@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLBISON = @INTLBISON@
+INTLDEPS = @INTLDEPS@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
+LIBICONV = @LIBICONV@
+LN_S = @LN_S@
+MAINT = @MAINT@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+PACKAGE = @PACKAGE@
+PKG_CONFIG = @PKG_CONFIG@
+POFILES = @POFILES@
+POSUB = @POSUB@
+RANLIB = @RANLIB@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SERVER_LIBS = @SERVER_LIBS@
+SOUND_CFLAGS = @SOUND_CFLAGS@
+SOUND_LIBS = @SOUND_LIBS@
+STRIP = @STRIP@
+UNAME = @UNAME@
+UP = @UP@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+am__include = @am__include@
+am__quote = @am__quote@
+gui_sources = @gui_sources@
+install_sh = @install_sh@
+noinst_LIBRARIES = libchecker.a
+
+libchecker_a_SOURCES = \
+ActionAssign.cc \
+ActionAssign.h \
+Action.cc \
+ActionEQ1.cc \
+ActionEQ1.h \
+ActionGEQ1.cc \
+ActionGEQ1.h \
+Action.h \
+ActionInSet.cc \
+ActionInSet.h \
+ActionNormal.cc \
+ActionNormal.h \
+ActionNotInSet.cc \
+ActionNotInSet.h \
+amodel.cc \
+amodel.h \
+aparser.cc \
+aparser.h \
+bitreader.cc \
+bitreader.h \
+bitwriter.cc \
+bitwriter.h \
+classlist.h \
+cmodel.cc \
+cmodel.h \
+common.c \
+common.h \
+cparser.cc \
+cparser.h \
+DefaultGuidance3.cc \
+DefaultGuidance3.h \
+DefaultGuidance2.cc \
+DefaultGuidance2.h \
+DefaultGuidance.cc \
+DefaultGuidance.h \
+dmodel.cc \
+dmodel.h \
+dparser.cc \
+dparser.h \
+element.cc \
+element.h \
+fieldcheck.cc \
+fieldcheck.h \
+file.cc \
+file.h \
+GenericHashtable.c \
+GenericHashtable.h \
+Guidance.cc \
+Guidance.h \
+Hashtable.cc \
+Hashtable.h \
+list.c \
+list.h \
+model.cc \
+model.h \
+normalizer.cc \
+normalizer.h \
+omodel.cc \
+omodel.h \
+oparser.cc \
+oparser.h \
+processabstract.cc \
+processabstract.h \
+processconcrete.cc \
+processconcrete.h \
+processobject.cc \
+processobject.h \
+Relation.cc \
+Relation.h \
+repair.cc \
+repair.h \
+set.cc \
+set.h \
+test.cc \
+test.h \
+tmodel.cc \
+tmodel.h \
+token.cc \
+token.h \
+typeparser.cc \
+typeparser.h \
+tmap.cc \
+tmap.h \
+redblack.c \
+redblack.h \
+cmemory.h
+
+subdir = checker
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+libchecker_a_AR = $(AR) cru
+libchecker_a_LIBADD =
+am_libchecker_a_OBJECTS = ActionAssign.$(OBJEXT) Action.$(OBJEXT) \
+ ActionEQ1.$(OBJEXT) ActionGEQ1.$(OBJEXT) ActionInSet.$(OBJEXT) \
+ ActionNormal.$(OBJEXT) ActionNotInSet.$(OBJEXT) \
+ amodel.$(OBJEXT) aparser.$(OBJEXT) bitreader.$(OBJEXT) \
+ bitwriter.$(OBJEXT) cmodel.$(OBJEXT) common.$(OBJEXT) \
+ cparser.$(OBJEXT) DefaultGuidance3.$(OBJEXT) \
+ DefaultGuidance2.$(OBJEXT) DefaultGuidance.$(OBJEXT) \
+ dmodel.$(OBJEXT) dparser.$(OBJEXT) element.$(OBJEXT) \
+ fieldcheck.$(OBJEXT) file.$(OBJEXT) GenericHashtable.$(OBJEXT) \
+ Guidance.$(OBJEXT) Hashtable.$(OBJEXT) list.$(OBJEXT) \
+ model.$(OBJEXT) normalizer.$(OBJEXT) omodel.$(OBJEXT) \
+ oparser.$(OBJEXT) processabstract.$(OBJEXT) \
+ processconcrete.$(OBJEXT) processobject.$(OBJEXT) \
+ Relation.$(OBJEXT) repair.$(OBJEXT) set.$(OBJEXT) \
+ test.$(OBJEXT) tmodel.$(OBJEXT) token.$(OBJEXT) \
+ typeparser.$(OBJEXT) tmap.$(OBJEXT) redblack.$(OBJEXT)
+libchecker_a_OBJECTS = $(am_libchecker_a_OBJECTS)
+
+DEFS = @DEFS@
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/Action.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/ActionAssign.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/ActionEQ1.Po ./$(DEPDIR)/ActionGEQ1.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/ActionInSet.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/ActionNormal.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/ActionNotInSet.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/DefaultGuidance.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/DefaultGuidance2.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/DefaultGuidance3.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/GenericHashtable.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/Guidance.Po ./$(DEPDIR)/Hashtable.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/Relation.Po ./$(DEPDIR)/amodel.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/aparser.Po ./$(DEPDIR)/bitreader.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/bitwriter.Po ./$(DEPDIR)/cmodel.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/common.Po ./$(DEPDIR)/cparser.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/dmodel.Po ./$(DEPDIR)/dparser.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/element.Po ./$(DEPDIR)/fieldcheck.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/file.Po ./$(DEPDIR)/list.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/model.Po ./$(DEPDIR)/normalizer.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/omodel.Po ./$(DEPDIR)/oparser.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/processabstract.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/processconcrete.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/processobject.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/redblack.Po ./$(DEPDIR)/repair.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/set.Po ./$(DEPDIR)/test.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/tmap.Po ./$(DEPDIR)/tmodel.Po \
+@AMDEP_TRUE@ ./$(DEPDIR)/token.Po ./$(DEPDIR)/typeparser.Po
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CFLAGS = @CFLAGS@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+CXXFLAGS = @CXXFLAGS@
+DIST_SOURCES = $(libchecker_a_SOURCES)
+DIST_COMMON = README Makefile.am Makefile.in
+SOURCES = $(libchecker_a_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cc .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu checker/Makefile
+Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+AR = ar
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+libchecker.a: $(libchecker_a_OBJECTS) $(libchecker_a_DEPENDENCIES)
+ -rm -f libchecker.a
+ $(libchecker_a_AR) libchecker.a $(libchecker_a_OBJECTS) $(libchecker_a_LIBADD)
+ $(RANLIB) libchecker.a
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Action.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ActionAssign.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ActionEQ1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ActionGEQ1.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ActionInSet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ActionNormal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ActionNotInSet.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultGuidance.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultGuidance2.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultGuidance3.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/GenericHashtable.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Guidance.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Hashtable.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Relation.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amodel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitreader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitwriter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmodel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dmodel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/element.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fieldcheck.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/model.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/normalizer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omodel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/processabstract.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/processconcrete.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/processobject.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/redblack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repair.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/set.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tmap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tmodel.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/token.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/typeparser.Po@am__quote@
+
+distclean-depend:
+ -rm -rf ./$(DEPDIR)
+
+.c.o:
+@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
+
+.c.obj:
+@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(COMPILE) -c `cygpath -w $<`
+CCDEPMODE = @CCDEPMODE@
+
+.cc.o:
+@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+.cc.obj:
+@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ $(CXXCOMPILE) -c -o $@ `cygpath -w $<`
+CXXDEPMODE = @CXXDEPMODE@
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @list='$(DISTFILES)'; for file in $$list; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LIBRARIES)
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+uninstall-am: uninstall-info-am
+
+.PHONY: GTAGS all all-am check check-am clean clean-generic \
+ clean-noinstLIBRARIES distclean distclean-compile \
+ distclean-depend distclean-generic distclean-tags distdir dvi \
+ dvi-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic tags uninstall uninstall-am \
+ uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+#include "Relation.h"
+#include "element.h"
+#include "GenericHashtable.h"
+#include "set.h"
+#include "stdio.h"
+
+
+// class Tuple
+
+Tuple::Tuple(void *l,void *r) {
+ left=l;
+ right=r;
+}
+
+Tuple::Tuple() {
+ left=NULL;right=NULL;
+}
+
+bool Tuple::isnull() {
+ if (left==NULL&&right==NULL)
+ return true;
+ else
+ return false;
+}
+
+
+// class WorkRelation
+
+WorkRelation::WorkRelation() {
+ forward=genallocatehashtable((unsigned int (*)(void *)) & hashelement,(int (*)(void *,void *)) & elementequals);
+ inverse=genallocatehashtable((unsigned int (*)(void *)) & hashelement,(int (*)(void *,void *)) & elementequals);
+ flag=false;
+}
+
+WorkRelation::WorkRelation(bool flag) {
+ forward=genallocatehashtable(NULL,NULL);
+ inverse=genallocatehashtable(NULL,NULL);
+ this->flag=true;
+}
+
+Tuple WorkRelation::firstelement() {
+ if (forward->list==NULL)
+ return Tuple();
+ void * forwardfirst=forward->list->src;
+ WorkSet *ws=getset(forwardfirst);
+ return Tuple(forwardfirst,ws->firstelement());
+}
+
+Tuple WorkRelation::getnextelement(void *left,void *right) {
+ WorkSet *ws=getset(left);
+ if (ws->getnextelement(right)!=NULL) {
+ return Tuple(left, ws->getnextelement(right));
+ }
+ void *leftnext=getnext(forward,left);
+ if (leftnext!=NULL) {
+ return Tuple(leftnext,getset(leftnext)->firstelement());
+ } else return Tuple();
+}
+
+bool WorkRelation::contains(void *key, void*object) {
+ /*Set up forward reference*/
+ if(!gencontains(forward,key))
+ return false;
+ WorkSet *w=(WorkSet *)gengettable(forward,key);
+ return w->contains(object);
+}
+
+void WorkRelation::put(void *key, void*object) {
+ { /*Set up forward reference*/
+ if(!gencontains(forward,key)) {
+ WorkSet *w=flag?new WorkSet(true):new WorkSet();
+ genputtable(forward,key,w);
+ }
+ WorkSet *w=(WorkSet *)gengettable(forward,key);
+ w->addobject(object);
+ }
+ {/*Set up backwars reference*/
+ if(!gencontains(inverse,object)) {
+ WorkSet *w=flag?new WorkSet(true):new WorkSet();
+ genputtable(inverse,object,w);
+ }
+ WorkSet *w=(WorkSet *) gengettable(inverse,object);
+ w->addobject(key);
+ }
+}
+
+void WorkRelation::remove(void *key, void *object) {
+ { /*Set up forward reference*/
+ WorkSet *w=(WorkSet *)gengettable(forward,key);
+ w->removeobject(object);
+ if (w->isEmpty()) {
+ genfreekey(forward,key);
+ delete(w);
+ }
+ }
+ { /*Set up backwards reference*/
+ WorkSet *w=(WorkSet *)gengettable(inverse,object);
+ w->removeobject(key);
+ if (w->isEmpty()) {
+ genfreekey(inverse,object);
+ delete(w);
+ }
+ }
+}
+
+WorkSet* WorkRelation::getset(void *key) {
+ if (gencontains(forward,key))
+ return (WorkSet *) gengettable(forward,key);
+ else return NULL;
+}
+
+void* WorkRelation::getobj(void *key) {
+ WorkSet *ws=getset(key);
+ if (ws==NULL)
+ return NULL;
+ return ws->firstelement();
+}
+
+WorkSet* WorkRelation::invgetset(void *key) {
+ if (gencontains(inverse,key))
+ return (WorkSet *) gengettable(inverse,key);
+ else
+ return NULL;
+}
+
+void* WorkRelation::invgetobj(void *key) {
+ WorkSet *ws=invgetset(key);
+ if (ws==NULL)
+ return NULL;
+ return ws->firstelement();
+}
+
+WorkRelation::~WorkRelation() {
+ destroyer(forward);
+ destroyer(inverse);
+}
+
+void WorkRelation::destroyer(struct genhashtable *d) {
+ struct geniterator *it=gengetiterator(d);
+ while (true) {
+ void *key=gennext(it);
+ if (key==NULL)
+ break;
+ WorkSet *ws=(WorkSet *)gengettable(d,key);
+ delete(ws);
+ }
+ genfreeiterator(it);
+ genfreehashtable(d);
+}
+
+void WorkRelation::print()
+{
+ printf("\n");
+ Tuple tuple = firstelement();
+ while (!tuple.isnull())
+ {
+ Element *l = (Element *) tuple.left;
+ Element *r = (Element *) tuple.right;
+ printf("("); l->print(); printf(", "); r->print(); printf(")\n");
+ tuple = getnextelement(tuple.left, tuple.right);
+ }
+}
--- /dev/null
+#ifndef Relation_H
+#define Relation_h
+#include "classlist.h"
+
+class Tuple {
+ public:
+ Tuple(void *l,void *r);
+ Tuple();
+ bool isnull();
+ void *left,*right;
+};
+
+
+
+#define WRELATION_SINGDOMAIN 0x1
+#define WRELATION_MANYDOMAIN 0x2
+#define WRELATION_SINGRANGE 0x10
+#define WRELATION_MANYRANGE 0x20
+
+class WorkRelation {
+ public:
+ WorkRelation();
+ WorkRelation(bool);
+ ~WorkRelation();
+ bool contains(void *key, void *object);
+ Tuple firstelement();
+ Tuple getnextelement(void *left, void *right);
+ void put(void *key, void *object);
+ void remove(void *key, void *object);
+ WorkSet* getset(void *key);
+ void* getobj(void *key);
+ WorkSet* invgetset(void *key);
+ void* invgetobj(void *key);
+ void print();
+
+ private:
+ void destroyer(struct genhashtable *d);
+ bool flag;
+ struct genhashtable *forward, *inverse;
+};
+#endif
+
+
+
--- /dev/null
+#include "SimpleHash.h"
+
+/* LINKED HASH NODE ****************************************************/
+
+LinkedHashNode::LinkedHashNode(int key, int data, LinkedHashNode *next) {
+ this->key = key;
+ this->data = data;
+ this->next = next;
+}
+
+LinkedHashNode::LinkedHashNode() {
+ this->key = -1;
+ this->data = -1;
+ this->next = 0;
+}
+
+/* SIMPLE LIST ****************************************************/
+
+SimpleList::SimpleList() {
+ ptr = 0;
+ head.next = 0;
+}
+
+void SimpleList::reset() {
+ ptr = &head;
+}
+
+int SimpleList::hasMoreElements() {
+ return (ptr->next == 0);
+}
+
+int SimpleList::nextElement() {
+ ptr = ptr->next;
+ return ptr->data;
+}
+
+void SimpleList::add(int data) {
+ LinkedHashNode *cur = &head;
+ while (cur->next) {
+ cur = cur->next;
+ if (cur->data == data) {
+ return; // no duplicates
+ }
+ }
+ cur->next = new LinkedHashNode(0, data, 0);
+ return;
+}
+
+int SimpleList::contains(int data) {
+ LinkedHashNode *cur = &head;
+ while (cur->next) {
+ cur = cur->next;
+ if (cur->data == data) {
+ return 1; // found!
+ }
+ }
+ return 0;
+}
+
+/* SIMPLE HASH ********************************************************/
+
+SimpleHash::SimpleHash(int size) {
+ if (size <= 0) {
+ throw SimpleHashException();
+ }
+ this->size = size;
+ this->bucket = new LinkedHashNode[size];
+ this->last = &all;
+ all.next = 0;
+ this->numparents = 0;
+ this->numelements = 0;
+}
+
+SimpleHash::SimpleHash() {
+ this->size = 100;
+ this->bucket = new LinkedHashNode[size];
+ this->last = &all;
+ all.next = 0;
+ this->numparents = 0;
+ this->numelements = 0;
+}
+
+
+SimpleHash::~SimpleHash() {
+}
+
+void SimpleHash::addParent(SimpleHash* parent) {
+ parents[numparents++] = parent;
+}
+
+int SimpleHash::add(int key, int data) {
+ unsigned int hashkey = (unsigned int)key % size;
+
+ LinkedHashNode *ptr = &bucket[hashkey];
+
+ /* check that this key/object pair isn't already here */
+ // TBD can be optimized for set v. relation */
+ while (ptr->next) {
+ ptr = ptr->next;
+ if (ptr->key == key && ptr->data == data) {
+ return 0;
+ }
+ }
+
+ ptr->next = new LinkedHashNode(key, data, 0);
+ last = last->next = new LinkedHashNode(key, data, 0);
+ numelements++;
+
+ for (int i = 0; i < numparents; i++) {
+ parents[i]->add(key, data);
+ }
+
+ return key;
+}
+
+bool SimpleHash::contains(int key) {
+ unsigned int hashkey = (unsigned int)key % size;
+
+ LinkedHashNode *ptr = &bucket[hashkey];
+ while (ptr->next) {
+ ptr = ptr->next;
+ if (ptr->key == key) {
+ // we already have this object
+ // stored in the hash so just return
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SimpleHash::contains(int key, int data) {
+ unsigned int hashkey = (unsigned int)key % size;
+
+ LinkedHashNode *ptr = &bucket[hashkey];
+ while (ptr->next) {
+ ptr = ptr->next;
+ if (ptr->key == key && ptr->data == data) {
+ // we already have this object
+ // stored in the hash so just return
+ return true;
+ }
+ }
+ return false;
+}
+
+int SimpleHash::count(int key) {
+ unsigned int hashkey = (unsigned int)key % size;
+ int count = 0;
+
+ LinkedHashNode *ptr = &bucket[hashkey];
+ while (ptr->next) {
+ ptr = ptr->next;
+ if (ptr->key == key) {
+ count++;
+ }
+ }
+ return count;
+}
+
+int SimpleHash::get(int key, int&data) {
+ unsigned int hashkey = (unsigned int)key % size;
+
+ LinkedHashNode *ptr = &bucket[hashkey];
+ while (ptr->next) {
+ ptr = ptr->next;
+ if (ptr->key == key) {
+ data = ptr->data;
+ return 1; // success
+ }
+ }
+
+ return 0; // failure
+}
+
+int SimpleHash::countdata(int data) {
+ int count = 0;
+ for (int i = 0; i < size ; i++) {
+ LinkedHashNode *ptr = &bucket[i];
+ while(ptr->next) {
+ ptr = ptr->next;
+ if (ptr->data == data) {
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
+SimpleHashException::SimpleHashException() {}
--- /dev/null
+#ifndef SIMPLEHASH_H
+#define SIMPLEHASH_H
+
+/* LinkedHashNode *****************************************************/
+
+class LinkedHashNode {
+
+public:
+ LinkedHashNode *next;
+ int data;
+ int key;
+ LinkedHashNode(int key, int data, LinkedHashNode *next);
+ LinkedHashNode();
+
+};
+
+/* SimpleList *********************************************************/
+
+class SimpleList {
+private:
+ LinkedHashNode head;
+ LinkedHashNode *ptr;
+public:
+ SimpleList();
+ void add(int data);
+ int contains(int data);
+ void reset();
+ int hasMoreElements();
+ int nextElement();
+};
+
+
+/* SimpleIterator *****************************************************/
+
+class SimpleIterator {
+
+private:
+
+ LinkedHashNode *cur;
+
+public:
+
+ inline SimpleIterator(LinkedHashNode *start) {
+ cur = start;
+ }
+
+ inline int hasNext() {
+ return (int)cur->next == 0 ? 0 : 1;
+ }
+
+ inline int next() {
+ cur = cur->next;
+ return cur->data;
+ }
+
+ inline int key() {
+ return cur->key;
+ }
+
+ inline int size() {
+ int temp = 0;
+ while (cur->next) {
+ temp++;
+ cur = cur->next;
+ }
+ return temp;
+ }
+
+};
+
+/* SimpleHash *********************************************************/
+
+class SimpleHash {
+
+private:
+ int numelements;
+
+ int size;
+ LinkedHashNode *bucket;
+ LinkedHashNode all;
+ LinkedHashNode *last;
+
+ int numparents;
+ SimpleHash* parents[10];
+
+public:
+
+ SimpleHash();
+
+ SimpleHash(int size);
+
+ ~SimpleHash();
+
+ int add(int key, int data);
+
+ bool contains(int key);
+
+ bool contains(int key, int data);
+
+ int get(int key, int& data);
+
+ int countdata(int data);
+
+ void addParent(SimpleHash* parent);
+
+ inline SimpleIterator* iterator() {
+ return new SimpleIterator(&all);
+ }
+
+ inline int count() {
+ return numelements;
+ }
+
+ int count(int key);
+
+};
+
+/* SimpleHashExcepion *************************************************/
+
+class SimpleHashException {
+public:
+ SimpleHashException();
+};
+
+#endif
+
--- /dev/null
+// Defines the Model Definition Language (MDL)
+
+#include <stdio.h>
+#include "amodel.h"
+#include "omodel.h"
+
+
+// class Field
+
+Field::Field(char *s) {
+ str=s;
+}
+
+void Field::print() {
+ printf("%s",str);
+}
+
+char * Field::field() {
+ return str;
+}
+
+// class AElementexpr
+
+AElementexpr::AElementexpr(AElementexpr *l, AElementexpr *r, int op) {
+ left=l;right=r;type=op;
+}
+
+AElementexpr::AElementexpr(char *ctype, AElementexpr *l) {
+ type=AELEMENTEXPR_CAST;
+ left=l;
+ casttype=ctype;
+}
+
+AElementexpr::AElementexpr(Literal *lit) {
+ literal=lit;
+ type=AELEMENTEXPR_LIT;
+}
+
+AElementexpr::AElementexpr(Label *lab) {
+ label=lab;
+ type=AELEMENTEXPR_LABEL;
+}
+
+AElementexpr::AElementexpr(AElementexpr *l,Field *f) {
+ field=f;
+ left=l;
+ type=AELEMENTEXPR_FIELD;
+}
+
+AElementexpr::AElementexpr() {
+ type=AELEMENTEXPR_NULL;
+}
+
+AElementexpr::AElementexpr(AElementexpr *l,Field *f, AElementexpr * i) {
+ field=f;
+ left=l;
+ right=i;
+ type=AELEMENTEXPR_FIELDARRAY;
+}
+
+AElementexpr * AElementexpr::getleft() {
+ return left;
+}
+
+char * AElementexpr::getcasttype() {
+ return casttype;
+}
+
+AElementexpr * AElementexpr::getright() {
+ return right;
+}
+
+int AElementexpr::gettype() {
+ return type;
+}
+
+Label * AElementexpr::getlabel() {
+ return label;
+}
+
+Literal * AElementexpr::getliteral() {
+ return literal;
+}
+
+Field * AElementexpr::getfield() {
+ return field;
+}
+
+void AElementexpr::print() {
+ switch(type) {
+ case AELEMENTEXPR_LABEL:
+ label->print();
+ break;
+ case AELEMENTEXPR_SUB:
+ printf("(");
+ left->print();
+ printf("-");
+ right->print();
+ printf(")");
+ break;
+ case AELEMENTEXPR_ADD:
+ printf("(");
+ left->print();
+ printf("+");
+ right->print();
+ printf(")");
+ break;
+ case AELEMENTEXPR_MULT:
+ printf("(");
+ left->print();
+ printf("*");
+ right->print();
+ printf(")");
+ break;
+ case AELEMENTEXPR_DIV:
+ printf("(");
+ left->print();
+ printf("/");
+ right->print();
+ printf(")");
+ break;
+ case AELEMENTEXPR_LIT:
+ literal->print();
+ break;
+ case AELEMENTEXPR_FIELD:
+ left->print();
+ printf(".");
+ field->print();
+ break;
+ case AELEMENTEXPR_FIELDARRAY:
+ left->print();
+ printf(".");
+ field->print();
+ printf("[");
+ right->print();
+ printf("]");
+ break;
+ case AELEMENTEXPR_CAST:
+ printf("cast(%s,",casttype);
+ left->print();
+ printf(")");
+ break;
+ case AELEMENTEXPR_NULL:
+ printf("NULL");
+ break;
+ }
+}
+
+// class Type
+
+Type::Type(char *s, int n, Label** l) {
+ str=s;numlabels=n;labels=l;
+}
+
+void Type::print() {
+ printf("(%s(",str);
+ for(int i=0;i>numlabels;i++) {
+ labels[i]->print();
+ }
+ printf("))");
+}
+
+int Type::getnumlabels() {
+ return numlabels;
+}
+
+Label * Type::getlabel(int i) {
+ return labels[i];
+}
+
+// class TypeEle
+
+TypeEle::TypeEle(char *s, int n, AElementexpr** e) {
+ str=s;numexpr=n;exprs=e;
+}
+
+void TypeEle::print() {
+ printf("(%s(",str);
+ for(int i=0;i<numexpr;i++) {
+ exprs[i]->print();
+ }
+ printf("))");
+}
+
+int TypeEle::getnumexpr() {
+ return numexpr;
+}
+
+AElementexpr * TypeEle::getexpr(int i) {
+ return exprs[i];
+}
+
+// class AQuantifier
+
+AQuantifier::AQuantifier(Label *l,Type *t, Set *s) {
+ left=l;
+ tleft=t;
+ set=s;
+ type=AQUANTIFIER_SING;
+}
+
+AQuantifier::AQuantifier(Label *l,Type *tl, Label *r, Type *tr, Set *s) {
+ left=l;
+ tleft=tl;
+ right=r;
+ tright=tr;
+ set=s;
+ type=AQUANTIFIER_TUPLE;
+}
+
+AQuantifier::AQuantifier(Label *l,AElementexpr *e1, AElementexpr *e2) {
+ left=l;
+ lower=e1;upper=e2;
+ type=AQUANTIFIER_RANGE;
+}
+
+Label * AQuantifier::getleft() {
+ return left;
+}
+
+Type * AQuantifier::gettleft() {
+ return tleft;
+}
+
+Type * AQuantifier::gettright() {
+ return tright;
+}
+
+Label * AQuantifier::getright() {
+ return right;
+}
+
+Set * AQuantifier::getset() {
+ return set;
+}
+
+AElementexpr * AQuantifier::getlower() {
+ return lower;
+}
+
+AElementexpr * AQuantifier::getupper() {
+ return upper;
+}
+
+int AQuantifier::gettype() {
+ return type;
+}
+
+void AQuantifier::print() {
+ switch(type) {
+ case AQUANTIFIER_SING:
+ printf("forall ");
+ if (tleft!=NULL)
+ tleft->print();
+ left->print();
+ printf(" in ");
+ set->print();
+ break;
+ case AQUANTIFIER_TUPLE:
+ printf("forall <");
+ if (tleft!=NULL)
+ tleft->print();
+ left->print();
+ if (tright!=NULL)
+ tright->print();
+ right->print();
+ printf("> in ");
+ set->print();
+ break;
+ case AQUANTIFIER_RANGE:
+ printf("for ");
+ left->print();
+ printf("=");
+ lower->print();
+ printf(" to ");
+ upper->print();
+ break;
+ }
+}
+
+// class Statementa
+
+Statementa::Statementa(AElementexpr *l, char *vt) {
+ leftee=l;
+ validtype=vt;
+ type=STATEMENTA_VALID;
+}
+
+char * Statementa::getvalidtype() {
+ return validtype;
+}
+
+Statementa::Statementa(AElementexpr *l, Set *s) {
+ leftee=l;
+ set=s;
+ type=STATEMENTA_SET;
+}
+
+Statementa::Statementa(Statementa *l, Statementa *r, int t) {
+ left=l;
+ right=r;
+ type=t;
+}
+
+int Statementa::gettype() {
+ return type;
+}
+
+Statementa * Statementa::getleft() {
+ return left;
+}
+
+Statementa * Statementa::getright() {
+ return right;
+}
+
+AElementexpr * Statementa::getleftee() {
+ return leftee;
+}
+
+AElementexpr * Statementa::getrightee() {
+ return rightee;
+}
+
+Statementa::Statementa(Statementa *l) {
+ type=STATEMENTA_NOT;
+ left=l;
+}
+
+Statementa::Statementa() {
+ type=STATEMENTA_TRUE;
+}
+
+Statementa::Statementa(AElementexpr *l, AElementexpr *r, int t) {
+ leftee=l;
+ rightee=r;
+ type=t;
+}
+
+Set * Statementa::getset() {
+ return set;
+}
+
+void Statementa::print() {
+ printf("(");
+ switch(type) {
+ case STATEMENTA_SET:
+ leftee->print();
+ printf(" in ");
+ set->print();
+ break;
+ case STATEMENTA_OR:
+ left->print();
+ printf(" OR ");
+ right->print();
+ break;
+ case STATEMENTA_AND:
+ left->print();
+ printf(" AND ");
+ right->print();
+ break;
+ case STATEMENTA_NOT:
+ printf("!");
+ left->print();
+ break;
+ case STATEMENTA_EQUALS:
+ leftee->print();
+ printf("=");
+ rightee->print();
+ break;
+ case STATEMENTA_LT:
+ leftee->print();
+ printf("<");
+ rightee->print();
+ break;
+ case STATEMENTA_TRUE:
+ printf("true");
+ break;
+ }
+ printf(")");
+}
+
+// class Statementb
+
+TypeEle * Statementb::gettleft() {
+ return tleft;
+}
+
+TypeEle * Statementb::gettright() {
+ return tright;
+}
+
+AElementexpr * Statementb::getleft() {
+ return left;
+}
+
+AElementexpr * Statementb::getright() {
+ return right;
+}
+
+Setlabel * Statementb::getsetlabel() {
+ return setlabel;
+}
+
+Statementb::Statementb(TypeEle *tl,AElementexpr *l, Setlabel *sl) {
+ left=l;setlabel=sl;tleft=tl;
+ type=STATEMENTB_SING;
+}
+
+int Statementb::gettype() {
+ return type;
+}
+
+Statementb::Statementb(TypeEle *tl,AElementexpr *l, TypeEle *tr,AElementexpr *r, Setlabel *sl) {
+ left=l;right=r;
+ tleft=tl;tright=tr;
+ setlabel=sl;
+ type=STATEMENTB_TUPLE;
+}
+
+void Statementb::print() {
+ switch(type) {
+ case STATEMENTB_SING:
+ left->print();
+ printf(" in ");
+ setlabel->print();
+ break;
+ case STATEMENTB_TUPLE:
+ printf("<");
+ left->print();
+ printf(",");
+ right->print();
+ printf("> in ");
+ setlabel->print();
+ break;
+ }
+}
+
+// class Rule
+
+Rule::Rule() {
+ quantifiers=NULL;
+ numquantifiers=0;
+ statementa=NULL;
+ statementb=NULL;
+ delay=false;
+ staticrule=false;
+}
+
+Rule::Rule(AQuantifier **q, int nq) {
+ quantifiers=q;
+ numquantifiers=nq;
+ statementa=NULL;
+ statementb=NULL;
+ delay=false;
+ staticrule=false;
+}
+
+void Rule::setdelay() {
+ delay=true;
+}
+
+bool Rule::isdelayed() {
+ return delay;
+}
+
+bool Rule::isstatic() {
+ return staticrule;
+}
+void Rule::setstatic() {
+ staticrule=true;
+}
+
+void Rule::setstatementa(Statementa *sa) {
+ statementa=sa;
+}
+
+void Rule::setstatementb(Statementb *sb) {
+ statementb=sb;
+}
+
+Statementa * Rule::getstatementa() {
+ return statementa;
+}
+
+Statementb * Rule::getstatementb() {
+ return statementb;
+}
+
+int Rule::numquants() {
+ return numquantifiers;
+}
+
+AQuantifier* Rule::getquant(int i) {
+ return quantifiers[i];
+}
+
+void Rule::print() {
+ printf("[");
+ for(int i=0;i<numquantifiers;i++) {
+ if (i!=0)
+ printf(",");
+ quantifiers[i]->print();
+ }
+ printf("],");
+ statementa->print();
+ printf(" => ");
+ statementb->print();
+ printf("\n");
+}
--- /dev/null
+// Defines the Model Definition Language (MDL)
+
+#ifndef Abstract_H
+#define Abstract_H
+#include<unistd.h>
+#include "classlist.h"
+
+
+class Field {
+ public:
+ Field(char *s);
+ void print();
+ char * field();
+ private:
+ char *str;
+};
+
+
+
+
+
+#define AELEMENTEXPR_LABEL 1
+#define AELEMENTEXPR_SUB 2
+#define AELEMENTEXPR_ADD 3
+#define AELEMENTEXPR_MULT 4
+#define AELEMENTEXPR_LIT 5
+#define AELEMENTEXPR_FIELD 6
+#define AELEMENTEXPR_FIELDARRAY 7
+#define AELEMENTEXPR_NULL 8
+#define AELEMENTEXPR_DIV 12
+#define AELEMENTEXPR_CAST 13
+
+class AElementexpr {
+ public:
+ AElementexpr(AElementexpr *l, AElementexpr *r, int op);
+ AElementexpr(Literal *lit);
+ AElementexpr(Label *lab);
+ AElementexpr(char *ctype, AElementexpr *l);
+ AElementexpr(AElementexpr *l,Field *f);
+ AElementexpr();
+ AElementexpr(AElementexpr *l,Field *f, AElementexpr * i);
+ AElementexpr * getleft();
+ AElementexpr * getright();
+ int gettype();
+ Label * getlabel();
+ Literal * getliteral();
+ Field * getfield();
+ virtual void print();
+ char * getcasttype();
+
+ protected:
+ int type;
+ char *casttype;
+ AElementexpr *left, *right;
+ Label *label;
+ Literal *literal;
+ Field *field;
+};
+
+
+
+
+
+class Type {
+ public:
+ Type(char *s, int n, Label** l);
+ void print();
+ int getnumlabels();
+ Label * getlabel(int i);
+
+ private:
+ char *str;
+ int numlabels;
+ Label **labels;
+};
+
+
+
+
+
+class TypeEle {
+ public:
+ TypeEle(char *s, int n, AElementexpr ** e);
+ void print();
+ int getnumexpr();
+ AElementexpr * getexpr(int i);
+ private:
+ char *str;
+ int numexpr;
+ AElementexpr **exprs;
+};
+
+
+
+
+
+#define AQUANTIFIER_SING 1
+#define AQUANTIFIER_TUPLE 2
+#define AQUANTIFIER_RANGE 3
+
+class AQuantifier {
+ public:
+ AQuantifier(Label *l,Type *t, Set *s);
+ AQuantifier(Label *l,Type *tl, Label *r, Type *tr, Set *s);
+ AQuantifier(Label *l,AElementexpr *e1, AElementexpr *e2);
+ void print();
+ int gettype();
+ Label *getleft();
+ Type *gettleft();
+ Type *gettright();
+ Label *getright();
+ Set *getset();
+ AElementexpr * getlower();
+ AElementexpr * getupper();
+
+ private:
+ int type;
+ AElementexpr *lower, *upper;
+ Label *left, *right;
+ Type *tleft,*tright;
+ Set *set;
+};
+
+
+
+
+
+
+#define STATEMENTA_OR 1
+#define STATEMENTA_AND 2
+#define STATEMENTA_NOT 3
+#define STATEMENTA_EQUALS 4
+#define STATEMENTA_LT 5
+#define STATEMENTA_TRUE 6
+#define STATEMENTA_SET 7
+#define STATEMENTA_VALID 8
+
+class Statementa {
+ public:
+ Statementa(Statementa *l, Statementa *r, int t);
+ Statementa(Statementa *l);
+ Statementa();
+ Statementa(AElementexpr *l, AElementexpr *r, int t);
+ Statementa(AElementexpr *l, Set *s);
+ Statementa(AElementexpr *, char *);
+ void print();
+ int gettype();
+ Statementa * getleft();
+ Statementa * getright();
+ AElementexpr * getleftee();
+ AElementexpr * getrightee();
+ Set * getset();
+ char *getvalidtype();
+
+ private:
+ int type;
+ Set *set;
+ Statementa *left,*right;
+ AElementexpr *leftee, *rightee;
+ char *validtype;
+};
+
+
+
+
+
+
+#define STATEMENTB_SING 1
+#define STATEMENTB_TUPLE 2
+
+class Statementb {
+ public:
+ Statementb(TypeEle *tl,AElementexpr *l, Setlabel *sl);
+ Statementb(TypeEle *tl,AElementexpr *l, TypeEle *tr,AElementexpr *r, Setlabel *sl);
+ Statementb() {}
+ virtual void print();
+ int gettype();
+ AElementexpr *getleft();
+ AElementexpr *getright();
+ Setlabel *getsetlabel();
+ TypeEle * gettleft();
+ TypeEle * gettright();
+
+ protected:
+ TypeEle *tleft, *tright;
+ AElementexpr *left, *right;
+ Setlabel *setlabel;
+ int type;
+};
+
+
+
+
+
+
+class Rule {
+ public:
+ Rule();
+ Rule(AQuantifier **q, int nq);
+ void setstatementa(Statementa *sa);
+ void setstatementb(Statementb *sb);
+ void setdelay();
+ void print();
+ int numquants();
+ AQuantifier* getquant(int i);
+ Statementa *getstatementa();
+ Statementb *getstatementb();
+ bool isdelayed();
+ bool isstatic();
+ void setstatic();
+
+ private:
+ bool staticrule;
+ bool delay;
+ int numquantifiers;
+ AQuantifier **quantifiers;
+ Statementa *statementa;
+ Statementb *statementb;
+};
+
+
+#endif
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "aparser.h"
+#include "list.h"
+#include "common.h"
+#include "token.h"
+#include "amodel.h"
+#include "omodel.h"
+#include "model.h"
+
+AParser::AParser(Reader *r) {
+ reader=r;
+}
+
+Rule * AParser::parserule() {
+ Token token=reader->peakahead();
+ while(token.token_type==TOKEN_EOL) {
+ skiptoken();
+ token=reader->peakahead();
+ }
+ if (token.token_type==TOKEN_EOF)
+ return NULL;
+ bool delay=false;bool staticrule=false;
+ if (token.token_type==TOKEN_DELAY||token.token_type==TOKEN_STATIC) {
+ /* both shouldn't be allowed..doesn't make sense...*/
+ if(token.token_type==TOKEN_DELAY)
+ delay=true;
+ else
+ staticrule=true;
+ skiptoken();
+ token=reader->peakahead();
+ }
+ Rule *c;
+ /*Get Quantifiers*/
+ if (token.token_type==TOKEN_OPENBRACK) {
+ skiptoken();
+ c=parsequantifiers();
+ needtoken(TOKEN_COMMA);
+ } else c=new Rule();
+ if (delay)
+ c->setdelay();
+ if (staticrule) {
+ int count=0;
+ for(int i=0;i<c->numquants();i++) {
+ AQuantifier *aq=c->getquant(i);
+ switch(aq->gettype()) {
+ case AQUANTIFIER_SING:
+ if (count>=1)
+ error();
+ count++;
+ break;
+ case AQUANTIFIER_RANGE:
+ break;
+ default:
+ error();
+ }
+ }
+ c->setstatic();
+ }
+
+ /*Peek ahead to see if sizeof*/
+ c->setstatementa(parsestatementa(false));
+ needtoken(TOKEN_IMPLIES);
+ c->setstatementb(parsestatementb());
+ return c;
+}
+
+TypeEle * AParser::parsetypeele() {
+ Token type=reader->readnext();
+ needtoken(TOKEN_OPENPAREN);
+ List *list=new List();
+ while(true) {
+ Token token=reader->peakahead();
+ switch(token.token_type) {
+ case TOKEN_CLOSEPAREN: {
+ skiptoken();
+ AElementexpr** larray=new AElementexpr* [list->size()];
+ list->toArray((void **)larray);
+ TypeEle *t=new TypeEle(copystr(type.str),list->size(),larray);
+ delete(list);
+ return t;
+ }
+ default:
+ list->addobject(parseaelementexpr(false));
+ if (reader->peakahead().token_type!=TOKEN_CLOSEPAREN)
+ needtoken(TOKEN_COMMA);
+ break;
+ }
+ }
+}
+
+Type * AParser::parsetype() {
+ Token type=reader->readnext();
+ needtoken(TOKEN_OPENPAREN);
+ List *list=new List();
+ while(true) {
+ Token token=reader->readnext();
+ switch(token.token_type) {
+ case TOKEN_CLOSEPAREN:
+ {
+ Label** larray=new Label* [list->size()];
+ list->toArray((void **)larray);
+ Type *t=new Type(copystr(type.str),list->size(),larray);
+ delete(list);
+ return t;
+ }
+ default:
+ list->addobject(new Label(copystr(token.str)));
+ if (reader->peakahead().token_type!=TOKEN_CLOSEPAREN)
+ needtoken(TOKEN_COMMA);
+ break;
+ }
+ }
+}
+
+Statementa * AParser::parsestatementa(bool flag) {
+ Statementa * oldst=NULL;
+ AElementexpr *oldee=NULL;
+ int eeflag=-1;
+ int joinflag=-1;
+ while(true) {
+ Token token=reader->peakahead();
+ switch(token.token_type) {
+ case TOKEN_EOL:
+ error();
+ case TOKEN_OPENPAREN:
+ {
+ skiptoken();
+ Statementa *st=parsestatementa(false);
+ if (flag)
+ return st;
+ if (oldst==NULL) {
+ oldst=st;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statementa(oldst, st, STATEMENTA_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statementa(oldst, st, STATEMENTA_OR);
+ } else {
+ error();
+ }
+ joinflag=-1;
+ }
+ }
+ break;
+ case TOKEN_IMPLIES:
+ return oldst;
+ case TOKEN_CLOSEPAREN:
+ skiptoken();
+ return oldst;
+ case TOKEN_AND:
+ skiptoken();
+ if (oldst==NULL) error();
+ joinflag=TOKEN_AND;
+ break;
+ case TOKEN_OR:
+ skiptoken();
+ if (oldst==NULL) error();
+ joinflag=TOKEN_OR;
+ break;
+ case TOKEN_TRUE:
+ {
+ skiptoken();
+ Statementa *st=new Statementa();
+ if (flag)
+ return st;
+ if (oldst==NULL) {
+ oldst=st;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statementa(oldst, st, STATEMENTA_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statementa(oldst, st, STATEMENTA_OR);
+ } else {
+ error();
+ }
+ joinflag=-1;
+ }
+ }
+ break;
+ case TOKEN_NOT:
+ {
+ skiptoken();
+ Statementa * st=new Statementa(parsestatementa(true));
+ if (flag)
+ return st;
+ if (oldst==NULL) {
+ oldst=st;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statementa(oldst, st, STATEMENTA_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statementa(oldst, st, STATEMENTA_OR);
+ } else {
+ error();
+ }
+ joinflag=-1;
+ }
+ }
+ break;
+ case TOKEN_IN: {
+ skiptoken();
+ Set *s=parseset();
+ if (oldee==NULL||eeflag!=-1)
+ error();
+ Statementa * st=new Statementa(oldee,s);
+ if (flag)
+ return st;
+ oldee=NULL;
+ if (oldst==NULL) {
+ oldst=st;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statementa(oldst, st, STATEMENTA_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statementa(oldst, st, STATEMENTA_OR);
+ } else {
+ error();
+ }
+ joinflag=-1;
+ }
+ }
+ break;
+ case TOKEN_ISVALID: {
+ if (oldee!=NULL) error();
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ AElementexpr *ae=parseaelementexpr(false);
+ Token t=reader->peakahead();
+ char *type=NULL;
+ if (t.token_type==TOKEN_COMMA) {
+ skiptoken();
+ Token t2=reader->readnext();
+ type=copystr(t2.str);
+ }
+ Statementa *st=new Statementa(ae, type);
+ needtoken(TOKEN_CLOSEPAREN);
+ if (flag)
+ return st;
+ if (oldst==NULL) {
+ oldst=st;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statementa(oldst, st, STATEMENTA_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statementa(oldst, st, STATEMENTA_OR);
+ } else {
+ error();
+ }
+ joinflag=-1;
+ }
+ }
+ break;
+ case TOKEN_EQUALS:
+ skiptoken();
+ if (oldee==NULL) error();
+ eeflag=STATEMENTA_EQUALS;
+ break;
+ case TOKEN_LT:
+ skiptoken();
+ if (oldee==NULL) error();
+ eeflag=STATEMENTA_LT;
+ break;
+ default:
+ if ((oldee!=NULL) && (eeflag==-1))
+ error();
+ else if ((oldee==NULL)&&(eeflag==-1))
+ oldee=parseaelementexpr(false);
+ else {
+ /*oldee!=NULL, and joinee!=-1*/
+ Statementa * sa=new Statementa(oldee, parseaelementexpr(false), eeflag);
+ eeflag=-1;
+ oldee=NULL;
+ if (flag) return sa;
+ if (oldst==NULL) {
+ oldst=sa;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statementa(oldst, sa, STATEMENTA_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statementa(oldst, sa, STATEMENTA_OR);
+ } else {
+ error();
+ }
+ joinflag=-1;
+ }
+ }
+ break;
+ }
+ }
+}
+
+AElementexpr * AParser::checkdot(AElementexpr * incoming) {
+ Token tdot=reader->peakahead();
+ if (tdot.token_type!=TOKEN_DOT) return incoming;
+ skiptoken();
+ Token tfield=reader->readnext();
+ Token tpeak=reader->peakahead();
+ if (tpeak.token_type==TOKEN_OPENBRACK) {
+ skiptoken();
+ AElementexpr *index=parseaelementexpr(false);
+ return checkdot(new AElementexpr(incoming, new Field(copystr(tfield.str)),index));
+ } else {
+ return checkdot(new AElementexpr(incoming, new Field(copystr(tfield.str))));
+ }
+}
+
+AElementexpr * AParser::parseaelementexpr(bool isquant) {
+ AElementexpr *oldee=NULL;
+ int joinop=-1;
+ while(true) {
+ Token t=reader->peakahead();
+ switch(t.token_type) {
+ case TOKEN_LITERAL:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ Token literal=reader->readnext();
+ needtoken(TOKEN_CLOSEPAREN);
+ if (oldee==NULL)
+ oldee=new AElementexpr(new Literal(copystr(literal.str)));
+ else {
+ if (joinop!=-1) {
+ oldee=new AElementexpr(oldee,new AElementexpr(new Literal(copystr(literal.str))),joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+ case TOKEN_CAST:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ Token casttype=reader->readnext();
+ needtoken(TOKEN_COMMA);
+ AElementexpr *ee=parseaelementexpr(false);
+ AElementexpr *tee=checkdot(new AElementexpr(copystr(casttype.str),ee));
+ if (oldee==NULL)
+ oldee=tee;
+ else {
+ if (joinop!=-1) {
+ oldee=new AElementexpr(oldee,tee,joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+
+ case TOKEN_OPENPAREN:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ AElementexpr *ee=checkdot(parseaelementexpr(false));
+ if (oldee==NULL)
+ oldee=ee;
+ else {
+ if (joinop!=-1) {
+ oldee=new AElementexpr(oldee,ee,joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+ case TOKEN_CLOSEBRACK:
+ if (isquant)
+ return oldee;
+ skiptoken();
+ return oldee;
+ case TOKEN_CLOSEPAREN:
+ skiptoken();
+ return oldee;
+ case TOKEN_SUB:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=AELEMENTEXPR_SUB;
+ else
+ error();
+ break;
+ case TOKEN_ADD:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=AELEMENTEXPR_ADD;
+ else
+ error();
+ break;
+ case TOKEN_MULT:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=AELEMENTEXPR_MULT;
+ else
+ error();
+ break;
+ case TOKEN_DIV:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=AELEMENTEXPR_DIV;
+ else
+ error();
+ break;
+ case TOKEN_NULL:
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ if (oldee==NULL)
+ oldee=checkdot(new AElementexpr());
+ else {
+ if (joinop!=-1) {
+ oldee=new AElementexpr(oldee,checkdot(new AElementexpr()),joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ default:
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ if (oldee==NULL)
+ oldee=checkdot(new AElementexpr(new Label(copystr(t.str))));
+ else {
+ if (joinop!=-1) {
+ oldee=new AElementexpr(oldee,checkdot(new AElementexpr(new Label(copystr(t.str)))),joinop);
+ joinop=-1;
+ } else error();
+ }
+ }
+ }
+}
+
+Statementb * AParser::parsestatementb() {
+ Token t=reader->peakahead();
+ if (t.token_type==TOKEN_LT) {
+ skiptoken();
+ Token tpeak=reader->peakahead();
+ TypeEle *typel=NULL,*typer=NULL;
+ if (tpeak.token_type==TOKEN_OPENPAREN) {
+ skiptoken();
+ typel=parsetypeele();
+ needtoken(TOKEN_CLOSEPAREN);
+ }
+ AElementexpr *ael=parseaelementexpr(false);
+ needtoken(TOKEN_COMMA);
+ if (tpeak.token_type==TOKEN_OPENPAREN) {
+ skiptoken();
+ typer=parsetypeele();
+ needtoken(TOKEN_CLOSEPAREN);
+ }
+ AElementexpr *aer=parseaelementexpr(false);
+ needtoken(TOKEN_GT);
+ needtoken(TOKEN_IN);
+ Token setlabel=reader->readnext();
+ return new Statementb(typel,ael,typer,aer,new Setlabel(copystr(setlabel.str)));
+ }
+
+ TypeEle *type=NULL;
+ if (t.token_type==TOKEN_OPENPAREN) {
+ skiptoken();
+ type=parsetypeele();
+ needtoken(TOKEN_CLOSEPAREN);
+ }
+ AElementexpr *ae=parseaelementexpr(false);
+ needtoken(TOKEN_IN);
+ Token setlabel=reader->readnext();
+ return new Statementb(type,ae,new Setlabel(copystr(setlabel.str)));
+}
+
+void AParser::error() {
+ printf("ERROR\n");
+ reader->error();
+ exit(-1);
+}
+
+void AParser::skiptoken() {
+ reader->readnext();
+}
+
+void AParser::needtoken(int token) {
+ Token t=reader->readnext();
+ if (!(t.token_type==token)) {
+ printf("Needed token: ");
+ tokenname(token);
+ printf("\n Got token: %s ",t.str);
+ tokenname(t.token_type);
+ error();
+ }
+}
+
+Rule * AParser::parsequantifiers() {
+ bool bool_continue=true;
+ List * list=new List();
+ do {
+ Token token2=reader->readnext();
+ switch(token2.token_type) {
+ case TOKEN_CLOSEBRACK:
+ bool_continue=false;
+ break;
+ case TOKEN_FORALL:
+ list->addobject(parsequantifier());
+ break;
+ case TOKEN_FOR:
+ list->addobject(parsequantifierfor());
+ case TOKEN_COMMA:
+ break;
+ default:
+ error();
+ }
+ } while(bool_continue);
+ AQuantifier** qarray=new AQuantifier* [list->size()];
+ list->toArray((void **)qarray);
+ Rule *c=new Rule(qarray,list->size());
+ delete(list);
+ return c;
+}
+
+AQuantifier * AParser::parsequantifier() {
+ Token token=reader->peakahead();
+ if (token.token_type==TOKEN_LT) {
+ skiptoken();
+ Type *tl=NULL, *tr=NULL;
+ if (token.token_type==TOKEN_OPENPAREN) {
+ skiptoken();
+ tl=parsetype();
+ needtoken(TOKEN_CLOSEPAREN);
+ }
+ Token labell=reader->readnext();
+ needtoken(TOKEN_COMMA);
+
+ if (token.token_type==TOKEN_OPENPAREN) {
+ skiptoken();
+ tr=parsetype();
+ needtoken(TOKEN_CLOSEPAREN);
+ }
+ Token labelr=reader->readnext();
+
+ needtoken(TOKEN_GT);
+ needtoken(TOKEN_IN);
+ return new AQuantifier(new Label(copystr(labell.str)),tl,new Label(copystr(labelr.str)),tr,parseset());
+ } else {
+ Type *t=NULL;
+ if (token.token_type==TOKEN_OPENPAREN) {
+ skiptoken();
+ t=parsetype();
+ needtoken(TOKEN_CLOSEPAREN);
+ }
+ Token label=reader->readnext();
+ needtoken(TOKEN_IN);
+ return new AQuantifier(new Label(copystr(label.str)),t,parseset());
+ }
+}
+
+AQuantifier * AParser::parsequantifierfor() {
+ Token label=reader->readnext();
+ needtoken(TOKEN_EQUALS);
+ AElementexpr *lower=parseaelementexpr(false);
+ needtoken(TOKEN_TO);
+ AElementexpr *upper=parseaelementexpr(true);
+ return new AQuantifier(new Label(copystr(label.str)),lower,upper);
+}
+
+Set * AParser::parseset() {
+ Token label=reader->readnext();
+ if (label.token_type==TOKEN_OPENBRACE) {
+ bool bool_continue=true;
+ List * list=new List();
+ do {
+ Token token2=reader->readnext();
+ switch(token2.token_type) {
+ case TOKEN_CLOSEBRACE:
+ bool_continue=false;
+ break;
+ case TOKEN_COMMA:
+ break;
+ default:
+ list->addobject(new Literal(copystr(token2.str)));
+ break;
+ }
+ } while(bool_continue);
+ int size=list->size();
+ Literal** qarray=new Literal* [size];
+ list->toArray((void **)qarray);
+ delete(list);
+ return new Set(qarray,size);
+ } else
+ return new Set(new Setlabel(copystr(label.str)));
+}
+
--- /dev/null
+#ifndef AbstractParser_H
+#define AbstractParser_H
+
+#include "common.h"
+#include <iostream.h>
+#include <stdio.h>
+#include "classlist.h"
+
+class AParser {
+ public:
+ AParser(Reader *r);
+ Rule * parserule();
+ AParser() {}
+
+ protected:
+ Type * parsetype();
+ TypeEle * parsetypeele();
+ AElementexpr * checkdot(AElementexpr * incoming);
+ Rule * parsequantifiers();
+ AQuantifier * parsequantifierfor();
+ AQuantifier * parsequantifier();
+ Set * parseset();
+ Setexpr * parsesetexpr();
+ Statementa * parsestatementa(bool);
+ virtual Statementb * parsestatementb();
+ virtual AElementexpr * parseaelementexpr(bool);
+ void skiptoken();
+ void needtoken(int);
+ void error();
+ Reader *reader;
+};
+#endif
--- /dev/null
+// Interface for reading structures
+
+#include <assert.h>
+#include "bitreader.h"
+#include "element.h"
+#include "Hashtable.h"
+#include "tmodel.h"
+#include "amodel.h"
+#include "model.h"
+#include "processabstract.h"
+
+bitreader::bitreader(model *m, Hashtable *e) {
+ globalmodel=m;
+ env=e;
+}
+
+Element * bitreader::readfieldorarray(Element *element, Field * field, Element * index) {
+ assert(element->type()==ELEMENT_OBJECT);
+ // Hashtable *env=new Hashtable((int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);;
+ if (element->getobject()==NULL)
+ return NULL;
+ structure *type=element->getstructure();
+ // assert(type->getnumparams()==element->getnumparams());
+ /* build parameter mapping */
+ /* for(int i=0;i<type->getnumparams();i++) {
+ env->put(type->getparam(i)->getname(),element->paramvalue(i));
+ }*/
+ char *fieldname=field->field();
+ ttype *typeoffield=NULL;
+ AElementexpr *lindex=NULL;
+ for(int i=0;i<type->getnumlabels();i++) {
+ if (equivalentstrings(type->getlabel(i)->getname(),fieldname)) {
+ /* got label not field... */
+ typeoffield=type->getlabel(i)->gettype();
+ fieldname=type->getlabel(i)->getfield();
+ lindex=type->getlabel(i)->getindex();
+ break;
+ }
+ }
+ int offset=0;
+ int bitoffset=0;
+ for(int i=0;i<type->getnumfields();i++) {
+ if(equivalentstrings(type->getfield(i)->getname(), fieldname)) {
+ /* got fieldname */
+ if (typeoffield==NULL)
+ typeoffield=type->getfield(i)->gettype();
+ break;
+ } else {
+ offset+=type->getfield(i)->gettype()->getbytes(this,globalmodel,env);
+ }
+ }
+ if (index!=NULL||lindex!=NULL) {
+ if (lindex!=NULL)
+ index=evaluateexpr(globalmodel,lindex,env,true,true);
+ if(typeoffield->gettype()==TTYPE_BIT) {
+ offset+=(index->intvalue())/8;
+ bitoffset=(index->intvalue())%8;
+ } else {
+ if (index->intvalue()!=0) {
+ /* Don't want to force computation of basesize unless we really need to...
+ we'd like to handle the filesystem example...:) */
+ int size=typeoffield->basesize(this,globalmodel,env);
+ offset+=size*index->intvalue();
+ }
+ }
+ if (lindex!=NULL)
+ delete(index);
+ }
+ Element *ele=NULL;
+ void *addr=(void *)(((char *) element->getobject())+offset);
+ if (typeoffield->isptr())
+ addr=*((void **)addr);
+ switch(typeoffield->gettype()) {
+ case TTYPE_INT:
+ {
+ int i=*((int *) addr);
+ ele=new Element(i);
+ break;
+ }
+ case TTYPE_SHORT:
+ {
+ short i=*((short *) addr);
+ ele=new Element(i);
+ break;
+ }
+ case TTYPE_BIT:
+ {
+ char c=*((char *) addr);
+ ele=new Element((bool)((c&(1<<bitoffset))!=0));
+ break;
+ }
+ case TTYPE_BYTE:
+ {
+ char c=*((char *)addr);
+ ele=new Element(c);
+ break;
+ }
+ case TTYPE_STRUCT:
+ {
+ /* Element **earray=new Element *[typeoffield->getnumparamvalues()];
+ for(int i=0;i<typeoffield->getnumparamvalues();i++) {
+ earray[i]=evaluateexpr(this,typeoffield->getparamvalues(i),env);
+ }*/
+ ele=new Element(addr,globalmodel->getstructure(typeoffield->getname()));
+ break;
+ }
+ }
+ return ele;
+}
+
--- /dev/null
+// Interface for reading structures
+
+#ifndef BITREADER_H
+#define BITREADER_H
+#include "classlist.h"
+
+class bitreader {
+ public:
+ bitreader(model *m, Hashtable *env);
+ Element * readfieldorarray(Element *element, Field *field, Element *index);
+ private:
+ model *globalmodel;
+ Hashtable *env;
+};
+
+#endif
--- /dev/null
+// Interface for writing structures
+
+#include <assert.h>
+#include <stdio.h>
+#include "bitwriter.h"
+#include "bitreader.h"
+#include "element.h"
+#include "Hashtable.h"
+#include "tmodel.h"
+#include "amodel.h"
+#include "model.h"
+#include "processabstract.h"
+
+
+bitwriter::bitwriter(model *m, Hashtable *e) {
+ globalmodel=m;
+ bitread=new bitreader(m,e);
+ env=e;
+}
+
+void bitwriter::writefieldorarray(Element *element, Field * field, Element * index, Element *target) {
+ assert(element->type()==ELEMENT_OBJECT);
+ // DEBUG STATEMENT
+ /*
+ element->print();
+ printf(".");
+ field->print();
+ if (index!=NULL) {
+ printf("[");
+ index->print();
+ printf("]");
+ }
+ printf("=");
+ target->print();
+ printf("\n");
+ */
+ // Hashtable *env=new Hashtable((int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);;
+ structure *type=element->getstructure();
+ //assert(type->getnumparams()==element->getnumparams());
+
+ /* build parameter mapping */
+ /* for(int i=0;i<type->getnumparams();i++) {
+ env->put(type->getparam(i)->getname(),element->paramvalue(i));
+ }*/
+ char *fieldname=field->field();
+ ttype *typeoffield=NULL;
+ AElementexpr *lindex=NULL;
+ for(int i=0;i<type->getnumlabels();i++) {
+ if (equivalentstrings(type->getlabel(i)->getname(),fieldname)) {
+ /* got label not field... */
+ typeoffield=type->getlabel(i)->gettype();
+ fieldname=type->getlabel(i)->getfield();
+ lindex=type->getlabel(i)->getindex();
+ break;
+ }
+ }
+ int offset=0;
+ int bitoffset=0;
+ for(int i=0;i<type->getnumfields();i++) {
+ if(equivalentstrings(type->getfield(i)->getname(), fieldname)) {
+ /* got fieldname */
+ if (typeoffield==NULL)
+ typeoffield=type->getfield(i)->gettype();
+ break;
+ } else {
+ offset+=type->getfield(i)->gettype()->getbytes(bitread,globalmodel,env);
+ }
+ }
+ if (index!=NULL||lindex!=NULL) {
+ if (lindex!=NULL)
+ index=evaluateexpr(globalmodel,lindex,env,true,true);
+ if(typeoffield->gettype()==TTYPE_BIT) {
+ offset+=(index->intvalue())/8;
+ bitoffset=(index->intvalue())%8;
+ } else {
+ int size=typeoffield->basesize(bitread,globalmodel,env);
+ offset+=size*index->intvalue();
+ }
+ if (lindex!=NULL)
+ delete(index);
+ }
+ void *addr=(void *)(((char *) element->getobject())+offset);
+
+ if (typeoffield->isptr())
+ addr=*((void **)addr);
+ switch(typeoffield->gettype()) {
+ case TTYPE_INT:
+ {
+ *((int *) addr)=target->intvalue();
+ break;
+ }
+ case TTYPE_SHORT:
+ {
+ *((short *) addr)=target->getshortvalue();
+ break;
+ }
+ case TTYPE_BIT:
+ {
+ char c=*((char *) addr);
+ char co=c;
+ bool b=target->getboolvalue();
+ char mask=0xFF^(1<<bitoffset);
+ if (b)
+ c=(c&mask)|(1<<bitoffset);
+ else
+ c=c&mask;
+ *((char *)addr)=c;
+ /*
+ if (co!=c)
+ printf("Change: %hhd %hhd\n",co,c);
+ */
+ break;
+ }
+ case TTYPE_BYTE:
+ {
+ *((char *)addr)=target->getbytevalue();
+ break;
+ }
+ case TTYPE_STRUCT:
+ {
+ assert(typeoffield->isptr());
+ *((void **)(((char *) element->getobject())+offset))=target->getobject();
+ break;
+ }
+ }
+}
+
--- /dev/null
+// Interface for writing structures
+
+#ifndef BITWRITER_H
+#define BITWRITER_H
+#include "classlist.h"
+
+class bitwriter {
+ public:
+ bitwriter(model *m, Hashtable *env);
+ void writefieldorarray(Element *element, Field *field, Element *index, Element *);
+ private:
+ model *globalmodel;
+ bitreader * bitread;
+ Hashtable *env;
+};
+
+#endif
--- /dev/null
+#include <stdlib.h>
+#include "catcherror.h"
+
+struct StackElement * stackptr=NULL;
+
+void handler(int signal) {
+ jmp_buf *jb=(jmp_buf *)popstack(&stackptr);
+ if (jb==NULL) {
+ printf("Signal %d\n",signal);
+ exit(-1);
+ }
+ longjmp(*jb,1);
+}
+
+void installhandlers() {
+ signal(SIGSEGV,&handler);
+ signal(SIGFPE,&handler);
+}
--- /dev/null
+#ifndef CATCHERROR_H
+#define CATCHERROR_H
+
+#include "stack.h"
+#include <signal.h>
+#include <setjmp.h>
+#include <stdio.h>
+
+void handler(int signal);
+void installhandlers();
+extern struct StackElement * stackptr;
+
+#define STARTREPAIR(repair, label) \
+ jmp_buf label_save_buf; \
+ if (setjmp(label_save_buf)) { \
+ repair \
+ resetanalysis(); \
+ goto label_error; \
+ } \
+label_error:\
+ pushstack(&stackptr, &label_save_buf);
+
+
+
+
+#define ENDREPAIR(label) popstack(&stackptr);
+
+
+
+#endif
--- /dev/null
+#ifndef classlist_h
+#define classlist_h
+//#include "dmalloc.h"
+//#define REPAIR
+#define DEBUGMESSAGES
+//#define DEBUGMANYMESSAGES
+#define TOOL
+
+class TypeEle;
+class Rule;
+class AQuantifier;
+class Statementa;
+class Statementb;
+class AElementexpr;
+class Type;
+class Field;
+class AParser;
+class bitreader;
+class DomainSet;
+class DRelation;
+class DomainRelation;
+class Dparser;
+class ElementWrapper;
+class Element;
+class Hashtable;
+class List;
+class model;
+class Literal;
+class Setlabel;
+class Constraint;
+class Quantifier;
+class Statement;
+class Predicate;
+class Valueexpr;
+class Elementexpr;
+class Set;
+class Setexpr;
+class Relation;
+class Label;
+class Parser;
+class processabstract;
+class processconcrete;
+class processobject;
+class RelationSet;
+class State;
+class Tuple;
+class WorkRelation;
+class WorkSet;
+class Iterator;
+class structure;
+class ttype;
+//class tparam;
+class tlabel;
+class tfield;
+class Token;
+class Reader;
+class Typeparser;
+class NormalForm;
+class SentenceArray;
+class CoerceSentence;
+class CoercePredicate;
+class Action;
+class ActionInSet;
+class ActionNotInSet;
+class ActionGEQ1;
+class ActionEQ1;
+class ActionAssign;
+class ActionNotAssign;
+class CParser;
+class CStatementb;
+class CAElementexpr;
+class Expr;
+class Repair;
+class bitwriter;
+class Guidance;
+class Source;
+class FieldCheck;
+class FieldTuple;
+class ActionNormal;
+class typemap;
+//class RParser;
+
+extern model *exportmodel;
+#endif
--- /dev/null
+#ifndef CMEMORY_H
+#define CMEMORY_H
+#include "test.h"
+#define malloc(size) ourmalloc(size)
+#define calloc(memb,size) ourcalloc(memb,size)
+#define realloc(ptr,size) ourrealloc(ptr,size)
+#define free(size) ourfree(size)
+#endif
--- /dev/null
+#include <stdio.h>
+#include "cmodel.h"
+#include "amodel.h"
+#include "omodel.h"
+
+
+
+// class CAElementexpr
+
+CAElementexpr::CAElementexpr(CAElementexpr *index, Setexpr *se) {
+ left=index;right=NULL;type=CAELEMENTEXPR_ELEMENT;
+ setexpr=se;
+}
+
+
+CAElementexpr::CAElementexpr(CAElementexpr *l, CAElementexpr *r, int op) {
+ left=l;right=r;type=op;
+}
+
+CAElementexpr::CAElementexpr(Literal *lit) {
+ literal=lit;
+ type=CAELEMENTEXPR_LIT;
+}
+
+CAElementexpr::CAElementexpr(Label *lab) {
+ label=lab;
+ type=CAELEMENTEXPR_LABEL;
+}
+CAElementexpr::CAElementexpr() {
+ type=CAELEMENTEXPR_NULL;
+}
+
+CAElementexpr * CAElementexpr::getleft() {
+ return (CAElementexpr *) left;
+}
+
+CAElementexpr * CAElementexpr::getright() {
+ return (CAElementexpr *) right;
+}
+
+Relation * CAElementexpr::getrelation() {
+ return rrelation;
+}
+
+CAElementexpr::CAElementexpr(CAElementexpr *index, Relation *r) {
+ left=index;right=NULL;type=CAELEMENTEXPR_RELATION;
+ rrelation=r;
+}
+
+CAElementexpr::CAElementexpr(Setexpr *se) {
+ setexpr=se;
+ type=CAELEMENTEXPR_SIZEOF;
+}
+
+
+void CAElementexpr::print() {
+ switch(type) {
+ case CAELEMENTEXPR_LABEL:
+ label->print();
+ break;
+ case CAELEMENTEXPR_NULL:
+ printf("NULL");
+ break;
+ case CAELEMENTEXPR_RELATION:
+ left->print();
+ printf(".");
+ rrelation->print();
+ break;
+ case CAELEMENTEXPR_SUB:
+ left->print();
+ printf("-");
+ right->print();
+ break;
+ case CAELEMENTEXPR_ADD:
+ left->print();
+ printf("+");
+ right->print();
+ break;
+ case CAELEMENTEXPR_MULT:
+ left->print();
+ printf("*");
+ right->print();
+ break;
+ case CAELEMENTEXPR_DIV:
+ left->print();
+ printf("/");
+ right->print();
+ break;
+ case CAELEMENTEXPR_LIT:
+ literal->print();
+ break;
+ case CAELEMENTEXPR_SIZEOF:
+ printf("sizeof(");
+ setexpr->print();
+ printf(")");
+ break;
+ case CAELEMENTEXPR_ELEMENT:
+ printf("element ");
+ left->print();
+ printf(" of ");
+ setexpr->print();
+ break;
+ }
+}
+
+Setexpr * CAElementexpr::getsetexpr() {
+ return setexpr;
+}
+
+
+
+
+
+// class Expr
+
+
+Expr::Expr(Label *l) {
+ label=l;
+ type=EXPR_LABEL;
+}
+
+Expr::Expr(Expr *e, Field *f) {
+ field=f;expr=e; type=EXPR_FIELD;
+}
+
+Expr::Expr(char *ctype, Expr *e) {
+ expr=e;
+ casttype=ctype;
+ type=EXPR_CAST;
+}
+
+char * Expr::getcasttype() {
+ return casttype;
+}
+
+Expr::Expr(Expr *e, Field *f, CAElementexpr *cae) {
+ field=f;expr=e;index=cae;
+ type=EXPR_ARRAY;
+}
+
+Expr * Expr::getexpr() {
+ return expr;
+}
+
+int Expr::gettype() {
+ return type;
+}
+
+Field * Expr::getfield() {
+ return field;
+}
+
+Label * Expr::getlabel() {
+ return label;
+}
+
+CAElementexpr * Expr::getindex() {
+ return index;
+}
+
+void Expr::print() {
+ switch(type) {
+ case EXPR_LABEL:
+ label->print();
+ break;
+ case EXPR_FIELD:
+ expr->print();
+ printf(".");
+ field->print();
+ break;
+ case EXPR_CAST:
+ printf("cast(%s,",casttype);
+ expr->print();
+ printf(")");
+ break;
+ case EXPR_ARRAY:
+ expr->print();
+ printf(".");
+ field->print();
+ printf("[");
+ index->print();
+ printf("]");
+ break;
+ }
+}
+
+
+
+
+
+
+// class CStatementb
+
+void CStatementb::print() {
+ switch(type) {
+ case CSTATEMENTB_ARRAYASSIGN:
+ expr->print();
+ printf(".");
+ field->print();
+ printf("[");
+ left->print();
+ printf("]=");
+ right->print();
+ break;
+ case CSTATEMENTB_FIELDASSIGN:
+ expr->print();
+ printf(".");
+ field->print();
+ printf("=");
+ right->print();
+ break;
+ }
+}
+
+CStatementb::CStatementb(Expr *l, Field *f, CAElementexpr *rvalue) {
+ expr=l;
+ field=f;
+ right=rvalue;
+ type=CSTATEMENTB_FIELDASSIGN;
+}
+
+CStatementb::CStatementb(Expr *l, Field *f, CAElementexpr *index, CAElementexpr *rvalue) {
+ expr=l;
+ field=f;
+ left=index;
+ right=rvalue;
+ type=CSTATEMENTB_ARRAYASSIGN;
+}
+
+Expr * CStatementb::getexpr() {
+ return expr;
+}
+
+Field * CStatementb::getfield() {
+ return field;
+}
--- /dev/null
+#ifndef Cmodel_H
+#define Cmodel_H
+#include<unistd.h>
+#include "classlist.h"
+#include "amodel.h"
+
+#define CAELEMENTEXPR_LABEL 1
+#define CAELEMENTEXPR_SUB 2
+#define CAELEMENTEXPR_ADD 3
+#define CAELEMENTEXPR_MULT 4
+#define CAELEMENTEXPR_LIT 5
+#define CAELEMENTEXPR_NULL 8
+#define CAELEMENTEXPR_SIZEOF 9
+#define CAELEMENTEXPR_ELEMENT 10
+#define CAELEMENTEXPR_RELATION 11
+#define CAELEMENTEXPR_DIV 12
+class CAElementexpr:public AElementexpr {
+ public:
+ CAElementexpr(CAElementexpr *index, Setexpr *se);
+ CAElementexpr(Setexpr *se);
+ CAElementexpr(CAElementexpr *,Relation *r);
+ CAElementexpr(CAElementexpr *l, CAElementexpr *r, int op);
+ CAElementexpr(Literal *lit);
+ CAElementexpr(Label *lab);
+ CAElementexpr();
+ CAElementexpr * getleft();
+ CAElementexpr * getright();
+ Setexpr * getsetexpr();
+ void print();
+ Relation * getrelation();
+ private:
+ Relation *rrelation;
+ Setexpr *setexpr;
+};
+
+#define EXPR_LABEL 1
+#define EXPR_FIELD 2
+#define EXPR_ARRAY 3
+#define EXPR_CAST 4
+
+class Expr {
+ public:
+ Expr(Label *l);
+ Expr(Expr *, Field *);
+ Expr(Expr *, Field *, CAElementexpr *);
+ Expr(char *, Expr *);
+ int gettype();
+ Expr * getexpr();
+ Field * getfield();
+ Label * getlabel();
+ CAElementexpr * getindex();
+ void print();
+ char * getcasttype();
+
+ private:
+ int type;
+ CAElementexpr *index;
+ Expr *expr;
+ Field *field;
+ Label *label;
+ char *casttype;
+};
+
+#define CSTATEMENTB_FIELDASSIGN 3
+#define CSTATEMENTB_ARRAYASSIGN 4
+
+class CStatementb:public Statementb {
+ public:
+ void print();
+ CStatementb(Expr *l, Field *f, CAElementexpr *rvalue);
+ CStatementb(Expr *l, Field *f, CAElementexpr *index, CAElementexpr *rvalue);
+ Expr * getexpr();
+ Field * getfield();
+ protected:
+ Expr *expr;
+ Field *field;
+};
+#endif
--- /dev/null
+#include<string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "common.h"
+#include "classlist.h"
+
+char * copystr(const char *buf) {
+ int i;
+ if (buf==NULL)
+ return NULL;
+ for(i=0;;i++)
+ if (buf[i]==0) {
+ char *ptr=new char[i+1];
+ memcpy(ptr,buf,i+1);
+ return ptr;
+ }
+}
+
+
+unsigned int hashstring(char *strptr) {
+ unsigned int hashcode=0;
+ int *intptr=(int *) strptr;
+ if(intptr==NULL)
+ return 0;
+ while(1) {
+ int copy1=*intptr;
+ if((copy1&0xFF000000)&&
+ (copy1&0xFF0000)&&
+ (copy1&0xFF00)&&
+ (copy1&0xFF)) {
+ hashcode^=*intptr;
+ intptr++;
+ } else {
+ if (!copy1&0xFF000000)
+ hashcode^=copy1&0xFF000000;
+ else if (!copy1&0xFF0000)
+ hashcode^=copy1&0xFF0000;
+ else if (!copy1&0xFF00)
+ hashcode^=copy1&0xFF00;
+ else if (!copy1&0xFF)
+ hashcode^=copy1&0xFF;
+ return hashcode;
+ }
+ }
+}
+
+int equivalentstrings(char *str1, char *str2) {
+ if ((str1!=NULL)&&(str2!=NULL)) {
+ if (strcmp(str1,str2)!=0)
+ return 0;
+ else
+ return 1;
+ } else if ((str1==NULL)&&(str2==NULL))
+ return 1;
+ else return 0;
+}
+
--- /dev/null
+#ifndef COMMON_H
+#define COMMON_H
+
+char * copystr(const char *buf);
+unsigned int hashstring(char *strptr);
+int equivalentstrings(char *str1, char *str2);
+#endif
--- /dev/null
+#include "cparser.h"
+#include "token.h"
+#include "amodel.h"
+#include "omodel.h"
+#include "cmodel.h"
+#include "element.h"
+
+CParser::CParser(Reader *r) {
+ reader=r;
+}
+
+AElementexpr * CParser::parseaelementexpr(bool isquant) {
+ CAElementexpr *oldee=NULL;
+ int joinop=-1;
+ while(true) {
+ Token t=reader->peakahead();
+ switch(t.token_type) {
+ case TOKEN_LITERAL:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ Token literal=reader->readnext();
+ needtoken(TOKEN_CLOSEPAREN);
+ if (oldee==NULL)
+ oldee=new CAElementexpr(new Literal(copystr(literal.str)));
+ else {
+ if (joinop!=-1) {
+ oldee=new CAElementexpr(oldee,new CAElementexpr(new Literal(copystr(literal.str))),joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+
+ case TOKEN_OPENPAREN:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ CAElementexpr *ee=(CAElementexpr *)parseaelementexpr(false);
+ if (oldee==NULL)
+ oldee=ee;
+ else {
+ if (joinop!=-1) {
+ oldee=new CAElementexpr(oldee,ee,joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+
+ case TOKEN_CLOSEBRACK:
+ if (isquant)
+ return oldee;
+ // Otherwise fall through
+ case TOKEN_CLOSEPAREN:
+ skiptoken();
+ return checkdot(oldee);
+ break;
+ case TOKEN_SUB:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=CAELEMENTEXPR_SUB;
+ else
+ error();
+ break;
+ case TOKEN_ADD:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=CAELEMENTEXPR_ADD;
+ else
+ error();
+ break;
+ case TOKEN_SIZEOF: {
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ Setexpr *sae=parsesetexpr();
+ needtoken(TOKEN_CLOSEPAREN);
+ return new CAElementexpr(sae);
+ }
+ case TOKEN_ELEMENT: {
+ skiptoken();
+ CAElementexpr *cae=(CAElementexpr *)parseaelementexpr(false);
+ needtoken(TOKEN_OF);
+ Setexpr *sae=parsesetexpr();
+ return new CAElementexpr(cae,sae);
+ }
+ case TOKEN_OF:
+ return oldee;
+ case TOKEN_MULT:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=CAELEMENTEXPR_MULT;
+ else
+ error();
+ break;
+ case TOKEN_DIV:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=CAELEMENTEXPR_DIV;
+ else
+ error();
+ break;
+ case TOKEN_NULL:
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ if (oldee==NULL)
+ oldee=checkdot(new CAElementexpr());
+ else {
+ if (joinop!=-1) {
+ oldee=new CAElementexpr(oldee,checkdot(new CAElementexpr()),joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ default:
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ if (oldee==NULL)
+ oldee=checkdot(new CAElementexpr(new Label(copystr(t.str))));
+ else {
+ if (joinop!=-1) {
+ oldee=new CAElementexpr(oldee,checkdot(new CAElementexpr(new Label(copystr(t.str)))),joinop);
+ joinop=-1;
+ } else error();
+ }
+ }
+ }
+}
+
+CAElementexpr * CParser::checkdot(CAElementexpr * incoming) {
+ Token tdot=reader->peakahead();
+ if (tdot.token_type!=TOKEN_DOT) return incoming;
+ skiptoken();
+ Token tfield=reader->readnext();
+ Token tpeak=reader->peakahead();
+ return new CAElementexpr(incoming, new Relation(copystr(tfield.str)));
+}
+
+Setexpr * CParser::parsesetexpr() {
+ Token label=reader->readnext();
+ Token peak=reader->peakahead();
+ if (peak.token_type==TOKEN_DOT) {
+ skiptoken();
+ return new Setexpr(new Label(copystr(label.str)),false,new Relation(copystr(reader->readnext().str)));
+ } else if (peak.token_type==TOKEN_DOTINV) {
+ skiptoken();
+ return new Setexpr(new Label(copystr(label.str)),true,new Relation(copystr(reader->readnext().str)));
+ } else
+ return new Setexpr(new Setlabel(copystr(label.str)));
+}
+
+Expr * CParser::parseexpr() {
+ Expr * oldee=NULL;
+ Field *oldf=NULL;
+ CAElementexpr *oldindex=NULL;
+ bool parselside=true;
+ while(parselside) {
+ Token t=reader->readnext();
+ switch(t.token_type) {
+ case TOKEN_DOT:
+ if (oldf!=NULL) {
+ /* do shift-pack stuff */
+ if(oldindex==NULL)
+ oldee=new Expr(oldee,oldf);
+ else
+ oldee=new Expr(oldee,oldf,oldindex);
+ oldf=NULL;
+ oldindex=NULL;
+ }
+ {
+ Token name=reader->readnext();
+ oldf=new Field(copystr(name.str));
+ }
+ break;
+ case TOKEN_OPENBRACK:
+ oldindex=(CAElementexpr *)parseaelementexpr(true);
+ needtoken(TOKEN_CLOSEBRACK);
+ break;
+ case TOKEN_CAST: {
+ if(oldee!=NULL)
+ error();
+ needtoken(TOKEN_OPENPAREN);
+ Token fld=reader->readnext();
+ needtoken(TOKEN_COMMA);
+ Expr *ex=parseexpr();
+ needtoken(TOKEN_CLOSEPAREN);
+ oldee=new Expr(copystr(fld.str),ex);
+ break;
+ }
+ case TOKEN_CLOSEPAREN:
+ if (oldf!=NULL) {
+ /* do shift-pack stuff */
+ if(oldindex==NULL)
+ oldee=new Expr(oldee,oldf);
+ else
+ oldee=new Expr(oldee,oldf,oldindex);
+ oldf=NULL;
+ oldindex=NULL;
+ }
+ return oldee;
+ default:
+ if(oldee!=NULL)
+ error();
+ oldee=new Expr(new Label(copystr(t.str)));
+ }
+ }
+ return oldee;
+}
+
+Statementb * CParser::parsestatementb() {
+ Expr * oldee=NULL;
+ Field *oldf=NULL;
+ CAElementexpr *oldindex=NULL;
+ bool parselside=true;
+ while(parselside) {
+ Token t=reader->readnext();
+ switch(t.token_type) {
+ case TOKEN_DOT:
+ if (oldf!=NULL) {
+ /* do shift-pack stuff */
+ if(oldindex==NULL)
+ oldee=new Expr(oldee,oldf);
+ else
+ oldee=new Expr(oldee,oldf,oldindex);
+ oldf=NULL;
+ oldindex=NULL;
+ }
+ {
+ Token name=reader->readnext();
+ oldf=new Field(copystr(name.str));
+ }
+ break;
+ case TOKEN_OPENBRACK:
+ oldindex=(CAElementexpr *)parseaelementexpr(true);
+ needtoken(TOKEN_CLOSEBRACK);
+ break;
+ case TOKEN_CAST: {
+ if(oldee!=NULL)
+ error();
+ needtoken(TOKEN_OPENPAREN);
+ Token fld=reader->readnext();
+ needtoken(TOKEN_COMMA);
+ Expr *ex=parseexpr();
+ oldee=new Expr(copystr(fld.str),ex);
+ break;
+ }
+ case TOKEN_EQUALS:
+ parselside=false;
+ if (oldf==NULL)
+ error();
+ break;
+ default:
+ if(oldee!=NULL)
+ error();
+ oldee=new Expr(new Label(copystr(t.str)));
+ }
+ }
+ CAElementexpr *rside=(CAElementexpr *)parseaelementexpr(false);
+ if (oldindex==NULL)
+ return new CStatementb(oldee,oldf,rside);
+ else
+ return new CStatementb(oldee,oldf,oldindex,rside);
+}
--- /dev/null
+#ifndef CParser_H
+#define CParser_H
+
+#include "common.h"
+#include <iostream.h>
+#include <stdio.h>
+#include "classlist.h"
+#include "aparser.h"
+
+class CParser:public AParser {
+ public:
+ CParser(Reader *r);
+ protected:
+ Expr * parseexpr();
+ AElementexpr * parseaelementexpr(bool);
+ CAElementexpr * checkdot(CAElementexpr * incoming);
+ Setexpr * parsesetexpr();
+ Statementb * parsestatementb();
+};
+#endif
--- /dev/null
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <assert.h>
+
+#include <errno.h>
+extern int errno;
+
+#include "file.h"
+extern "C" {
+#include "test.h"
+}
+#include "Hashtable.h"
+#include "model.h"
+#include "element.h"
+#include "tmap.h"
+
+char *dstring="d\0";
+struct filedesc files[MAXFILES];
+struct InodeBitmap ib;
+struct BlockBitmap bb;
+
+int bbbptr; // pointer to the BlockBitmap block
+int ibbptr; // pointer to the InodeBlock block
+int itbptr; // pointer to the InodeTable block
+int rdiptr; // pointer to the RootDirectoryInode block
+
+struct InodeBitmap* sc_ib;
+struct BlockBitmap* sc_bb;
+struct InodeBlock* sc_it;
+int sc_bbbptr;
+int sc_ibbptr;
+int sc_itbptr;
+int sc_rdiptr;
+
+#include "SimpleHash.h"
+
+int testinode(int i) {
+ char temp;
+ assert(sc_ib);
+ temp = sc_ib->inode[i/8]&(1<<(i%8));
+ return temp == 0 ? 0 : 1;
+}
+
+int testblock(int i) {
+ char temp;
+ assert(sc_bb);
+ temp = sc_bb->blocks[i/8]&(1<<(i%8));
+ return temp == 0 ? 0 : 1;
+}
+
+void assertvalidmemory(int low, int high) {
+ typemap *tm=exportmodel->gettypemap();
+ assert(tm->assertvalidmemory((void*) low, (void*) high));
+}
+
+unsigned long selfcheck2(struct block* d) {
+
+ struct timeval begin,end;
+ unsigned long t;
+ gettimeofday(&begin,NULL);
+
+#include "RepairCompiler/MCC/test2.cc"
+
+ gettimeofday(&end,NULL);
+ t=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+ return t;
+}
+
+void selfcheck(struct block* diskptr) {
+
+ /* get time information for statistics */
+ struct timeval begin,end;
+ unsigned long t;
+ gettimeofday(&begin,NULL);
+
+
+ /* hand written data structure consistency */
+
+ struct SuperBlock* sb = (struct SuperBlock*)&diskptr[0];
+ struct GroupBlock* gb = (struct GroupBlock*)&diskptr[1];
+
+ int numblocks = sb->NumberofBlocks;
+ int numinodes = sb->NumberofInodes;
+
+ SimpleHash* hash_inodeof = new SimpleHash(1000); // estimation of the number of files!
+ SimpleHash* hash_contents = new SimpleHash(1000); // contents
+ SimpleList* list_inodes = new SimpleList();
+ SimpleList* list_blocks = new SimpleList();
+
+ // simple test
+
+ // check bitmap consistency with superblock, groupblock, inotetableblock
+ // inodebitmapblock, blockbitmapblock, rootidrectoryinode
+
+ sc_bbbptr = gb->BlockBitmapBlock;
+ sc_ibbptr = gb->InodeBitmapBlock;
+ sc_itbptr = gb->InodeTableBlock;
+ sc_rdiptr = sb->RootDirectoryInode;
+
+ // constraint 8: automatic...
+ // constraint 9: automatic...
+
+ // constraint 10:
+ if (sc_itbptr < numblocks) {
+ sc_it = (InodeBlock*)&diskptr[sc_itbptr];
+ } else {
+ sc_it = NULL;
+ }
+
+ // constraint 11:
+ if (sc_ibbptr < numblocks) {
+ sc_ib = (InodeBitmap*)&diskptr[sc_ibbptr];
+ } else {
+ sc_ib = NULL;
+ }
+
+ // constraint 12:
+ if (sc_bbbptr < numblocks) {
+ sc_bb = (BlockBitmap*)&diskptr[sc_bbbptr];
+ } else {
+ sc_bb = NULL;
+ }
+
+ // rule 1
+ if (sc_bb) {
+ // constraint 3
+ assert(testblock(0)); // superblock
+
+ // building blocks
+ list_blocks->add(0);
+ }
+
+ // rule 2
+ if (sc_bb) {
+ // constraint 3
+ assert(testblock(1)); // groupblock
+
+ // building list_blocks
+ list_blocks->add(1);
+ }
+
+ // rule 3
+ if (sc_bb) {
+ // constraint 3
+ assert(testblock(sc_itbptr));
+
+ // building list_blocks
+ list_blocks->add(sc_itbptr);
+ }
+
+ // rule 4
+ if (sc_bb) {
+ // constraint 3
+ assert(testblock(sc_ibbptr));
+
+ // building list_blocks
+ list_blocks->add(sc_ibbptr);
+ }
+
+ // rule 5
+ if (sc_bb) {
+ // constraint 3
+ assert(testblock(sc_bbbptr));
+
+ // building list_blocks
+ list_blocks->add(sc_bbbptr);
+ }
+
+ // build inodeof and contents
+ if (sb->RootDirectoryInode < numinodes) {
+ int dinode = sb->RootDirectoryInode;
+
+ // building list_inodes
+ list_inodes->add(dinode);
+
+ for (int k = 0 ; k <= 11 ; k++) {
+
+ int block = sc_it->entries[dinode].Blockptr[k];
+
+ if (block != 0) {
+ hash_contents->add(dinode, block);
+ list_blocks->add(block);
+ }
+
+ if (block < numblocks) {
+
+ DirectoryBlock* db = (DirectoryBlock*)&diskptr[block];
+
+ for (int j = 0; j < sb->blocksize/128 ; j++) {
+
+ DirectoryEntry* de = (DirectoryEntry*)&db->entries[j];
+
+ if (de->inodenumber < numinodes) {
+ // add <de, de.inodenumber> to inodeof
+ hash_inodeof->add((int)de, de->inodenumber);
+ }
+
+ if (de->inodenumber < numinodes && de->inodenumber != 0) {
+
+ // build list_inodes
+ list_inodes->add(de->inodenumber);
+
+ for (int j2 = 0 ; j2 <= 11 ; j2++) {
+ int block2 = sc_it->entries[de->inodenumber].Blockptr[j2];
+ if (block2 != 0) {
+ hash_contents->add(de->inodenumber, block2);
+ if (block2 < numblocks) {
+ list_blocks->add(block2);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //printf("\n");
+
+ // rule 6 and rule 11: rootdirectoryinode
+ if (sb->RootDirectoryInode < numinodes) {
+ int inode = sb->RootDirectoryInode;
+
+ // constraint 1
+ assert(testinode(inode));
+
+ int filesize = sc_it->entries[inode].filesize;
+ int contents = 0;
+ for (int j = 0; j <= 11; j++) {
+ int block2 = sc_it->entries[inode].Blockptr[j];
+ if (block2 != 0) {
+ // TBD: needs to actual store state because
+ // there could be duplicate numbers and they
+ // shouldn't be double counted
+ contents++;
+
+ // rule 11
+ if (block2 < numblocks) {
+ // constraint 3
+ assert(testblock(block2));
+
+ // constraint 7
+ //printf("%d - %d %d %d\n", inode, j, block2, hash_contents->countdata(block2));
+ assert(hash_contents->countdata(block2)==1);
+ }
+ }
+ }
+
+ // constraint 6
+ assert(filesize <= (contents*8192));
+
+ // constraint 5:
+ assert(sc_it->entries[inode].referencecount == hash_inodeof->countdata(inode));
+ }
+
+ // rule 14
+ if (sb->RootDirectoryInode < numinodes) {
+ int dinode = sb->RootDirectoryInode;
+
+ for (int j = 0; j < sb->blocksize/128 ; j++) {
+ for (int k = 0 ; k <= 11 ; k++) {
+ int block = sc_it->entries[dinode].Blockptr[k];
+ if (block < numblocks) {
+ DirectoryBlock* db = (DirectoryBlock*)&diskptr[block];
+ DirectoryEntry* de = (DirectoryEntry*)&db->entries[j];
+
+ int inode = de->inodenumber;
+ if (inode < numinodes && inode != 0) {
+
+ // constraint 1
+ assert(testinode(inode));
+
+ // constraint 6
+ int filesize = sc_it->entries[inode].filesize;
+ int contents = 0;
+ for (int j2 = 0; j2 <= 11; j2++) {
+ int block2 = sc_it->entries[inode].Blockptr[j2];
+ if (block2 != 0) {
+ // TBD
+ contents++;
+
+ // rule 11
+ if (block2 < numblocks) {
+ // constraint 3
+ assert(testblock(block2));
+
+ // constraint 7
+ assert(hash_contents->countdata(block2)==1);
+ }
+ }
+ }
+ assert(filesize <= (contents*8192));
+
+ // constraint 5:
+ assert(sc_it->entries[inode].referencecount == hash_inodeof->countdata(inode));
+ }
+ }
+ }
+ }
+ }
+
+ // to go, [7, 8 ]
+ // interesting question is going to be how to deal with 7 and 8
+ // actually it turns out that the constraints bound to rules 7 and 8 are
+ // easy... its just that creating the lists for 7 and 8 is a little tricky...
+ // 7 can easily piggyback on the creation of inodeof/contents... it fits quite
+ // nicely into that traversal... same goes for 8
+
+ // rule 7
+ for (int i = 0 ; i < numinodes ; i++) {
+ if (!list_inodes->contains(i)) {
+ // constraint 2
+ if (testinode(i)) {
+ printf("<bad inode,%d>", i);
+ assert(testinode(i)==0);
+ }
+ }
+ }
+
+ // rule 8
+ for (int i = 0 ; i < numblocks ; i++) {
+ if (!list_blocks->contains(i)) {
+ // constraint 4
+ if (testblock(i)) {
+ printf("<bad block,%d>", i);
+ assert(testblock(i)==0);
+ }
+
+ }
+ }
+
+
+ gettimeofday(&end,NULL);
+ t=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+
+ printf("\npassed tests in %ld u-seconds!\n", t);
+
+
+}
+
+
+int main(int argc, char **argv)
+{
+
+ for(int i=0;i<MAXFILES;i++)
+ files[i].used=false;
+
+
+ if (argc <= 1) {
+ printf("Filesystem Repair:\n\tusage: main [0..9]\n\n");
+ printf("\t 0 : creates disk\n");
+ printf("\t 1 : mount disk, creates files and writes test data\n");
+ printf("\t 2 : \n");
+ printf("\t 3 : inserts errors to break specs\n");
+ printf("\t 4 : \n");
+ printf("\t 5 : \n");
+ printf("\t 6 : \n");
+ printf("\t 7 : \n");
+ printf("\t 8 : \n");
+ printf("\t 9 : \n");
+ exit(-1);
+ }
+
+ switch(argv[1][0]) {
+
+ case '0':
+ //creates a disk
+ createdisk();
+ return 1;
+
+
+ case '1': {
+ /* mounts the disk, creates NUMFILES files, and writes "buf" in each file
+ for 90 times */
+ struct block * ptr=mountdisk("disk");
+
+ for(int i=0; i<NUMFILES; i++) {
+ char filename[10];
+ sprintf(filename,"file_%d",i);
+ openfile(ptr,filename);
+ }
+
+ for(int j=0; j<90; j++) {
+ for(int i=0; i<NUMFILES; i++) {
+ char *buf="01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123";
+ writefile(ptr,i,buf,122);
+ }
+ }
+
+ for(int i=0; i<NUMFILES; i++) {
+ closefile(ptr,i);
+ }
+
+ printdirectory(ptr);
+ printinodeblock(ptr);
+
+ unmountdisk(ptr);
+ break;
+ }
+
+
+ case 'r': {
+ struct block * ptr=mountdisk("disk");
+
+ initializeanalysis();
+
+ alloc(ptr,LENGTH);
+ addmapping(dstring,ptr,"Disk");
+
+ printdirectory(ptr);
+ printinodeblock(ptr);
+
+ // check the DSs
+ unsigned long time = 0;
+ for (int i = 0; i < 50; i++) {
+ time += benchmark();
+ }
+
+ printf("\ninterpreted: %u us\n", (time/50));
+
+ dealloc(ptr);
+ unmountdisk(ptr);
+ break;
+ }
+
+ case 's': {
+ struct block * ptr=mountdisk("disk");
+
+ initializeanalysis();
+
+ alloc(ptr,LENGTH);
+ addmapping(dstring,ptr,"Disk");
+
+ printdirectory(ptr);
+ printinodeblock(ptr);
+
+ // check the DSs
+ selfcheck(ptr);
+
+
+ dealloc(ptr);
+ unmountdisk(ptr);
+ break;
+ }
+
+ case 'x': {
+ struct block * ptr=mountdisk("disk");
+
+ initializeanalysis();
+
+ alloc(ptr,LENGTH);
+ addmapping(dstring,ptr,"Disk");
+
+ printdirectory(ptr);
+ printinodeblock(ptr);
+
+ // check the DSs
+ // check the DSs
+ unsigned long time = 0;
+ for (int i = 0; i < 50; i++) {
+ time += selfcheck2(ptr);
+ }
+
+ printf("\ncompiled: %u us\n", (time/50));
+
+ dealloc(ptr);
+ unmountdisk(ptr);
+ break;
+ }
+
+
+ // insert errors that break the specs
+ case '3': {
+ struct block * ptr=mountdisk("disk");
+ initializeanalysis();
+ Hashtable *env=exportmodel->gethashtable();
+ alloc(ptr,LENGTH);
+ addmapping(dstring,ptr,"Disk");
+
+ // insert errors that break the specs
+ doanalysis2();
+ dealloc(ptr);
+ unmountdisk(ptr);
+ break;
+ }
+
+
+ // insert errors that do not break the specs
+ case '4': {
+ struct block * ptr=mountdisk("disk");
+ initializeanalysis();
+ Hashtable *env=exportmodel->gethashtable();
+ alloc(ptr,LENGTH);
+ addmapping(dstring,ptr,"Disk");
+
+ // insert errors that do not break the specs
+ doanalysis3();
+ dealloc(ptr);
+ unmountdisk(ptr);
+ break;
+ }
+
+
+ case '5': {
+ // prints the directory structure, and prints the contents of each file
+ struct block * ptr=mountdisk("disk");
+ printdirectory(ptr);
+ for(int i=1; i<NUMFILES; i++) {
+ char filename[10];
+ sprintf(filename,"file_%d",i);
+ printfile(filename,ptr);
+ }
+ unmountdisk(ptr);
+ break;
+ }
+
+ case '6': {
+ // the same as "case '1'" only that the files are accessed in reversed order
+ struct block * ptr=mountdisk("disk");
+ for(int i=NUMFILES; i>1; i--) {
+ char filename[10];
+ sprintf(filename,"file_%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0; j<90; j++) {
+ for(int i=NUMFILES; i>1; i--) {
+ char *buf="01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123";
+ writefile(ptr,i,buf,122);
+ }
+ }
+ for(int i=NUMFILES; i>1; i--) {
+ closefile(ptr,i);
+ }
+ unmountdisk(ptr);
+ break;
+ }
+
+ case '7': {
+ struct block * ptr=mountdisk("disk");
+ for(int i=NUMFILES; i>=0; i--) {
+ char filename[10];
+ sprintf(filename,"file_%d",i);
+ openfile(ptr,filename);
+ }
+
+ for(int j=0;j<6000;j++) {
+ for(int i=NUMFILES; i>=0; i--) {
+ char name[10];
+ int len=sprintf(name, "%d ",i);
+ writefile(ptr,i,name,len);
+ }
+ }
+ for(int i=NUMFILES; i>=0; i--) {
+ closefile(ptr,i);
+ }
+ for(int i=NUMFILES; i>=0; i--) {
+ char filename[10];
+ sprintf(filename,"file_%d",i);
+ openfile(ptr,filename);
+ }
+
+ for(int j=0;j<400;j++) {
+ for(int i=NUMFILES; i>=0; i--) {
+ int l=0;
+ char name[10];
+ int len=sprintf(name, "%d ",i);
+ readfile(ptr,i,name,len);
+ sscanf(name, "%d ", &l);
+ if (l!=i) {
+ printf("ERROR in benchmark\n");
+ }
+ }
+ }
+ for(int i=NUMFILES; i>=0; i--) {
+ closefile(ptr,i);
+ }
+ unmountdisk(ptr);
+ }
+ break;
+
+
+ case '8': {
+ {
+ struct block * ptr=chmountdisk("disk");
+ initializeanalysis();
+ Hashtable *env=exportmodel->gethashtable();
+ alloc(ptr,LENGTH);
+ addmapping(dstring,ptr,"Disk");
+ doanalysis();
+ dealloc(ptr);
+ chunmountdisk(ptr);
+ }
+ struct block * ptr=mountdisk("disk");
+ for(int i=NUMFILES; i>=0; i--) {
+ char filename[10];
+ sprintf(filename,"file_%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0; j<6000; j++) {
+ for(int i=NUMFILES; i>=0; i--) {
+ char name[10];
+ int len=sprintf(name, "%d ",i);
+ writefile(ptr,i,name,len);
+ }
+ }
+ for(int i=NUMFILES; i>=0; i--) {
+ closefile(ptr,i);
+ }
+ for(int i=NUMFILES; i>=0; i--) {
+ char filename[10];
+ sprintf(filename,"file_%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0;j<400;j++) {
+ for(int i=NUMFILES; i>=0; i--) {
+ int l=0;
+ char name[10];
+ int len=sprintf(name, "%d ",i);
+ readfile(ptr,i,name,len);
+ sscanf(name, "%d ", &l);
+ if (l!=i) {
+ printf("ERROR in benchmark\n");
+ }
+ }
+ }
+ for(int i=NUMFILES; i>=0; i--) {
+ closefile(ptr,i);
+ }
+ unmountdisk(ptr);
+ }
+
+ case '9': {
+ for(int i=0;i<MAXFILES;i++)
+ files[i].used=false;
+
+
+ struct block * ptr=mountdisk("disk");
+
+ for(int i=0; i<NUMFILES; i++)
+ {
+ char filename[10];
+ sprintf(filename,"file_%d", i);
+ openfile(ptr,filename);
+ }
+
+ for(int i=0; i<NUMFILES; i++)
+ {
+ char buf[100];
+ sprintf(buf,"This is file_%d.", i);
+ writefile(ptr,i,buf,strlen(buf));
+ }
+
+
+ createlink(ptr, "file_1", "link_1");
+ createlink(ptr, "file_1", "link_2");
+
+ removefile("file_1", ptr);
+
+ int fd = openfile(ptr, "new");
+ writefile(ptr, fd, "new", 3);
+
+ printfile("file_1", ptr);
+ printfile("link_1", ptr);
+ printfile("link_2", ptr);
+
+ for(int i=0; i<NUMFILES; i++)
+ closefile(ptr,i);
+
+
+ unmountdisk(ptr);
+ }
+
+ }
+}
+
+
+
+struct block * chmountdisk(char *filename) {
+ int fd=open(filename,O_CREAT|O_RDWR);
+ struct block *ptr=(struct block *) mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
+ return ptr;
+}
+
+
+
+void chunmountdisk(struct block *vptr) {
+ int val=munmap(vptr,LENGTH);
+ if (val!=0)
+ printf("Error!\n");
+}
+
+
+
+// mounts the disk from the file "filename"
+struct block * mountdisk(char *filename) {
+ int fd=open(filename,O_CREAT|O_RDWR);
+ struct block *ptr=(struct block *) mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
+
+ // droy: debugging
+ if ((int)ptr == -1) {
+ perror("mountdisk\0");
+ exit(-1);
+ }
+
+
+ struct SuperBlock *sb=(struct SuperBlock *) &ptr[0];
+ struct GroupBlock *gb=(struct GroupBlock *) &ptr[1];
+ bbbptr=gb->BlockBitmapBlock;
+ ibbptr=gb->InodeBitmapBlock;
+ itbptr=gb->InodeTableBlock;
+ rdiptr=sb->RootDirectoryInode;
+
+ struct InodeBitmap *ibb=(struct InodeBitmap *) &ptr[ibbptr];
+ for(int i=0;i<(NUMINODES/8+1);i++)
+ ib.inode[i]=ibb->inode[i];
+
+ struct BlockBitmap *bbb=(struct BlockBitmap *) &ptr[bbbptr];
+ for(int i=0;i<(NUMBLOCK/8+1);i++)
+ bb.blocks[i]=bbb->blocks[i];
+
+ printf("Disk mounted successfully from the file %s\n", filename);
+ fflush(NULL);
+
+ return ptr;
+}
+
+
+
+void unmountdisk(struct block *vptr) {
+ struct InodeBitmap *ibb=(struct InodeBitmap *) &vptr[ibbptr];
+ for(int i=0;i<(NUMINODES/8+1);i++)
+ ibb->inode[i]=ib.inode[i];
+
+ struct BlockBitmap *bbb=(struct BlockBitmap *) &vptr[bbbptr];
+ for(int i=0;i<(NUMBLOCK/8+1);i++)
+ bbb->blocks[i]=bb.blocks[i];
+ int val=munmap(vptr,LENGTH);
+ if (val!=0)
+ printf("Error!\n");
+}
+
+
+void removefile(char *filename, struct block *ptr) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/128;j++) {
+ if (db->entries[j].name[0]!=0) {
+ if(strcmp(filename,db->entries[j].name)==0) {
+ /* Found file */
+ db->entries[j].name[0]=0; //Delete entry
+ int inode=db->entries[j].inodenumber;
+ db->entries[j].inodenumber=0;
+
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ itb->entries[inode].referencecount--;
+
+ if (itb->entries[inode].referencecount==0) {
+ for(int i=0;i<((itb->entries[inode].filesize+BLOCKSIZE-1)/BLOCKSIZE);i++) {
+ int blocknum=itb->entries[inode].Blockptr[i];
+ bb.blocks[blocknum/8]^=(1<<(blocknum%8));
+ }
+ ib.inode[inode/8]^=(1<<(inode%8));
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void createlink(struct block *ptr,char *filename, char *linkname) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++) {
+ if (db->entries[j].name[0]!=0) {
+ if(strcmp(filename,db->entries[j].name)==0) {
+ /* Found file */
+ int inode=db->entries[j].inodenumber;
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
+ itb->entries[inode].referencecount++;
+ addtode(ptr, inode, linkname);
+ }
+ }
+ }
+ }
+}
+
+
+void closefile(struct block *ptr, int fd) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
+
+
+ msync(&itb->entries[fd],sizeof(DirectoryEntry),MS_SYNC);
+ files[fd].used=false;
+}
+
+
+bool writefile(struct block *ptr, int fd, char *s) {
+ return (writefile(ptr,fd,s,1)==1);
+}
+
+
+int writefile(struct block *ptr, int fd, char *s, int len) {
+ struct filedesc *tfd=&files[fd];
+ if (tfd->used==false)
+ return -1;
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
+ int filelen=itb->entries[tfd->inode].filesize;
+ if ((12*BLOCKSIZE-tfd->offset)<len)
+ len=12*BLOCKSIZE-tfd->offset;
+ for(int i=0;i<len;i++) {
+ int nbuffer=tfd->offset/BLOCKSIZE;
+ int noffset=tfd->offset%BLOCKSIZE;
+ if (tfd->offset>=filelen) {
+ if (noffset==0) {
+ int bptr=getblock(ptr);
+ if (bptr==-1) {
+ if (itb->entries[files[fd].inode].filesize<files[fd].offset)
+ itb->entries[files[fd].inode].filesize=files[fd].offset;
+ return i;
+ }
+ itb->entries[tfd->inode].Blockptr[nbuffer]=bptr;
+ }
+ }
+ int block=itb->entries[tfd->inode].Blockptr[nbuffer];
+ char *fchar=(char *)&ptr[block];
+ int tocopy=len-i;
+ if (tocopy>(BLOCKSIZE-noffset))
+ tocopy=BLOCKSIZE-noffset;
+ memcpy(&fchar[noffset],&s[i],tocopy);
+ msync(&fchar[noffset],tocopy,MS_SYNC);
+ i+=tocopy;
+ tfd->offset+=tocopy;
+ }
+ if (itb->entries[files[fd].inode].filesize<files[fd].offset)
+ itb->entries[files[fd].inode].filesize=files[fd].offset;
+ return len;
+}
+
+
+// reads one char from the file fd and returns it
+char readfile(struct block *ptr, int fd) {
+ char array[1];
+ if (readfile(ptr,fd,array,1)==1)
+ return array[0];
+ else
+ return EOF;
+}
+
+// reads len chars from file fd (file system *ptr) and returns them in buf
+int readfile(struct block *ptr, int fd, char *buf, int len) {
+ struct filedesc *tfd=&files[fd];
+ if (tfd->used==false)
+ return -1;
+
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ int filelen=itb->entries[tfd->inode].filesize;
+
+ // if there are fewer than len chars left, read until the end
+ if ((filelen-tfd->offset)<len)
+ len=filelen-tfd->offset;
+
+ for(int i=0;i<len;) {
+ int nbuffer=tfd->offset/BLOCKSIZE;
+ int noffset=tfd->offset%BLOCKSIZE;
+ int block=itb->entries[tfd->inode].Blockptr[nbuffer];
+ char *fchar=(char *)&ptr[block];
+ int tocopy=len-i;
+ if (tocopy>(BLOCKSIZE-noffset))
+ tocopy=BLOCKSIZE-noffset;
+ memcpy(&buf[i],&fchar[noffset],tocopy);
+ i+=tocopy;
+ tfd->offset+=tocopy;
+ }
+ return len;
+}
+
+
+
+int openfile(struct block *ptr, char *filename) {
+ /* Locate fd */
+ int fd=-1;
+ for(int k=0;k<MAXFILES;k++) {
+ if(!files[k].used) {
+ /* Found file */
+ fd=k;
+ files[fd].used=true;
+ break;
+ }
+ }
+ if (fd==-1) return fd;
+
+ /* Check to see if file exists*/
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++)
+ {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++)
+ {
+ if (db->entries[j].name[0]!=0) {
+ if(strcmp(filename, db->entries[j].name)==0)
+ {
+ files[fd].inode=db->entries[j].inodenumber;
+ files[fd].offset=0;
+ return fd;
+ }
+ }
+ }
+ }
+
+ /* If file doesn't exist, create it */
+ int inode=getinode(ptr);
+ if (inode==-1) {
+ files[fd].used=false;
+ return -1;
+ }
+ itb->entries[inode].filesize=0;
+ itb->entries[inode].referencecount=1;
+ for (int i=0;i<12;i++)
+ itb->entries[inode].Blockptr[i]=0;
+
+ addtode(ptr, inode, filename);
+ files[fd].inode=inode;
+ files[fd].offset=0;
+ return fd;
+}
+
+
+void createfile(struct block *ptr,char *filename, char *buf,int buflen) {
+ int fd=openfile(ptr,filename);
+ writefile(ptr,fd,buf,buflen);
+ closefile(ptr,fd);
+}
+
+
+
+// adds a file to the directory entry
+void addtode(struct block *ptr, int inode, char *filename) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++) {
+ if (db->entries[j].name[0]==0) {
+ /* lets finish */
+ strncpy(db->entries[j].name,filename,124);
+ db->entries[j].inodenumber=inode;
+ msync(&db->entries[j],sizeof(DirectoryEntry),MS_SYNC);
+ return;
+ }
+ }
+ }
+}
+
+
+// return the first free node in the InodeTable. Marks that inode as used.
+int getinode(struct block *ptr) {
+ for(int i=0;i<NUMINODES;i++) {
+ if (!(ib.inode[i/8]&(1<<(i%8)))) {
+ ib.inode[i/8]=ib.inode[i/8]|(1<<(i%8));
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+int getblock(struct block * ptr) {
+ for(int i=0;i<NUMBLOCK;i++) {
+ if (!(bb.blocks[i/8]&(1<<(i%8)))) {
+ bb.blocks[i/8]=bb.blocks[i/8]|(1<<(i%8));
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+
+void createdisk()
+{
+ int blocksize=BLOCKSIZE;
+ int numblocks=NUMBLOCK;
+
+ int fd=open("disk",O_CREAT|O_RDWR|O_TRUNC, S_IREAD|S_IWRITE);
+
+ // creates numblocks and initializes them with 0
+ char *buf=(char *)calloc(1,blocksize);
+ for(int i=0;i<numblocks;i++) {
+ write(fd,buf,blocksize);
+ }
+ free(buf);
+
+ // maps the file 'disk' into memory
+ void *vptr=mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
+
+ // added by dan roy for debugging
+ if ((int)vptr == -1) {
+ perror("createdisk()\0");
+ exit(-1);
+ }
+ // end dan roy
+
+ struct block *ptr=(struct block *)vptr;
+ {
+ struct SuperBlock * sb=(struct SuperBlock*) &ptr[0];
+ sb->FreeBlockCount=NUMBLOCK-5;
+ sb->FreeInodeCount=NUMINODES-1;
+ sb->NumberofInodes=NUMINODES;
+ sb->NumberofBlocks=NUMBLOCK;
+ sb->RootDirectoryInode=0;
+ sb->blocksize=BLOCKSIZE;
+ }
+ {
+ struct GroupBlock * gb=(struct GroupBlock *) &ptr[1];
+ gb->BlockBitmapBlock=2;
+ gb->InodeBitmapBlock=3;
+ gb->InodeTableBlock=4;
+ gb->GroupFreeBlockCount=NUMBLOCK-5;
+ gb->GroupFreeInodeCount=NUMINODES-1;
+ }
+ {
+ struct BlockBitmap * bb=(struct BlockBitmap *) &ptr[2];
+ //memset(bb, 0, sizeof(BlockBitmap));
+ for(int i=0;i<(5+12);i++) {
+ bb->blocks[i/8]=bb->blocks[i/8]|(1<<(i%8));
+ }
+ }
+ {
+ struct InodeBitmap * ib=(struct InodeBitmap *) &ptr[3];
+ //memset(ib, 0, sizeof(InodeBitmap));
+ ib->inode[0]=1;
+ }
+ {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
+
+ itb->entries[0].filesize=12*BLOCKSIZE;
+ for(int i=0;i<12;i++)
+ itb->entries[0].Blockptr[i]=i+5; // blocks 5 to 16 are RootDirectory entries
+ itb->entries[0].referencecount=0;
+ }
+
+ int val=munmap(vptr,LENGTH);
+ if (val!=0)
+ printf("Error!\n");
+
+ printf("Disk created successfully!\n");
+}
+
+
+void printdirectory(struct block *ptr)
+{
+ struct InodeBlock *itb=(struct InodeBlock *) &ptr[itbptr];
+
+ for(int i=0;i<12;i++)
+ {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+
+ for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++) {
+ if (db->entries[j].name[0]!=0)
+ {
+ /* lets finish */
+ //printf("%s %d\n",db->entries[j].name, db->entries[j].inodenumber);
+ printf("%s (inode %d) (%d bytes)\n",db->entries[j].name, db->entries[j].inodenumber, itb->entries[db->entries[j].inodenumber].filesize);
+ }
+ }
+ }
+
+ //printf("end of printdirectory\n");
+}
+
+// prints the contents of the file with filename "filename"
+void printfile(char *filename, struct block *ptr)
+{
+ printf("=== BEGIN of %s ===\n", filename);
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/DIRECTORYENTRYSIZE;j++) {
+ if (db->entries[j].name[0]!=0) {
+ if(strcmp(filename,db->entries[j].name)==0) {
+ /* Found file */
+ int inode=db->entries[j].inodenumber;
+
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<((itb->entries[inode].filesize+BLOCKSIZE-1)/BLOCKSIZE);i++) {
+ struct block *b=&ptr[itb->entries[inode].Blockptr[i]];
+ write(0,b,BLOCKSIZE);
+ }
+ }
+ }
+ }
+ }
+ printf("\n=== END of %s ===\n", filename);
+}
+
+
+void printinodeblock(struct block *ptr)
+{
+ struct InodeBlock *itb=(struct InodeBlock *) &ptr[itbptr];
+
+ for (int i=0; i<NUMINODES; i++)
+ {
+ Inode inode = itb->entries[i];
+ printf("inode %d: (filesize %d), (referencecount %d)\n", i, inode.filesize, inode.referencecount);
+ }
+}
+
+
--- /dev/null
+// defines the sets and the relations used
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "dmodel.h"
+#include "set.h"
+#include "Relation.h"
+#include "Hashtable.h"
+#include "model.h"
+#include "Guidance.h"
+
+
+// class DomainSet
+
+DomainSet::DomainSet(char *name) {
+ setname=name;
+ flag=0;
+ this->type=NULL;
+ numsubsets=0;
+ subsets=NULL;
+ set=new WorkSet();
+}
+
+void DomainSet::reset() {
+ delete(set);
+ set=new WorkSet();
+}
+
+char * DomainSet::getelementtype() {
+ return type;
+}
+
+int DomainSet::gettype() {
+ return flag%DOMAINSET_TYPED;
+}
+
+void DomainSet::settype(char *type) {
+ this->type=type;
+ flag|=DOMAINSET_TYPED;
+}
+
+void DomainSet::setsubsets(char **subsets, int numsubsets) {
+ this->subsets=subsets;
+ this->numsubsets=numsubsets;
+ flag=DOMAINSET_SUBSET;
+}
+
+void DomainSet::setpartition(char **subsets, int numsubsets) {
+ this->subsets=subsets;
+ this->numsubsets=numsubsets;
+ flag=DOMAINSET_PARTITION;
+}
+
+void DomainSet::print() {
+ printf("%s",setname);
+ if (DOMAINSET_TYPED&flag)
+ printf("(%s)",type);
+ printf(":");
+ if (DOMAINSET_PARTITION&flag)
+ printf("partition ");
+ for(int i=0;i<numsubsets;i++)
+ if (i==0)
+ printf("%s ",subsets[i]);
+ else
+ printf("| %s",subsets[i]);
+ printf("Size: %d",set->size());
+}
+
+char * DomainSet::getname() {
+ return setname;
+}
+
+WorkSet * DomainSet::getset() {
+ return set;
+}
+
+int DomainSet::getnumsubsets() {
+ return numsubsets;
+}
+
+char * DomainSet::getsubset(int i) {
+ return subsets[i];
+}
+
+
+
+
+// class DRelation
+
+DRelation::DRelation(char *n, char *d, char *r, int t, bool b) {
+ domain=d;range=r;type=t;name=n;
+ relation=new WorkRelation();
+ staticrel=b;
+ tokenrange = NULL;
+}
+
+void DRelation::reset() {
+ delete(relation);
+ relation=new WorkRelation();
+}
+
+bool DRelation::isstatic() {
+ return staticrel;
+}
+
+char * DRelation::getdomain() {
+ return domain;
+}
+
+char * DRelation::getrange() {
+ return range;
+}
+
+WorkSet* DRelation::gettokenrange() {
+ return tokenrange;
+}
+
+void DRelation::settokenrange(WorkSet *ws) {
+ tokenrange = ws;
+}
+
+
+
+void DRelation::print() {
+ printf("%s: %s -> %s (",name,domain,range);
+ if (type&DRELATION_MANYDOMAIN)
+ printf("M");
+ else
+ printf("1");
+ printf("->");
+ if (type&DRELATION_MANYRANGE)
+ printf("M");
+ else
+ printf("1");
+ printf(")");
+
+}
+
+char * DRelation::getname() {
+ return name;
+}
+
+WorkRelation * DRelation::getrelation() {
+ return relation;
+}
+
+
+
+
+
+// class DomainRelation
+
+DomainRelation::DomainRelation(DomainSet **s, int ns, DRelation **r,int nr) {
+ sets=s; numsets=ns;
+ relations=r;numrelations=nr;
+ settable=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
+ relationtable=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
+ for(int i=0;i<numsets;i++)
+ settable->put(sets[i]->getname(),sets[i]);
+ for(int i=0;i<numrelations;i++)
+ relationtable->put(relations[i]->getname(),relations[i]);
+}
+
+void DomainRelation::reset() {
+ for(int i=0;i<numsets;i++) {
+ sets[i]->reset();
+ }
+ for(int i=0;i<numrelations;i++) {
+ relations[i]->reset();
+ }
+}
+
+bool DomainRelation::issupersetof(DomainSet *sub,DomainSet *super) {
+ while(sub!=NULL) {
+ if (sub==super)
+ return true;
+ sub=getsuperset(sub);
+ }
+ return false;
+}
+
+void DomainRelation::print() {
+ for(int i=0;i<numsets;i++) {
+ sets[i]->print();
+ printf("\n");
+ }
+ printf("\n");
+ for(int i=0;i<numrelations;i++) {
+ relations[i]->print();
+ printf("\n");
+ }
+}
+
+DomainSet * DomainRelation::getset(char * setname) {
+ if (setname!=NULL)
+ return (DomainSet *)settable->get(setname);
+ else return NULL;
+}
+
+DRelation * DomainRelation::getrelation(char * relationname) {
+ if (relationname!=NULL)
+ return (DRelation *)relationtable->get(relationname);
+ else
+ return NULL;
+}
+
+DomainRelation::~DomainRelation() {
+ delete(settable);
+ delete(relationtable);
+ for(int i=0;i<numsets;i++)
+ delete(sets[i]);
+ for(int i=0;i<numrelations;i++)
+ delete(relations[i]);
+ delete(sets);
+ delete(relations);
+}
+
+void DomainRelation::addallsubsets(DomainSet *ds, WorkSet *ws) {
+ WorkSet *tmp=new WorkSet(true);
+ tmp->addobject(ds);
+ while(!tmp->isEmpty()) {
+ DomainSet *s=(DomainSet *)tmp->firstelement();
+ tmp->removeobject(s);
+ ws->addobject(s);
+ for(int j=0;j<s->getnumsubsets();j++) {
+ tmp->addobject(getset(s->getsubset(j)));
+ }
+ }
+ delete(tmp);
+}
+
+WorkSet * DomainRelation::conflictdelsets(char * setname, char * boundset) {
+ /* Want to know what set removals insertion into "setname" could cause */
+ if (equivalentstrings(setname,"int"))
+ return new WorkSet(true);
+ if (equivalentstrings(setname,"token"))
+ return new WorkSet(true);
+ DomainSet *bs=getset(boundset);
+ WorkSet *wsret=new WorkSet(true);
+ WorkSet *ws=new WorkSet(true);
+ while(bs!=NULL) {
+ ws->addobject(bs);
+ bs=getsuperset(bs);
+ }
+
+ DomainSet *oldcs=getset(setname);
+ DomainSet *cs=getsuperset(oldcs);
+
+
+ while(cs!=NULL) {
+ if (ws->contains(cs)) {
+ if (cs->gettype()==DOMAINSET_PARTITION &&
+ !equivalentstrings(cs->getname(),boundset)) {
+ delete(ws);
+ delete(wsret);
+ ws=new WorkSet(true);
+
+ DomainSet *bs=getset(boundset);
+ addallsubsets(bs,ws);
+ DomainSet *oldbs=bs;
+ bs=getsuperset(oldbs);
+ while(bs!=cs) {
+ ws->addobject(bs);
+ if (bs->gettype()!=DOMAINSET_PARTITION) {
+ for(int i=0;i<bs->getnumsubsets();i++) {
+ DomainSet *tss=getset(bs->getsubset(i));
+ if (oldbs!=tss) {
+ addallsubsets(tss,ws);
+ }
+ }
+ }
+ oldbs=bs;
+ bs=getsuperset(oldbs);
+ }
+ return ws;
+ }
+ break;
+ }
+ if (cs->gettype()==DOMAINSET_PARTITION) {
+ /* We have a partition...got to look at all other subsets */
+ for(int i=0;i<cs->getnumsubsets();i++) {
+ if (!equivalentstrings(cs->getsubset(i),oldcs->getname())) {
+ addallsubsets(getset(cs->getsubset(i)),wsret);
+ }
+ }
+ }
+ oldcs=cs;
+ cs=getsuperset(cs);
+ }
+ delete(ws);
+ return wsret;
+}
+
+DomainSet * DomainRelation::getsuperset(DomainSet *s) {
+ char *name=s->getname();
+ for(int i=0;i<numsets;i++)
+ for (int j=0;j<sets[i]->getnumsubsets();j++) {
+ if(equivalentstrings(name,sets[i]->getsubset(j)))
+ return sets[i];
+ }
+ return NULL;
+}
+
+WorkSet * DomainRelation::conflictaddsets(char * setname, char *boundset, model *m) {
+ /* Want to know what set additions insertion into "setname" could cause */
+ if (equivalentstrings(setname,"int"))
+ return new WorkSet(true);
+ if (equivalentstrings(setname,"token"))
+ return new WorkSet(true);
+ DomainSet *bs=getset(boundset);
+ WorkSet *wsret=new WorkSet(true);
+ WorkSet *ws=new WorkSet(true);
+ while(bs!=NULL) {
+ ws->addobject(bs);
+ bs=getsuperset(bs);
+ }
+
+ Guidance *g=m->getguidance();
+ DomainSet *ds=getset(g->insertiontoset(setname));
+ while(ds!=NULL) {
+ if (ws->contains(ds))
+ break;
+ wsret->addobject(ds);
+ ds=getsuperset(ds);
+ }
+
+ delete(ws);
+ return wsret;
+}
+
+WorkSet * DomainRelation::removeconflictdelsets(char *setname) {
+ /* Obviously remove from all subsets*/
+ WorkSet *tmp=new WorkSet(true);
+ WorkSet *wsret=new WorkSet(true);
+ tmp->addobject(getset(setname));
+ while(!tmp->isEmpty()) {
+ DomainSet *s=(DomainSet *)tmp->firstelement();
+ tmp->removeobject(s);
+ wsret->addobject(s);
+ for(int j=0;j<s->getnumsubsets();j++)
+ tmp->addobject(getset(s->getsubset(j)));
+ }
+ delete(tmp);
+ return wsret;
+}
+
+WorkSet * DomainRelation::removeconflictaddsets(char *setname, model *m) {
+ /* Remove could cause addition to a new set...*/
+ DomainSet *ds=getset(setname);
+ Guidance *g=m->getguidance();
+ char *settoputin=g->removefromset(setname);
+ if (settoputin==NULL)
+ return new WorkSet(true);
+ return conflictaddsets(settoputin, setname, m);
+}
+
+DomainSet * DomainRelation::getsource(DomainSet *s) {
+ return getsuperset(s);
+}
+
+void DomainRelation::addtoset(Element *ele, DomainSet *settoadd, model *m) {
+ /* Assumption is that object is not in set*/
+ if(settoadd->getset()->contains(ele)) /* Already in set-no worries */
+ return;
+ if(settoadd->gettype()==DOMAINSET_PARTITION) {
+ /* Have to find subset to add to */
+ char *subsettoadd=m->getguidance()->insertiontoset(settoadd->getname());
+ DomainSet *setptr=getset(subsettoadd);
+ while(setptr!=settoadd) {
+ setptr->getset()->addobject(ele);
+ m->triggerrule(ele,setptr->getname());
+ setptr=getsuperset(setptr);
+ }
+ }
+ settoadd->getset()->addobject(ele);
+ m->triggerrule(ele,settoadd->getname());
+ DomainSet *oldptr=settoadd;
+ DomainSet *ptr=getsuperset(oldptr);
+ while((ptr!=NULL)&&(!ptr->getset()->contains(ele))) {
+ ptr->getset()->addobject(ele);
+ m->triggerrule(ele,ptr->getname());
+ oldptr=ptr;
+ ptr=getsuperset(ptr);
+ }
+ if(ptr!=NULL&&
+ ptr->gettype()==DOMAINSET_PARTITION) {
+ /* may have to do removes....*/
+ for(int i=0;i<ptr->getnumsubsets();i++) {
+ char *subset=ptr->getsubset(i);
+ DomainSet *ptrsubset=getset(subset);
+ if (oldptr!=ptrsubset&&
+ ptrsubset->getset()->contains(ele)) {
+ /* GOT THE ONE*/
+ WorkSet *ws=new WorkSet(true);
+ ws->addobject(ptrsubset);
+ while(!ws->isEmpty()) {
+ DomainSet *ds=(DomainSet *)ws->firstelement();
+ ws->removeobject(ds);
+ if (ds->getset()->contains(ele)) {
+ for(int j=0;j<ds->getnumsubsets();j++) {
+ ws->addobject(getset(ds->getsubset(j)));
+ }
+ removefromthisset(ele, ds,m);
+ }
+ }
+ delete(ws);
+ break;
+ }
+ }
+ }
+}
+
+void DomainRelation::abstaddtoset(Element *ele, DomainSet *settoadd, model *m) {
+ /* Assumption is that object is not in set*/
+ if(settoadd->getset()->contains(ele)) /* Already in set-no worries */
+ return;
+ if(settoadd->gettype()==DOMAINSET_PARTITION) {
+ /* Have to find subset to add to */
+ char *subsettoadd=m->getguidance()->insertiontoset(settoadd->getname());
+ DomainSet *setptr=getset(subsettoadd);
+ while(setptr!=settoadd) {
+ setptr->getset()->addobject(ele);
+ m->triggerrule(ele,setptr->getname());
+ setptr=getsuperset(setptr);
+ }
+ }
+ settoadd->getset()->addobject(ele);
+ m->triggerrule(ele,settoadd->getname());
+ DomainSet *oldptr=settoadd;
+ DomainSet *ptr=getsuperset(oldptr);
+ while((ptr!=NULL)&&(!ptr->getset()->contains(ele))) {
+ ptr->getset()->addobject(ele);
+ m->triggerrule(ele,ptr->getname());
+ oldptr=ptr;
+ ptr=getsuperset(ptr);
+ }
+}
+
+void DomainRelation::removefromthisset(Element *ele, DomainSet *ds, model *m) {
+ ds->getset()->removeobject(ele); /*removed from set*/
+ /* Next need to search relations */
+ for(int i=0;i<numrelations;i++) {
+ DRelation * relation=relations[i];
+ if (equivalentstrings(relation->getdomain(),ds->getname()))
+ for(Element *target=(Element *) relation->getrelation()->getobj(ele);target!=NULL;target=(Element *) relation->getrelation()->getobj(ele)) {
+ relation->getrelation()->remove(ele,target);
+ if (relation->isstatic()) {
+ /* Have to actually remove target*/
+ DomainSet *targetset=getset(relation->getrange());
+ delfromsetmovetoset(target,targetset,m);
+ }
+ }
+ if (equivalentstrings(relation->getrange(),ds->getname()))
+ for(Element *target=(Element *) relation->getrelation()->invgetobj(ele);target!=NULL;target=(Element *) relation->getrelation()->invgetobj(ele)) {
+ relation->getrelation()->remove(target,ele);
+ if (relation->isstatic()) {
+ DomainSet *targetset=getset(relation->getdomain());
+ delfromsetmovetoset(target,targetset,m);
+ }
+ }
+ }
+}
+
+void DomainRelation::delfromsetmovetoset(Element *ele,DomainSet *deletefromset,model *m) {
+ WorkSet *ws=new WorkSet(true);
+ ws->addobject(deletefromset);
+ while(!ws->isEmpty()) {
+ DomainSet *ds=(DomainSet *)ws->firstelement();
+ ws->removeobject(ds);
+ if (ds->getset()->contains(ele)) {
+ for(int j=0;j<ds->getnumsubsets();j++) {
+ ws->addobject(getset(ds->getsubset(j)));
+ }
+ removefromthisset(ele, ds,m);
+ }
+ }
+ delete(ws);
+ char *mts=m->getguidance()->removefromset(deletefromset->getname());
+ DomainSet *movetoset=getset(mts);
+ addtoset(ele, movetoset, m); //Add to the movetoset now...
+}
+
+int DomainRelation::getnumrelation() {
+ return numrelations;
+}
+
+DRelation * DomainRelation::getrelation(int i) {
+ return relations[i];
+}
+
+
+bool DomainRelation::fixstuff() {
+ bool anychange=false;
+ /* Guaranteed fixpoint because we keep removing items...finite # of items */
+ while(true) {
+ bool changed=false;
+ for(int i=0;i<numsets;i++) {
+ if(checksubset(sets[i])) {
+ changed=true;
+ anychange=true;
+ }
+ }
+ for(int i=0;i<numrelations;i++) {
+ if(checkrelations(relations[i])) {
+ changed=true;
+ anychange=true;
+ }
+ }
+#ifdef REPAIR
+ /* Fix point only necessary if repairing */
+ if(!changed)
+#endif
+ break;
+ }
+ return anychange;
+}
+
+
+
+
+/* propagate the changes so that all the subset inclusion and partition
+ constraints are satisfied. */
+bool DomainRelation::checksubset(DomainSet *ds) {
+ // remove all elements in ds that are not contained by its superset
+ bool changed=false;
+ DomainSet *superset=getsuperset(ds);
+ WorkSet *ws=ds->getset();
+ WorkSet *wssuper=ds->getset();
+
+ void *ele=ws->firstelement();
+ while(ele!=NULL) {
+ if (!wssuper->contains(ele)) {
+ void *old=ele;
+ ele=ws->getnextelement(ele);
+ changed=true;
+#ifdef REPAIR
+ ws->removeobject(old);
+#endif
+ } else
+ ele=ws->getnextelement(ele);
+ }
+ /* Superset inclusion property guaranteed */
+
+
+ /* If an element is contained by more than one subset, remove it from
+ all subsets but the first one. If an element is not contained by
+ any subset, remove it from the superset */
+ if (ds->gettype()==DOMAINSET_PARTITION) {
+ ele=ws->firstelement();
+ while(ele!=NULL) {
+ int inccount=0;
+ for(int i=0;i<ds->getnumsubsets();i++) {
+ char *subsetname=ds->getsubset(i);
+ DomainSet *subset=getset(subsetname);
+ if (subset->getset()->contains(ele)) {
+ if (inccount==0)
+ inccount++;
+ else {
+ /* Partition exclusion property */
+ changed=true;
+#ifdef REPAIR
+ subset->getset()->removeobject(ele);
+#endif
+ }
+ }
+ }
+ if (inccount==0) {
+ /* Partition inclusion property */
+ changed=true;
+#ifdef REPAIR
+ ws->removeobject(ele);
+#endif
+ }
+ ele=ws->getnextelement(ele);
+ }
+ }
+ return changed;
+}
+
+
+
+bool DomainRelation::checkrelations(DRelation *dr) {
+ DomainSet *range=getset(dr->getrange());
+ DomainSet *domain=getset(dr->getdomain());
+ WorkSet *rangeset=NULL,*domainset=NULL;
+ bool changed=false;
+ if (range!=NULL)
+ rangeset=range->getset();
+ if (domain!=NULL)
+ domainset=domain->getset();
+ WorkRelation *rel=dr->getrelation();
+ Tuple ele=rel->firstelement();
+ while(!ele.isnull()) {
+ if((domainset!=NULL&&!domainset->contains(ele.left))||
+ (rangeset!=NULL&&!rangeset->contains(ele.right))) {
+ void *l=ele.left;
+ void *r=ele.right;
+ ele=rel->getnextelement(l,r);
+ changed=true;
+#ifdef REPAIR
+ rel->remove(l,r);
+#endif
+ } else {
+ ele=rel->getnextelement(ele.left,ele.right);
+ }
+ }
+ /* Relation is clean now also */
+ return changed;
+}
--- /dev/null
+// defines the sets and the relations used
+
+#ifndef DMODEL_H
+#define DMODEL_H
+
+#include "common.h"
+#include "classlist.h"
+
+#define DOMAINSET_SUBSET 1
+#define DOMAINSET_PARTITION 2
+#define DOMAINSET_TYPED 0x100
+
+// represents a set
+class DomainSet {
+ public:
+ DomainSet(char *name);
+ void settype(char *type);
+ void setsubsets(char **subsets, int numsubsets);
+ void setpartition(char **subsets, int numsubsets);
+ void print();
+ char *getname();
+ WorkSet *getset();
+ int getnumsubsets();
+ char *getsubset(int i);
+ int gettype();
+ char * getelementtype();
+ void reset();
+ private:
+ WorkSet *set; // the set itself
+ char *type; // the type of the elements in the set
+ char *setname; // the name of the set
+ int flag;
+ char ** subsets;// the subsets
+ int numsubsets;
+};
+
+
+
+
+#define DRELATION_SINGDOMAIN 0x1
+#define DRELATION_MANYDOMAIN 0x2
+#define DRELATION_SINGRANGE 0x10
+#define DRELATION_MANYRANGE 0x20
+
+// represents a relation
+class DRelation {
+ public:
+ DRelation(char *name, char *d, char *r, int t, bool);
+ void print();
+ char *getname();
+ WorkRelation *getrelation();
+ char *getdomain();
+ char *getrange();
+ WorkSet *gettokenrange();
+ void settokenrange(WorkSet *ws);
+ bool isstatic();
+ void reset();
+ private:
+ bool staticrel;
+ char *name;
+ char *domain;
+ char *range;
+ WorkSet *tokenrange; // the actual range, if the range is of type token
+ int type;
+ WorkRelation *relation;
+};
+
+
+
+// manages the entire collection of sets and relations
+class DomainRelation {
+ public:
+ DomainRelation(DomainSet **s, int ns, DRelation **r,int nr);
+ void print();
+ DomainSet * getset(char * setname);
+ DRelation * getrelation(char * relationname);
+ ~DomainRelation();
+ WorkSet * conflictdelsets(char *setname, char *boundset);
+ WorkSet * conflictaddsets(char *setname, char *boundset, model *m);
+ WorkSet * removeconflictdelsets(char *setname);
+ WorkSet * removeconflictaddsets(char *setname, model *m);
+ DomainSet * getsuperset(DomainSet *);
+ DomainSet * getsource(DomainSet *);
+ /* Tells what set we might get objects from for a given set */
+ void delfromsetmovetoset(Element *e,DomainSet *deletefromset,model *m);
+ void abstaddtoset(Element *e,DomainSet *addtoset,model *m);
+ void addtoset(Element *e,DomainSet *addtoset,model *m);
+ bool issupersetof(DomainSet *sub,DomainSet *super);
+ int getnumrelation();
+ DRelation * getrelation(int i);
+ bool fixstuff();
+ void reset();
+
+ private:
+ bool checkrelations(DRelation *dr);
+ bool checksubset(DomainSet *ds);
+ void addallsubsets(DomainSet *ds, WorkSet *ws);
+ void removefromthisset(Element *ele, DomainSet *ds,model *m);
+ Hashtable *settable, *relationtable;
+ DomainSet ** sets;
+ int numsets;
+ DRelation **relations;
+ int numrelations;
+};
+#endif
--- /dev/null
+#include <stdlib.h>
+#include "dparser.h"
+#include "list.h"
+#include "common.h"
+#include "token.h"
+#include "dmodel.h"
+
+Dparser::Dparser(Reader *r) {
+ reader=r;
+}
+
+DomainRelation *Dparser::parsesetrelation() {
+ List *sets=new List();
+ List *relations=new List();
+ for(Token t=reader->peakahead();t.token_type!=TOKEN_EOF;t=reader->peakahead()) {
+ switch(t.token_type) {
+ case TOKEN_EOL:
+ skiptoken();
+ break;
+ case TOKEN_SET:
+ sets->addobject(parseset());
+ break;
+ default:
+ relations->addobject(parserelation());
+ }
+ }
+ DomainSet **dsarray=new DomainSet*[sets->size()];
+ DRelation **drarray=new DRelation*[relations->size()];
+ sets->toArray((void **)dsarray);
+ relations->toArray((void **)drarray);
+ DomainRelation *dr=new DomainRelation(dsarray,sets->size(),
+ drarray,relations->size());
+ delete(sets);
+ delete(relations);
+ return dr;
+}
+
+DomainSet * Dparser::parseset() {
+ needtoken(TOKEN_SET);
+ Token name=reader->readnext();
+ DomainSet *ds=new DomainSet(copystr(name.str));
+ // Token istype=reader->peakahead();
+ // if (istype.token_type==TOKEN_OPENPAREN) {
+ //skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ ds->settype(copystr(reader->readnext().str));
+ needtoken(TOKEN_CLOSEPAREN);
+ //}
+ needtoken(TOKEN_COLON);
+ bool ispart=(reader->peakahead().token_type==TOKEN_PARTITION);
+ if (ispart)
+ skiptoken();
+ bool needset=false;
+ bool cont=true;
+ List *subsets=new List();
+ while(cont) {
+ Token t=reader->peakahead();
+ switch(t.token_type) {
+ case TOKEN_EOF:
+ if (!needset) {
+ printf("ERROR: Need set name");
+ exit(-1);
+ }
+ cont=false;
+ break;
+ case TOKEN_EOL:
+ if (!needset)
+ cont=false;
+ skiptoken();
+ break;
+ case TOKEN_BAR:
+ needset=true;
+ skiptoken();
+ break;
+ default:
+ subsets->addobject(copystr(t.str));
+ skiptoken();
+ needset=false;
+ }
+ }
+ char **carray=new char*[subsets->size()];
+ subsets->toArray((void **)carray);
+ if (ispart)
+ ds->setpartition(carray,subsets->size());
+ else
+ ds->setsubsets(carray,subsets->size());
+ delete(subsets);
+ return ds;
+}
+
+DRelation * Dparser::parserelation() {
+ Token name=reader->readnext();
+ bool isstat=false;
+ if (name.token_type==TOKEN_STATIC) {
+ isstat=true;
+ name=reader->readnext();
+ }
+ needtoken(TOKEN_COLON);
+ Token domain=reader->readnext();
+ needtoken(TOKEN_ARROW);
+ Token range=reader->readnext();
+ needtoken(TOKEN_OPENPAREN);
+ Token domainmult=reader->readnext();
+ needtoken(TOKEN_ARROW);
+ Token rangemult=reader->readnext();
+ needtoken(TOKEN_CLOSEPAREN);
+ int type=0;
+ if (domainmult.token_type==TOKEN_ONE)
+ type+=0x1;
+ else if (domainmult.token_type==TOKEN_MANY)
+ type+=0x2;
+ else error();
+
+ if (rangemult.token_type==TOKEN_ONE)
+ type+=0x10;
+ else if (rangemult.token_type==TOKEN_MANY)
+ type+=0x20;
+ else error();
+
+ return new DRelation(copystr(name.str),copystr(domain.str),
+ copystr(range.str),type,isstat);
+}
+
+void Dparser::error() {
+ printf("ERROR\n");
+ reader->error();
+ exit(-1);
+}
+
+void Dparser::skiptoken() {
+ reader->readnext();
+}
+
+void Dparser::needtoken(int token) {
+ Token t=reader->readnext();
+ if (!(t.token_type==token)) {
+ printf("Needed token: ");
+ tokenname(token);
+ printf("\n Got token: %s ",t.str);
+ tokenname(t.token_type);
+ error();
+ }
+}
--- /dev/null
+#ifndef DPARSER_H
+#define DPARSER_H
+#include "common.h"
+#include <iostream.h>
+#include <stdio.h>
+#include "classlist.h"
+
+class Dparser {
+ public:
+ Dparser(Reader *r);
+ DomainRelation * parsesetrelation();
+ private:
+ DomainSet * parseset();
+ DRelation * parserelation();
+ Reader *reader;
+ void skiptoken();
+ void needtoken(int);
+ void error();
+};
+#endif
--- /dev/null
+// provides an object wrapper around elementary types
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include "element.h"
+
+
+Element::Element() {
+ typevalue=ELEMENT_OBJECT;
+ token=NULL;
+ object=NULL;
+ integervalue=0;
+ bytevalue=0;
+ bitvalue=false;
+ shortvalue=0;
+ itemtype=NULL;
+}
+
+char * Element::gettoken() {
+ assert(typevalue==ELEMENT_TOKEN);
+ return token;
+}
+
+bool Element::isnumber() {
+ if ((type()==ELEMENT_INT)||
+ (type()==ELEMENT_BYTE)||
+ (type()==ELEMENT_SHORT))
+ return true;
+ else
+ return false;
+}
+
+Element::Element(void * objptr, structure * str) {
+ object=objptr;
+ typevalue=ELEMENT_OBJECT;
+ itemtype=str;
+ token=NULL;
+ integervalue=0;
+ bytevalue=0;
+ bitvalue=false;
+ shortvalue=0;
+}
+
+Element::Element(int value) {
+ typevalue=ELEMENT_INT;
+ integervalue=value;
+ object=NULL;
+ itemtype=NULL;
+ bytevalue=0;
+ bitvalue=false;
+ token=NULL;
+ shortvalue=0;
+}
+
+Element::Element(short value) {
+ typevalue=ELEMENT_SHORT;
+ shortvalue=value;
+ integervalue=0;
+ object=NULL;
+ itemtype=NULL;
+ bytevalue=0;
+ bitvalue=false;
+ token=NULL;
+}
+
+Element::Element(bool b) {
+ typevalue=ELEMENT_BIT;
+ bitvalue=b;
+ integervalue=0;
+ object=NULL;
+ itemtype=NULL;
+ bytevalue=0;
+ token=NULL;
+ shortvalue=0;
+}
+
+Element::Element(char byte) {
+ typevalue=ELEMENT_BYTE;
+ bytevalue=byte;
+ integervalue=0;
+ object=NULL;
+ itemtype=NULL;
+ token=NULL;
+ bitvalue=false;
+ shortvalue=0;
+}
+
+Element::Element(char * token) {/*Value destroyed by this destructor*/
+ this->token=token;
+ typevalue=ELEMENT_TOKEN;
+ integervalue=0;
+ bytevalue=0;
+ bitvalue=false;
+ object=NULL;
+ itemtype=NULL;
+ shortvalue=0;
+}
+
+Element::Element(Element * o) {
+ this->integervalue=o->integervalue;
+ this->bytevalue=o->bytevalue;
+ this->itemtype=o->itemtype;
+ this->token=copystr(o->token);
+ this->object=o->object;
+ this->typevalue=o->typevalue;
+ this->bitvalue=o->bitvalue;
+ this->shortvalue=o->shortvalue;
+}
+
+void Element::print() {
+ switch(typevalue) {
+ case ELEMENT_INT:
+#ifndef TOOL
+ printf("Int(%d)",integervalue);
+#else
+ printf("%d", integervalue);
+#endif
+ break;
+
+ case ELEMENT_SHORT:
+#ifndef TOOL
+ printf("Short(%d)",shortvalue);
+#else
+ printf("%d", shortvalue);
+#endif
+ break;
+
+ case ELEMENT_BIT:
+ if (bitvalue)
+#ifndef TOOL
+ printf("Bit(true)");
+#else
+ printf("true");
+#endif
+ else
+#ifndef TOOL
+ printf("Bit(false)");
+#else
+ printf("false");
+#endif
+ break;
+
+ case ELEMENT_BYTE:
+#ifndef TOOL
+ printf("Int(%c)",bytevalue);
+#else
+ printf("%c",bytevalue);
+#endif
+ break;
+
+ case ELEMENT_TOKEN:
+#ifndef TOOL
+ printf("Token(%s)",token);
+#else
+ printf("%s",token);
+#endif
+ break;
+
+ case ELEMENT_OBJECT:
+ printf("Object(%p)",object);
+ break;
+ }
+}
+
+unsigned int Element::hashCode() {
+ switch(typevalue) {
+ case ELEMENT_INT:
+ return integervalue;
+ case ELEMENT_SHORT:
+ return shortvalue;
+ case ELEMENT_BIT:
+ if (bitvalue)
+ return 1;
+ else
+ return 0;
+ case ELEMENT_BYTE:
+ return bytevalue;
+ case ELEMENT_TOKEN:
+ return hashstring(token);
+ case ELEMENT_OBJECT:
+ return (int)object;
+ }
+}
+
+bool Element::equals(ElementWrapper *other) {
+ if (other->type()!=typevalue)
+ return false;
+ switch(typevalue) {
+ case ELEMENT_INT:
+ return (this->integervalue==((Element *)other)->integervalue);
+ case ELEMENT_SHORT:
+ return (this->shortvalue==((Element *)other)->shortvalue);
+ case ELEMENT_BIT:
+ return (this->bitvalue==((Element *)other)->bitvalue);
+ case ELEMENT_BYTE:
+ return (this->bytevalue==((Element *)other)->bytevalue);
+ case ELEMENT_TOKEN:
+ return (equivalentstrings(token,((Element *)other)->token)==1);
+ case ELEMENT_OBJECT:
+ return object==((Element *)other)->object;
+ }
+}
+
+int Element::intvalue() {
+ switch(typevalue) {
+ case ELEMENT_INT:
+ return integervalue;
+ case ELEMENT_SHORT:
+ return shortvalue;
+ case ELEMENT_BYTE:
+ return bytevalue;
+ default:
+ printf("Illegal int conversion on Element\n");
+ exit(-1);
+ }
+}
+
+short Element::getshortvalue() {
+ assert(typevalue==ELEMENT_SHORT);
+ return shortvalue;
+}
+
+char Element::getbytevalue() {
+ assert(typevalue==ELEMENT_BYTE);
+ return bytevalue;
+}
+
+bool Element::getboolvalue() {
+ assert(typevalue==ELEMENT_BIT);
+ return bitvalue;
+}
+
+void * Element::getobject() {
+ assert(typevalue==ELEMENT_OBJECT);
+ return object;
+}
+
+int Element::type() {
+ return typevalue;
+}
+
+structure * Element::getstructure() {
+ return itemtype;
+}
+
+Element::~Element() {
+ if(typevalue==ELEMENT_TOKEN)
+ delete[] token;
+}
+
+unsigned int hashelement(ElementWrapper *e) {
+ return e->hashCode();
+}
+
+int elementequals(ElementWrapper *e1, ElementWrapper *e2) {
+ return e1->equals(e2);
+}
--- /dev/null
+// provides an object wrapper around elementary types
+
+
+#ifndef ELEMENT_H
+#define ELEMENT_H
+#include "common.h"
+#include "classlist.h"
+
+class ElementWrapper;
+
+#define ELEMENT_INT 1
+#define ELEMENT_BIT 2
+#define ELEMENT_BYTE 3
+#define ELEMENT_TOKEN 4
+#define ELEMENT_OBJECT 5
+#define ELEMENT_FTUPLE 6
+#define ELEMENT_SHORT 7
+
+class ElementWrapper {
+ public:
+ virtual unsigned int hashCode()=0;
+ virtual bool equals(ElementWrapper *other)=0;
+ virtual int type()=0;
+ private:
+};
+
+
+class Element:public ElementWrapper {
+ public:
+ Element();
+ Element(int value);
+ Element(short value);
+ Element(bool b);
+ Element(char byte);
+ Element(char * token);
+ Element(Element * o);
+ unsigned int hashCode();
+ bool equals(ElementWrapper *other);
+ int intvalue();
+ short getshortvalue();
+ char getbytevalue();
+ bool getboolvalue();
+ bool isnumber();
+ void * getobject();
+ int type();
+ structure * getstructure();
+ Element(void * objptr, structure * str);
+ char * gettoken();
+ ~Element();
+ void print();
+
+ private:
+ char *token;
+ void *object;
+ int typevalue;
+ short shortvalue;
+ int integervalue;
+ char bytevalue;
+ bool bitvalue;
+ structure *itemtype;
+};
+
+unsigned int hashelement(ElementWrapper *e);
+
+int elementequals(ElementWrapper *e1, ElementWrapper *e2);
+
+#endif
--- /dev/null
+#include <stdlib.h>
+#include "classlist.h"
+#include "fieldcheck.h"
+#include "common.h"
+#include "set.h"
+#include "dmodel.h"
+#include "omodel.h"
+#include "model.h"
+#include "Hashtable.h"
+#include "normalizer.h"
+
+FieldCheck::FieldCheck(model *m) {
+ cptoreqs=NULL;
+ nftoprovides=NULL;
+ globalmodel=m;
+ propertytonf=NULL;
+}
+
+bool FieldCheck::testsatisfy(WorkSet *satisfies, FieldTuple *ft) {
+ FieldTuple *copy=new FieldTuple(ft);
+ bool sat=false;
+ while(!sat&©!=NULL) {
+ if(satisfies->contains(copy)) {
+ sat=true;
+ break;
+ }
+ copy->set=globalmodel->getdomainrelation()->getsuperset(globalmodel->getdomainrelation()->getset(copy->set))->getname();
+ }
+ delete(copy);
+ return sat;
+}
+
+int FieldCheck::getindexthatprovides(char *set, char *relation) {
+ FieldTuple *copy=new FieldTuple(set,relation);
+ while(copy!=NULL) {
+ if(propertytonf->contains(copy)) {
+ /* Found!!! Do stuff */
+ NormalForm *nf=(NormalForm *)propertytonf->get(copy);
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ if (nf==globalmodel->getnormalform(i)) {
+ delete(copy);
+ return i;
+ }
+ }
+ printf("Error in getindexthatprovides\n");
+ exit(-1);
+ }
+ copy->set=globalmodel->getdomainrelation()->getsuperset(globalmodel->getdomainrelation()->getset(copy->set))->getname();
+ }
+ delete(copy);
+ return -1; /* Couldn't find...too bad */
+}
+
+void FieldCheck::analyze() {
+ WorkSet *satisfied=new WorkSet();
+ propertytonf=new Hashtable(NULL,NULL);
+ bool change=true;
+ bool allsatisfied=true;
+ FieldTuple *badft=NULL;
+ while(change) {
+ allsatisfied=true;
+ change=false;
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ NormalForm *nf=globalmodel->getnormalform(i);
+ bool gotallreqs=true;
+ for(int j=0;j<nf->getnumsentences();j++) {
+ CoerceSentence *cs=nf->getsentence(j);
+ for (int k=0;k<cs->getnumpredicates();k++) {
+ CoercePredicate *cp=cs->getpredicate(k);
+ WorkSet *reqs=(WorkSet *)cptoreqs->get(cp);
+ if (reqs!=NULL) {
+ for(FieldTuple *ft=(FieldTuple *)reqs->firstelement();ft!=NULL;
+ ft=(FieldTuple*)reqs->getnextelement(ft)) {
+ if (!testsatisfy(satisfied,ft)) {
+ gotallreqs=false;
+ allsatisfied=false;
+ badft=ft;
+ break;
+ }
+ }
+ }
+ if(!gotallreqs)
+ break;
+ }
+ if (gotallreqs) {
+ WorkSet *provides=(WorkSet *)nftoprovides->get(nf);
+ if(provides!=NULL) {
+ for(FieldTuple *ft=(FieldTuple *)provides->firstelement();ft!=NULL;
+ ft=(FieldTuple*)provides->getnextelement(ft)) {
+ if(!testsatisfy(satisfied,ft)) {
+ /* something to add */
+ satisfied->addobject(ft);
+ propertytonf->put(ft,nf);
+ change=true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!allsatisfied) {
+ printf("Some relations can't be established:<%s,%s>",badft->relation,badft->set);
+ exit(-1);
+ }
+ delete(satisfied);
+}
+
+void FieldCheck::buildmaps() {
+ cptoreqs=new Hashtable(NULL,NULL);
+ nftoprovides=new Hashtable(NULL,NULL);
+
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ NormalForm *nf=globalmodel->getnormalform(i);
+ Constraint *c=globalmodel->getconstraint(i);
+ WorkSet *old=NULL;
+ for(int j=0;j<nf->getnumsentences();j++) {
+ WorkSet *curr=new WorkSet();
+ CoerceSentence *cs=nf->getsentence(j);
+ for (int k=0;k<cs->getnumpredicates();k++) {
+ CoercePredicate *cp=cs->getpredicate(k);
+ WorkSet *wr=requireswhat(c,cp);
+ if (wr!=NULL)
+ cptoreqs->put(cp,wr);
+ FieldTuple *ft=provideswhat(c,cp);
+ if(ft!=NULL)
+ curr->addobject(ft);
+ else
+ delete(ft);
+ }
+ if (old==NULL)
+ old=curr;
+ else {
+ for(FieldTuple *ft=(FieldTuple *)old->firstelement();ft!=NULL;
+ ft=(FieldTuple *)old->getnextelement(ft)) {
+ if (!curr->contains(ft))
+ old->removeobject(ft);
+ }
+ delete(curr);
+ }
+ }
+ if(old!=NULL) {
+ if(old->isEmpty())
+ delete old;
+ else
+ nftoprovides->put(nf, old);
+ }
+ }
+}
+
+WorkSet * FieldCheck::requireswhat(Constraint *c,CoercePredicate *cp) {
+ Predicate *p=cp->getpredicate();
+ int type=p->gettype();
+ if (type==PREDICATE_LT ||
+ type==PREDICATE_LTE ||
+ type==PREDICATE_EQUALS ||
+ type==PREDICATE_GT ||
+ type==PREDICATE_GTE) {
+ WorkSet *ws=new WorkSet();
+ Elementexpr *ee=p->geteleexpr();
+ processee(ws,c,ee);
+ if (ws->isEmpty()) {
+ delete(ws);
+ return NULL;
+ } else return ws;
+ } else return NULL;
+}
+
+void FieldCheck::processee(WorkSet *ws, Constraint *c, Elementexpr *ee) {
+ switch(ee->gettype()) {
+ case ELEMENTEXPR_SUB:
+ case ELEMENTEXPR_ADD:
+ case ELEMENTEXPR_MULT:
+ processee(ws,c,ee->getleft());
+ processee(ws,c,ee->getright());
+ return;
+ case ELEMENTEXPR_RELATION: {
+ /* Interesting case */
+ char *rel=ee->getrelation()->getname();
+ Elementexpr *left=ee->getleft();
+ int tleft=left->gettype();
+ if (tleft==ELEMENTEXPR_LABEL) {
+ ws->addobject(new FieldTuple(rel,getset(c, left->getlabel()->label())));
+ } else if (tleft==ELEMENTEXPR_RELATION) {
+ DRelation *drl=globalmodel->getdomainrelation()->getrelation(left->getrelation()->getname());
+ char *rangeofl=drl->getrange();
+ ws->addobject(new FieldTuple(rel,rangeofl));
+ } else {
+ ee->print();
+ printf("Can't determine domain\n");
+ exit(-1);
+ }
+ }
+ return;
+ default:
+ return;
+ }
+}
+
+bool FieldCheck::setok(Constraint *c, char *set) {
+ for(int i=0;i<c->numquants();i++) {
+ Quantifier *q=c->getquant(i);
+ char *qs=q->getset()->getname();
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ DomainSet *iset=dr->getset(set);
+ DomainSet *qset=dr->getset(qs);
+ if (dr->issupersetof(iset,qset))
+ return false;
+ }
+ return true;
+}
+
+FieldTuple * FieldCheck::provideswhat(Constraint *c,CoercePredicate *cp) {
+ if (cp->getcoercebool())
+ return NULL;
+ Predicate *p=cp->getpredicate();
+ switch(p->gettype()) {
+ case PREDICATE_LT:
+ case PREDICATE_LTE:
+ case PREDICATE_EQUALS:
+ case PREDICATE_GTE:
+ case PREDICATE_GT: {
+ char *relation=p->getvalueexpr()->getrelation()->getname();
+ char *var=p->getvalueexpr()->getlabel()->label();
+ char *set=getset(c,var);
+ if (setok(c,set)) {
+ return new FieldTuple(relation,set);
+ } else
+ return NULL;
+ }
+ case PREDICATE_SET:
+ case PREDICATE_EQ1:
+ case PREDICATE_GTE1: {
+ Setexpr *se=p->getsetexpr();
+ if (se->gettype()==SETEXPR_REL) {
+ char *relation=se->getrelation()->getname();
+ char *var=se->getlabel()->label();
+ char *set=getset(c,var);
+ if (setok(c,set)) {
+ return new FieldTuple(relation,set);
+ } else return NULL;
+ }
+ return NULL;
+ }
+ default:
+ return NULL;
+ }
+}
+
+char *getset(Constraint *c, char *var) {
+ for (int i=0;i<c->numquants();i++) {
+ Quantifier *q=c->getquant(i);
+ if (equivalentstrings(var,q->getlabel()->label())) {
+ return q->getset()->getname();
+ }
+ }
+ return NULL;
+}
+
+unsigned int FieldTuple::hashCode() {
+ return hashstring(relation)^hashstring(set);
+}
+
+bool FieldTuple::equals(ElementWrapper *other) {
+ if (other->type()!=ELEMENT_FTUPLE)
+ return false;
+ FieldTuple *oft=(FieldTuple *)other;
+ if (equivalentstrings(relation, oft->relation)&&
+ equivalentstrings(set,oft->set))
+ return true;
+ else
+ return false;
+}
+
+int FieldTuple::type() {
+ return ELEMENT_FTUPLE;
+}
+
+FieldTuple::FieldTuple(char * r, char *s) {
+ relation=r;
+ set=s;
+}
+
+FieldTuple::FieldTuple(FieldTuple *o) {
+ this->relation=o->relation;
+ this->set=o->set;
+}
--- /dev/null
+#ifndef Fieldcheck_H
+#define Fieldcheck_H
+#include "classlist.h"
+#include "element.h"
+
+class FieldCheck {
+ public:
+ FieldCheck(model *m);
+ void analyze();
+ void buildmaps();
+ int getindexthatprovides(char *set, char *relation);
+ private:
+ bool setok(Constraint *c, char *set);
+ bool testsatisfy(WorkSet *satisfies, FieldTuple *ft);
+ WorkSet * requireswhat(Constraint *c,CoercePredicate *cp);
+ void processee(WorkSet *ws, Constraint *c, Elementexpr *ee);
+ FieldTuple * provideswhat(Constraint *c,CoercePredicate *cp);
+ model *globalmodel;
+ Hashtable *cptoreqs;
+ Hashtable *propertytonf;
+ Hashtable *nftoprovides;
+};
+
+char *getset(Constraint *c, char *var);
+
+class FieldTuple:public ElementWrapper {
+ public:
+ FieldTuple(FieldTuple *o);
+ unsigned int hashCode();
+ bool equals(ElementWrapper *other);
+ int type();
+
+ FieldTuple(char * r, char *s);
+ char * relation;
+ char * set;
+};
+#endif
+
--- /dev/null
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include "file.h"
+extern "C" {
+#include "test.h"
+}
+#include "Hashtable.h"
+#include "model.h"
+#include "element.h"
+
+char *dstring="d\0";
+struct filedesc files[MAXFILES];
+struct InodeBitmap ib;
+struct BlockBitmap bb;
+int bbbptr,ibbptr,itbptr,rdiptr;
+int main(int argc, char **argv) {
+ for(int i=0;i<MAXFILES;i++)
+ files[i].used=false;
+ switch(argv[1][0]) {
+ case '0': createdisk();
+ return 1;
+ case '1': {
+ struct block * ptr=mountdisk("disk");
+ for(int i=0;i<145;i++) {
+ char filename[10];
+ sprintf(filename,"fil%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0;j<90;j++) {
+ for(int i=0;i<145;i++) {
+ char *buf="01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123";
+ writefile(ptr,i,buf,122);
+ }
+ }
+ for(int i=0;i<145;i++) {
+ closefile(ptr,i);
+ }
+ unmountdisk(ptr);
+ break;
+ }
+ case '2': {
+ struct block * ptr=chmountdisk("disk");
+ initializeanalysis();
+ Hashtable *env=exportmodel->gethashtable();
+ alloc(ptr,LENGTH);
+ addmapping(dstring,ptr,"Disk");
+ // env->put(dstring,new Element(ptr,exportmodel->getstructure("Disk")));//should be of badstruct
+ doanalysis();
+ dealloc(ptr);
+ chunmountdisk(ptr);
+ break;
+ }
+ case '3': {
+ struct block * ptr=mountdisk("disk");
+ printdirectory(ptr);
+ for(int i=1;i<145;i++) {
+ char filename[10];
+ sprintf(filename,"fil%d",i);
+ printfile(filename,ptr);
+ }
+ unmountdisk(ptr);
+ break;
+ }
+ case '4': {
+ struct block * ptr=mountdisk("disk");
+ for(int i=145;i>1;i--) {
+ char filename[10];
+ sprintf(filename,"fil%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0;j<90;j++) {
+ for(int i=145;i>1;i--) {
+ char *buf="01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123";
+ writefile(ptr,i,buf,122);
+ }
+ }
+ for(int i=145;i>1;i--) {
+ closefile(ptr,i);
+ }
+ unmountdisk(ptr);
+ break;
+ }
+ case '5': {
+ struct block * ptr=mountdisk("disk");
+ for(int i=145;i>=0;i--) {
+ char filename[10];
+ sprintf(filename,"fil%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0;j<6000;j++) {
+ for(int i=145;i>=0;i--) {
+ char name[10];
+ int len=sprintf(name, "%d ",i);
+ writefile(ptr,i,name,len);
+ }
+ }
+ for(int i=145;i>=0;i--) {
+ closefile(ptr,i);
+ }
+ for(int i=145;i>=0;i--) {
+ char filename[10];
+ sprintf(filename,"fil%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0;j<400;j++) {
+ for(int i=145;i>=0;i--) {
+ int l=0;
+ char name[10];
+ int len=sprintf(name, "%d ",i);
+ readfile(ptr,i,name,len);
+ sscanf(name, "%d ", &l);
+ if (l!=i) {
+ printf("ERROR in benchmark\n");
+ }
+ }
+ }
+ for(int i=145;i>=0;i--) {
+ closefile(ptr,i);
+ }
+ unmountdisk(ptr);
+ }
+ break;
+ case '6': {
+ {
+ struct block * ptr=chmountdisk("disk");
+ initializeanalysis();
+ Hashtable *env=exportmodel->gethashtable();
+ alloc(ptr,LENGTH);
+ addmapping(dstring,ptr,"Disk");
+ doanalysis();
+ dealloc(ptr);
+ chunmountdisk(ptr);
+ }
+ struct block * ptr=mountdisk("disk");
+ for(int i=145;i>=0;i--) {
+ char filename[10];
+ sprintf(filename,"fil%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0;j<6000;j++) {
+ for(int i=145;i>=0;i--) {
+ char name[10];
+ int len=sprintf(name, "%d ",i);
+ writefile(ptr,i,name,len);
+ }
+ }
+ for(int i=145;i>=0;i--) {
+ closefile(ptr,i);
+ }
+ for(int i=145;i>=0;i--) {
+ char filename[10];
+ sprintf(filename,"fil%d",i);
+ openfile(ptr,filename);
+ }
+ for(int j=0;j<400;j++) {
+ for(int i=145;i>=0;i--) {
+ int l=0;
+ char name[10];
+ int len=sprintf(name, "%d ",i);
+ readfile(ptr,i,name,len);
+ sscanf(name, "%d ", &l);
+ if (l!=i) {
+ printf("ERROR in benchmark\n");
+ }
+ }
+ }
+ for(int i=145;i>=0;i--) {
+ closefile(ptr,i);
+ }
+ unmountdisk(ptr);
+ }
+ }
+}
+
+struct block * chmountdisk(char *filename) {
+ int fd=open(filename,O_CREAT|O_RDWR);
+ struct block *ptr=(struct block *) mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
+ return ptr;
+}
+
+void chunmountdisk(struct block *vptr) {
+ int val=munmap(vptr,LENGTH);
+}
+
+struct block * mountdisk(char *filename) {
+ int fd=open(filename,O_CREAT|O_RDWR);
+ struct block *ptr=(struct block *) mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
+ struct SuperBlock *sb=(struct SuperBlock *) &ptr[0];
+ struct GroupBlock *gb=(struct GroupBlock *) &ptr[1];
+ bbbptr=gb->BlockBitmapBlock;
+ ibbptr=gb->InodeBitmapBlock;
+ itbptr=gb->InodeTableBlock;
+ rdiptr=sb->RootDirectoryInode;
+
+ struct InodeBitmap *ibb=(struct InodeBitmap *) &ptr[ibbptr];
+ for(int i=0;i<(NUMINODES/8+1);i++)
+ ib.inode[i]=ibb->inode[i];
+ struct BlockBitmap *bbb=(struct BlockBitmap *) &ptr[bbbptr];
+ for(int i=0;i<(NUMBLOCK/8+1);i++)
+ bb.blocks[i]=bbb->blocks[i];
+ return ptr;
+}
+
+void unmountdisk(struct block *vptr) {
+ struct InodeBitmap *ibb=(struct InodeBitmap *) &vptr[ibbptr];
+ for(int i=0;i<(NUMINODES/8+1);i++)
+ ibb->inode[i]=ib.inode[i];
+
+ struct BlockBitmap *bbb=(struct BlockBitmap *) &vptr[bbbptr];
+ for(int i=0;i<(NUMBLOCK/8+1);i++)
+ bbb->blocks[i]=bb.blocks[i];
+ int val=munmap(vptr,LENGTH);
+}
+
+void printdirectory(struct block *ptr) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/128;j++) {
+ if (db->entries[j].name[0]!=0) {
+ /* lets finish */
+ printf("%s %d inode %d bytes\n",db->entries[j].name, db->entries[j].inodenumber,itb->entries[db->entries[j].inodenumber].filesize);
+ }
+ }
+ }
+}
+
+void printfile(char *filename, struct block *ptr) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/128;j++) {
+ if (db->entries[j].name[0]!=0) {
+ if(strcmp(filename,db->entries[j].name)==0) {
+ /* Found file */
+ int inode=db->entries[j].inodenumber;
+
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<((itb->entries[inode].filesize+BLOCKSIZE-1)/BLOCKSIZE);i++) {
+ struct block *b=&ptr[itb->entries[inode].Blockptr[i]];
+ write(0,b,BLOCKSIZE);
+ }
+ }
+ }
+ }
+ }
+}
+
+void removefile(char *filename, struct block *ptr) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/128;j++) {
+ if (db->entries[j].name[0]!=0) {
+ if(strcmp(filename,db->entries[j].name)==0) {
+ /* Found file */
+ db->entries[j].name[0]=0; //Delete entry
+ int inode=db->entries[j].inodenumber;
+
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ itb->entries[inode].referencecount--;
+
+ if (itb->entries[inode].referencecount==0) {
+ for(int i=0;i<((itb->entries[inode].filesize+BLOCKSIZE-1)/BLOCKSIZE);i++) {
+ int blocknum=itb->entries[inode].Blockptr[i];
+ bb.blocks[blocknum/8]^=(1<<(blocknum%8));
+ }
+ ib.inode[inode/8]^=(1<<(inode%8));
+ }
+ }
+ }
+ }
+ }
+}
+
+void createlink(struct block *ptr,char *filename, char *linkname) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/128;j++) {
+ if (db->entries[j].name[0]!=0) {
+ if(strcmp(filename,db->entries[j].name)==0) {
+ /* Found file */
+ int inode=db->entries[j].inodenumber;
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
+ itb->entries[inode].referencecount++;
+ addtode(ptr, inode, linkname);
+ }
+ }
+ }
+ }
+}
+
+void closefile(struct block *ptr, int fd) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
+
+
+ msync(&itb->entries[fd],sizeof(DirectoryEntry),MS_SYNC);
+ files[fd].used=false;
+}
+
+bool writefile(struct block *ptr, int fd, char *s) {
+ return (writefile(ptr,fd,s,1)==1);
+}
+
+int writefile(struct block *ptr, int fd, char *s, int len) {
+ struct filedesc *tfd=&files[fd];
+ if (tfd->used==false)
+ return -1;
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
+ int filelen=itb->entries[tfd->inode].filesize;
+ if ((12*BLOCKSIZE-tfd->offset)<len)
+ len=12*BLOCKSIZE-tfd->offset;
+ for(int i=0;i<len;i++) {
+ int nbuffer=tfd->offset/BLOCKSIZE;
+ int noffset=tfd->offset%BLOCKSIZE;
+ if (tfd->offset>=filelen) {
+ if (noffset==0) {
+ int bptr=getblock(ptr);
+ if (bptr==-1) {
+ if (itb->entries[files[fd].inode].filesize<files[fd].offset)
+ itb->entries[files[fd].inode].filesize=files[fd].offset;
+ return i;
+ }
+ itb->entries[tfd->inode].Blockptr[nbuffer]=bptr;
+ }
+ }
+ int block=itb->entries[tfd->inode].Blockptr[nbuffer];
+ char *fchar=(char *)&ptr[block];
+ int tocopy=len-i;
+ if (tocopy>(BLOCKSIZE-noffset))
+ tocopy=BLOCKSIZE-noffset;
+ memcpy(&fchar[noffset],&s[i],tocopy);
+ msync(&fchar[noffset],tocopy,MS_SYNC);
+ i+=tocopy;
+ tfd->offset+=tocopy;
+ }
+ if (itb->entries[files[fd].inode].filesize<files[fd].offset)
+ itb->entries[files[fd].inode].filesize=files[fd].offset;
+ return len;
+}
+
+
+char readfile(struct block *ptr, int fd) {
+ char array[1];
+ if (readfile(ptr,fd,array,1)==1)
+ return array[0];
+ else
+ return EOF;
+}
+
+int readfile(struct block *ptr, int fd, char *buf, int len) {
+ struct filedesc *tfd=&files[fd];
+ if (tfd->used==false)
+ return -1;
+
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ int filelen=itb->entries[tfd->inode].filesize;
+ if ((filelen-tfd->offset)<len)
+ len=filelen-tfd->offset;
+ for(int i=0;i<len;) {
+ int nbuffer=tfd->offset/BLOCKSIZE;
+ int noffset=tfd->offset%BLOCKSIZE;
+ int block=itb->entries[tfd->inode].Blockptr[nbuffer];
+ char *fchar=(char *)&ptr[block];
+ int tocopy=len-i;
+ if (tocopy>(BLOCKSIZE-noffset))
+ tocopy=BLOCKSIZE-noffset;
+ memcpy(&buf[i],&fchar[noffset],tocopy);
+ i+=tocopy;
+ tfd->offset+=tocopy;
+ }
+ return len;
+}
+
+int openfile(struct block *ptr, char *filename) {
+ /* Locate fd */
+ int fd=-1;
+ for(int k=0;k<MAXFILES;k++) {
+ /* Found file */
+ if(!files[k].used) {
+ fd=k;
+ files[fd].used=true;
+ break;
+ }
+ }
+ if (fd==-1) return fd;
+
+ /* Check to see if file exists*/
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/128;j++) {
+ if (db->entries[j].name[0]!=0) {
+ if(strcmp(filename,db->entries[j].name)==0) {
+ files[fd].inode=db->entries[j].inodenumber;
+ files[fd].offset=0;
+ return fd;
+ }
+ }
+ }
+ }
+ /* Create file */
+
+ int inode=getinode(ptr);
+ if (inode==-1) {
+ files[fd].used=false;
+ return -1;
+ }
+ itb->entries[inode].filesize=0;
+ itb->entries[inode].referencecount=1;
+
+ addtode(ptr, inode, filename);
+ files[fd].inode=inode;
+ files[fd].offset=0;
+ return fd;
+}
+
+void createfile(struct block *ptr,char *filename, char *buf,int buflen) {
+ int fd=openfile(ptr,filename);
+ writefile(ptr,fd,buf,buflen);
+ closefile(ptr,fd);
+}
+
+void addtode(struct block *ptr, int inode, char * filename) {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[itbptr];
+ for(int i=0;i<12;i++) {
+ struct DirectoryBlock *db=(struct DirectoryBlock *) &ptr[itb->entries[rdiptr].Blockptr[i]];
+ for(int j=0;j<BLOCKSIZE/128;j++) {
+ if (db->entries[j].name[0]==0) {
+ /* lets finish */
+ strncpy(db->entries[j].name,filename,124);
+ db->entries[j].inodenumber=inode;
+ msync(&db->entries[j],sizeof(DirectoryEntry),MS_SYNC);
+ return;
+ }
+ }
+ }
+}
+
+int getinode(struct block *ptr) {
+ for(int i=0;i<NUMINODES;i++) {
+ if (!(ib.inode[i/8]&(1<<(i%8)))) {
+ ib.inode[i/8]=ib.inode[i/8]|(1<<(i%8));
+ return i;
+ }
+ }
+ return -1;
+}
+
+int getblock(struct block * ptr) {
+ for(int i=0;i<NUMBLOCK;i++) {
+ if (!(bb.blocks[i/8]&(1<<(i%8)))) {
+ bb.blocks[i/8]=bb.blocks[i/8]|(1<<(i%8));
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+
+void createdisk() {
+ int blocksize=BLOCKSIZE;
+ int numblocks=NUMBLOCK;
+ int fd=open("disk",O_CREAT|O_RDWR|O_TRUNC);
+ char *buf=(char *)calloc(1,blocksize);
+ for(int i=0;i<numblocks;i++) {
+ write(fd,buf,blocksize);
+ }
+ free(buf);
+ void *vptr=mmap(NULL,LENGTH,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED,fd,0);
+ struct block *ptr=(struct block *)vptr;
+ {
+ struct SuperBlock * sb=(struct SuperBlock*) &ptr[0];
+ sb->FreeBlockCount=BLOCKSIZE-5;
+ sb->FreeInodeCount=NUMINODES-1;
+ sb->NumberofInodes=NUMINODES;
+ sb->NumberofBlocks=NUMBLOCK;
+ sb->RootDirectoryInode=0;
+ sb->blocksize=BLOCKSIZE;
+ }
+ {
+ struct GroupBlock * gb=(struct GroupBlock *) &ptr[1];
+ gb->BlockBitmapBlock=2;
+ gb->InodeBitmapBlock=3;
+ gb->InodeTableBlock=4;
+ gb->GroupFreeBlockCount=BLOCKSIZE-5;
+ gb->GroupFreeInodeCount=NUMINODES-1;
+ }
+ {
+ struct BlockBitmap * bb=(struct BlockBitmap *) &ptr[2];
+ for(int i=0;i<(5+12);i++)
+ bb->blocks[i/8]=bb->blocks[i/8]|(1<<(i%8));
+ }
+ {
+ struct InodeBitmap * ib=(struct InodeBitmap *) &ptr[3];
+ ib->inode[0]=1;
+ }
+ {
+ struct InodeBlock * itb=(struct InodeBlock *) &ptr[4];
+ itb->entries[0].filesize=12*BLOCKSIZE;
+ for(int i=0;i<12;i++)
+ itb->entries[0].Blockptr[i]=i+5;
+ itb->entries[0].referencecount=1;
+ }
+
+ int val=munmap(vptr,LENGTH);
+ if (val!=0)
+ printf("Error!\n");
+}
+
--- /dev/null
+#ifndef FILE_H
+#define FILE_H
+
+#define BLOCKSIZE 8192
+#define NUMBLOCK 1024
+#define LENGTH BLOCKSIZE*NUMBLOCK
+#define NUMINODES BLOCKSIZE/56
+#define NUMFILES 100
+
+struct block {
+ char array[BLOCKSIZE];
+};
+
+
+struct SuperBlock {
+ int FreeBlockCount;
+ int FreeInodeCount;
+ int NumberofBlocks;
+ int NumberofInodes;
+ int RootDirectoryInode;
+ int blocksize;
+};
+
+
+struct GroupBlock {
+ int BlockBitmapBlock;
+ int InodeBitmapBlock;
+ int InodeTableBlock;
+ int GroupFreeBlockCount;
+ int GroupFreeInodeCount;
+};
+
+
+struct BlockBitmap {
+ char blocks[NUMBLOCK/8+1];
+};
+
+
+struct InodeBitmap {
+ char inode[NUMINODES/8+1];
+};
+
+
+struct Inode {
+ int filesize;
+ int Blockptr[12];
+ int referencecount;
+};
+
+
+//the inode table
+struct InodeBlock {
+ struct Inode entries[NUMINODES];
+};
+
+
+#define DIRECTORYENTRYSIZE 128
+struct DirectoryEntry {
+ char name[124];
+ int inodenumber;
+};
+
+
+
+struct DirectoryBlock {
+ struct DirectoryEntry entries[BLOCKSIZE/128];
+};
+
+
+
+
+
+void createdisk();
+void createfile(struct block *ptr,char *filename, char *buf,int buflen);
+void addtode(struct block *ptr, int inode, char * filename);
+int getinode(struct block *ptr);
+int getblock(struct block * ptr);
+
+void removefile(char *filename, struct block *ptr);
+void createlink(struct block *ptr,char *filename, char *linkname);
+struct block * chmountdisk(char *filename);
+void chunmountdisk(struct block *vptr);
+struct block * mountdisk(char *filename);
+void unmountdisk(struct block *vptr);
+void closefile(struct block *ptr, int fd);
+bool writefile(struct block *ptr, int fd, char *s);
+int writefile(struct block *ptr, int fd, char *s, int len);
+char readfile(struct block *ptr, int fd);
+int readfile(struct block *ptr, int fd, char *buf, int len);
+int openfile(struct block *ptr, char *filename);
+
+void printdirectory(struct block *ptr);
+void printfile(char *filename, struct block *ptr);
+void printinodeblock(struct block* ptr);
+
+
+#define MAXFILES 300
+struct filedesc {
+ int inode;
+ int offset;
+ bool used;
+};
+#endif
+
--- /dev/null
+#include "list.h"
+//#include "dmalloc.h"
+
+List::List() {
+ array=new void*[INITIAL_LIST_SIZE];
+ length=0;
+ arraysize=INITIAL_LIST_SIZE;
+}
+
+List::~List() {
+ delete[](array);
+}
+
+void List::addobject(void *object) {
+ if ((length+1)>arraysize) {
+ void **oldarray=array;
+ int oldarraysize=arraysize;
+ arraysize*=2;
+ array=new void*[arraysize];
+ for(int i=0;i<length;i++)
+ array[i]=oldarray[i];
+ delete[](oldarray);
+ }
+ array[length++]=object;
+}
+
+void List::toArray(void **writearray) {
+ for(int i=0;i<length;i++) {
+ writearray[i]=array[i];
+ }
+}
+
+unsigned int List::size() {
+ return length;
+}
--- /dev/null
+#ifndef LIST_H
+#define LIST_H
+
+class List {
+ public:
+ List();
+ ~List();
+ void addobject(void *);
+ void toArray(void **);
+ unsigned int size();
+
+
+ private:
+ void **array;
+ unsigned int arraysize;
+ unsigned int length;
+};
+
+#define INITIAL_LIST_SIZE 10
+#endif
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fstream.h>
+#include <iostream.h>
+#include "classlist.h"
+#include "model.h"
+#include "token.h"
+#include "typeparser.h"
+#include "dparser.h"
+#include "aparser.h"
+#include "cparser.h"
+#include "oparser.h"
+#include "rparser.h"
+#include "dmodel.h"
+#include "omodel.h"
+#include "amodel.h"
+#include "tmodel.h"
+#include "list.h"
+#include "processabstract.h"
+#include "processobject.h"
+#include "processconcrete.h"
+#include "normalizer.h"
+#include "Hashtable.h"
+#include "element.h"
+#include "bitreader.h"
+#include "DefaultGuidance2.h"
+#include "DefaultGuidance.h"
+#include "DefaultGuidance3.h"
+#include "repair.h"
+#include "fieldcheck.h"
+#include "tmap.h"
+#include "string.h"
+#include "set.h"
+#include <sys/time.h>
+
+Hashtable * model::gethashtable() {
+ return env;
+}
+
+bitreader * model::getbitreader() {
+ return br;
+}
+
+Guidance * model::getguidance() {
+ return guidance;
+}
+
+model::model(char *abstractfile, char *modelfile, char *spacefile, char *structfile, char *concretefile, char *rangefile)
+{
+ parsestructfile(structfile);
+
+
+ //Hashtable first for lookups
+ env=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
+ // env->put(&bstring,new Element(&badstruct,getstructure("arrayofstructs")));//should be of badstruct
+ parseabstractfile(abstractfile);
+ parsemodelfile(modelfile);
+ parsespacefile(spacefile);
+ parseconcretefile(concretefile);
+ // parserangefile(rangefile);
+ // committing out because of memory problems
+
+ br=new bitreader(this,env);
+ guidance=new DefGuidance(this); // for the file system benchmark
+
+#ifdef REPAIR
+ repair=new Repair(this);
+ if (!repair->analyzetermination()) {
+#ifdef DEBUGMESSAGES
+ printf("Constraint set might not terminate and can't be repaired!\n");
+#endif
+ exit(-1);
+ }
+ fc=new FieldCheck(this);
+ fc->buildmaps();
+ fc->analyze();
+#endif
+ typmap=new typemap(this);
+}
+
+void model::reset() {
+ // typmap->reset(); Don't rebuild trees
+ domainrelation->reset();
+}
+
+typemap * model::gettypemap() {
+ return typmap;
+}
+
+Repair * model::getrepair() {
+ return repair;
+}
+
+NormalForm * model::getnormalform(Constraint *c) {
+ for (int i=0;i<numconstraint;i++) {
+ if (c==constraintarray[i])
+ return constraintnormal[i];
+ }
+ printf("Error finding normal form\n");
+ exit(-1);
+}
+
+int model::getnumconstraints() {
+ return numconstraint;
+}
+
+NormalForm * model::getnormalform(int i) {
+ return constraintnormal[i];
+}
+
+Constraint * model::getconstraint(int i) {
+ return constraintarray[i];
+}
+
+
+// processes the model definition rules
+void model::doabstraction() {
+ struct timeval begin,end;
+ unsigned long time;
+ gettimeofday(&begin,NULL);
+
+ pa=new processabstract(this);
+ bool clean=false;
+ /* Process rules until we reach a fixpoint*/
+ /* First the normal rules */
+ do {
+ clean=false;
+ for(int i=0;i<numrules;i++) {
+ if(!rulearray[i]->isdelayed()) {
+ pa->setclean();
+ pa->processrule(rulearray[i]);
+ if (pa->dirtyflagstatus())
+ clean=true;
+ }
+ }
+ } while(clean);
+
+ /* Then the delayed rules */
+ do {
+ clean=false;
+ for(int i=0;i<numrules;i++) {
+ if(rulearray[i]->isdelayed()) {
+ pa->setclean();
+ pa->processrule(rulearray[i]);
+ if (pa->dirtyflagstatus())
+ clean=true;
+ }
+ }
+ } while(clean);
+ gettimeofday(&end,NULL);
+ time=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+ printf("Time used for abstraction(us): %ld\n",time);
+
+ pa->printstats();
+}
+
+
+void model::triggerrule(Element *ele,char *set) {
+ for(int i=0;i<numrules;i++) {
+ if(rulearray[i]->isstatic()) {
+ pa->processrule(rulearray[i], ele, set);
+ }
+ }
+}
+
+
+// processes the external constraints
+void model::doconcrete() {
+ struct timeval begin,end;
+ unsigned long time;
+ gettimeofday(&begin,NULL);
+
+ processconcrete *pr=new processconcrete(this);
+ for(int i=0;i<numconcrete;i++) {
+ pr->processrule(concretearray[i]);
+ }
+ gettimeofday(&end,NULL);
+ time=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+ printf("Time used for concretization(us): %ld\n",time);
+
+ pr->printstats();
+ delete(pr);
+}
+
+
+
+// inserts faults that break the specifications
+void model::breakspec()
+{
+ srandom((unsigned) time(NULL));
+
+ processobject *po = new processobject(this);
+
+ // takes each satisfied constraint and breaks it with probability prob_breakconstraint
+ for (int i=0; i<numconstraint; i++)
+ {
+ Constraint *c = getconstraint(i);
+ if (po->issatisfied(c))
+ if (random()<prob_breakconstraint*RAND_MAX)
+ po->breakconstraint(c);
+ }
+
+ delete(po);
+}
+
+
+
+// inserts faults that don not break the specifications
+void model::inserterrors()
+{
+ printf("\nmodel::inserterrors CALLED\n\n");
+
+ srandom((unsigned) time(NULL));
+
+ processobject *po = new processobject(this);
+
+ // takes each satisfied constraint and modifies it with probability prob_modifyconstraint
+ long int r;
+ for (int i=0; i<numconstraint; i++)
+ {
+ Constraint *c = getconstraint(i);
+#ifdef DEBUGMESSAGES
+ printf("Constraint: ");
+ c->print();
+ if (po->issatisfied(c))
+ printf(" is satisfied\n");
+ else printf(" is not satisfied\n");
+ fflush(NULL);
+#endif
+ if (po->issatisfied(c))
+ {
+ r=random();
+#ifdef DEBUGMESSAGES
+ printf("r=%ld\n", r);
+#endif
+ if (r<prob_modifyconstraint*RAND_MAX)
+ po->modifyconstraint(c);
+ }
+ }
+
+ delete(po);
+}
+
+
+
+// processes the internal constraints
+// returns true only if no violated constraints were found
+bool model::docheck()
+{
+ struct timeval begin,end;
+ unsigned long time;
+ bool found=false;
+ processobject *po=new processobject(this);
+ bool t=false;
+ gettimeofday(&begin,NULL);
+
+ do {
+ t=false;
+ /* Process rules until we reach a fixpoint*/
+ for(int i=0;i<numconstraint;i++) {
+ if (!po->processconstraint(constraintarray[i]))
+ {
+ found=true;
+#ifdef TOOL
+ break;
+#endif
+ t=true; //Got to keep running
+ }
+ }
+ } while(t);
+ gettimeofday(&end,NULL);
+ time=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+ printf("Time used for check(us): %ld\n",time);
+ po->printstats();
+ delete(po);
+ //printf("return from docheck()");
+ return found;
+}
+
+
+DomainRelation * model::getdomainrelation() {
+ return domainrelation;
+}
+
+
+
+/* reads the testspace file, which keeps the sets and relations involved;
+ these sets and relations are managed by "domainrelation" */
+void model::parsespacefile(char *spacefile) {
+ ifstream *ifs=new ifstream();
+ ifs->open(spacefile);
+ Reader *r=new Reader(ifs);
+ Dparser *p=new Dparser(r);
+ domainrelation=p->parsesetrelation();
+
+#ifdef DEBUGMANYMESSAGES
+ domainrelation->print();
+#endif
+
+ ifs->close();
+ delete(ifs);
+}
+
+
+
+/* reads the teststruct file, which keeps the structure definitions;
+ these definitions are kept in "structurearray" */
+void model::parsestructfile(char *structfile) {
+ ifstream *ifs=new ifstream();
+ ifs->open(structfile);
+ Reader *r=new Reader(ifs);
+ Typeparser *p=new Typeparser(r);
+ List *list=new List();
+
+ do {
+ structure *st=p->parsestructure();
+ if (st!=NULL) {
+ list->addobject(st);
+
+#ifdef DEBUGMANYMESSAGES
+ st->print();
+#endif
+
+ }
+ else
+ break;
+ } while(true);
+ structurearray=new structure *[list->size()];
+ list->toArray((void **)structurearray);
+ numstarray=list->size();
+
+ ifs->close();
+ delete(list);
+ delete(ifs);
+}
+
+
+/* parses the testabstract file, which contains the model definition rules
+ these rules are kept in "rulearray" */
+void model::parseabstractfile(char *abstractfile) {
+ ifstream *ifs=new ifstream();
+ ifs->open(abstractfile);
+ Reader *r=new Reader(ifs);
+ AParser *p=new AParser(r);
+ List *list=new List();
+ int countstatic=0;
+ do {
+ Rule *ru=p->parserule();
+ if (ru!=NULL) {
+ list->addobject(ru);
+ if(ru->isstatic())
+ countstatic++;
+#ifdef DEBUGMANYMESSAGES
+ ru->print();
+#endif
+ }
+ else
+ break;
+ } while(true);
+ rulearray=new Rule *[list->size()];
+ list->toArray((void **)rulearray);
+ numrules=list->size();
+ numrulenormal=countstatic;
+ rulenormal=new NormalForm *[countstatic];
+ int count=0;
+ for(int i=0;i<numrules;i++) {
+ if(rulearray[i]->isstatic()) {
+ rulenormal[count++]=new NormalForm(rulearray[i]);
+ }
+ }
+ ifs->close();
+ delete(ifs);
+ delete(list);
+}
+
+
+
+/* parses the testconcrete file, which contains the external constraints;
+ these constraints are kept in "concretearray" */
+void model::parseconcretefile(char *abstractfile) {
+ ifstream *ifs=new ifstream();
+ ifs->open(abstractfile);
+ Reader *r=new Reader(ifs);
+ CParser *p=new CParser(r);
+ List *list=new List();
+ do {
+ Rule *ru=p->parserule();
+ if (ru!=NULL) {
+ list->addobject(ru);
+#ifdef DEBUGMANYMESSAGES
+ ru->print();
+#endif
+ }
+ else
+ break;
+ } while(true);
+ concretearray=new Rule *[list->size()];
+ list->toArray((void **)concretearray);
+ numconcrete=list->size();
+
+ ifs->close();
+ delete(ifs);
+ delete(list);
+}
+
+
+
+/* parses the testmodel file, which contains the internal constraints
+ these constraints are kept in constraintarray;
+ the constraints in normal form are kept in constraintnormal */
+void model::parsemodelfile(char *modelfile) {
+ ifstream* ifs=new ifstream();
+ ifs->open(modelfile);
+ Reader *r=new Reader(ifs);
+ Parser *p=new Parser(r);
+ List *list=new List();
+ do {
+ Constraint *c=p->parseconstraint();
+ if (c!=NULL) {
+ list->addobject(c);
+#ifdef DEBUGMANYMESSAGES
+ c->print();
+#endif
+ } else
+ break;
+ } while(true);
+
+ constraintarray=new Constraint *[list->size()];
+ list->toArray((void **)constraintarray);
+ numconstraint=list->size();
+ constraintnormal=new NormalForm *[list->size()];
+ for(int i=0;i<list->size();i++)
+ constraintnormal[i]=new NormalForm(constraintarray[i]);
+
+ ifs->close();
+ delete(ifs);
+ delete(list);
+}
+
+
+
+/* reads the testrange file, which keeps the ranges of the relations
+ of the form "relation: A -> token".
+ This information is used only by the fault injection mechanism.
+ This file should be read only after the testspace file.
+*/
+void model::parserangefile(char *rangefile)
+{
+ ifstream *ifs=new ifstream();
+ ifs->open(rangefile);
+ Reader *r = new Reader(ifs);
+ RParser *rp = new RParser(r);
+
+ do {
+ char* relation = rp->parserelation();
+
+ if (relation != NULL)
+ {
+#ifdef DEBUGMANYMESSAGES
+ printf("Reading relation: %s\n", relation);
+ fflush(NULL);
+#endif
+
+ // find the given relation, whose range should be of type "token"
+ DRelation *drel = domainrelation->getrelation(relation);
+ if (strcmp(drel->getrange(), "token") != 0)
+ {
+ printf("Error! Range of %s should be of type token.", relation);
+ exit(0);
+ }
+
+ WorkSet *ws = rp->parseworkset();
+#ifdef DEBUGMANYMESSAGES
+ printf("The range for %s is:\n", relation);
+ void *obj = ws->firstelement();
+ while (obj)
+ {
+ printf("%s ", (char *) obj);
+ obj = ws->getnextelement(obj);
+ }
+ fflush(NULL);
+ printf("\n\n");
+#endif
+ drel->settokenrange(ws);
+ delete(relation);
+ }
+ else
+ break;
+ } while(true);
+
+ ifs->close();
+ delete(ifs);
+ delete(r);
+ delete(rp);
+}
+
+
+
+structure * model::getstructure(char *name) {
+ for(int i=0;i<numstarray;i++) {
+ if (equivalentstrings(name,structurearray[i]->getname())) {
+ /* got match */
+ return structurearray[i];
+ }
+ }
+ return NULL;
+}
+
+FieldCheck * model::getfieldcheck() {
+ return fc;
+}
+
+int model::getnumrulenormal() {
+ return numrulenormal;
+}
+
+NormalForm * model::getrulenormal(int i) {
+ return rulenormal[i];
+}
+
+bool model::subtypeof(structure *sub,structure *super) {
+ while(sub!=NULL) {
+ if (sub==super)
+ return true;
+ if (sub->getsubtype()==NULL)
+ return false;
+ sub=getstructure(sub->getsubtype()->getname());
+ }
+ printf("Error in subtypeof\n");
+ return false; /* Should get here*/
+}
--- /dev/null
+#ifndef MODEL_H
+#define MODEL_H
+#include "classlist.h"
+
+class model {
+ public:
+ model(char *abstractfile, char *modelfile, char *spacefile,char *structfile, char *concretefile, char *rangefile);
+ DomainRelation * getdomainrelation();
+ structure *getstructure(char * name);
+ void doabstraction(); // processes the model definition rules
+ bool docheck(); // processes the internal constraints
+ void doconcrete(); // processes the external constraints
+
+ void breakspec(); // inserts faults that break the specs
+ void inserterrors(); // inserts faults that do not break the specs
+
+ NormalForm * getnormalform(Constraint *c);
+ Hashtable * gethashtable();
+ bitreader * getbitreader();
+ Guidance * getguidance();
+ int getnumconstraints();
+ Constraint * getconstraint(int i);
+ NormalForm * getnormalform(int i);
+ Repair *getrepair();
+ FieldCheck * getfieldcheck();
+ void triggerrule(Element *,char *);
+ int getnumrulenormal();
+ NormalForm * getrulenormal(int i);
+ bool subtypeof(structure *sub,structure *super);
+ typemap * gettypemap();
+ void reset();
+
+ static const double prob_breakconstraint = 1; // the probability with which each constraint is broken when inserting errors
+ static const double prob_breakpredicate = 1; // the probability with which each predicate from the selected sentences is broken
+ static const double prob_modifyconstraint = 1; // the probability with which each constraint is modified when inserting errors
+ static const double prob_breaksatisfiedsentence = 1; // the probability with which each satisfied sentence is modified (broken) when inserting errors
+ static const double prob_repairbrokensentence = 1; // the probability with which each broken sentence is modified (repaired) when inserting errors
+
+ private:
+ void parsespacefile(char *spacefile);
+ void parsestructfile(char *structfile);
+ void parseabstractfile(char *abstractfile);
+ void parseconcretefile(char *concretefile);
+ void parsemodelfile(char *modelfile);
+ void parserangefile(char *rangefile);
+
+ Hashtable *env;
+ bitreader *br;
+ Guidance * guidance;
+ Repair *repair;
+ FieldCheck *fc;
+ processabstract *pa;
+
+ structure **structurearray; // the structure definitions
+ int numstarray;
+
+ DomainRelation *domainrelation; // the sets and relations
+
+ Rule **rulearray; // the model definition rules
+ int numrules;
+ NormalForm **rulenormal; // the model definition rules in normal form
+ int numrulenormal;
+
+ Constraint **constraintarray; // the internal constraints
+ int numconstraint;
+ NormalForm **constraintnormal; // the internal constraints in normal form
+
+ Rule **concretearray; // the external constraints
+ int numconcrete;
+
+
+ typemap * typmap;
+};
+#endif
--- /dev/null
+// converts constraints into disjunctive normal form
+
+#include <stdlib.h>
+#include "normalizer.h"
+#include "omodel.h"
+#include "processobject.h"
+#include "set.h"
+#include "amodel.h"
+#include "common.h"
+
+
+
+// class CoercePredicate
+
+CoercePredicate::CoercePredicate(char *ts, char *lt, char *rs) {
+ triggerset=ts;
+ ltype=lt;
+ rtype=NULL;
+ relset=rs;
+ rule=false;
+ tuple=false;
+ predicate=NULL;
+}
+
+CoercePredicate::CoercePredicate(char *ts, char *lt, char *rt,char *rs) {
+ triggerset=ts;
+ ltype=lt;
+ rtype=rt;
+ relset=rs;
+ rule=false;
+ tuple=true;
+ predicate=NULL;
+}
+
+CoercePredicate::CoercePredicate(bool b, Predicate *p) {
+ rule=true;
+ coercebool=b;
+ predicate=p;
+#ifdef REPAIR
+ if((p->gettype()==PREDICATE_EQ1||
+ p->gettype()==PREDICATE_GTE1)&&coercebool==false) {
+ printf("Possible forcing size predicate to be false. Error!\n");
+ exit(-1);
+ }
+#endif
+}
+
+Predicate * CoercePredicate::getpredicate() {
+ return predicate;
+}
+
+bool CoercePredicate::isrule() {
+ return rule;
+}
+
+bool CoercePredicate::istuple() {
+ return tuple;
+}
+
+bool CoercePredicate::getcoercebool() {
+ return coercebool;
+}
+
+char * CoercePredicate::gettriggerset() {
+ return triggerset;
+}
+
+char * CoercePredicate::getrelset() {
+ return relset;
+}
+
+char * CoercePredicate::getltype() {
+ return ltype;
+}
+
+char * CoercePredicate::getrtype() {
+ return rtype;
+}
+
+
+
+
+// class CoerceSentence
+
+CoerceSentence::CoerceSentence(CoercePredicate **pred, int numpred) {
+ predicates=pred;
+ numpreds=numpred;
+}
+
+
+int CoerceSentence::getnumpredicates() {
+ return numpreds;
+}
+
+
+CoercePredicate * CoerceSentence::getpredicate(int i) {
+ return predicates[i];
+}
+
+
+
+// returns true iff the sentence is satisfied
+bool CoerceSentence::issatisfied(processobject *po, Hashtable *env)
+{
+ for (int i=0; i<getnumpredicates(); i++)
+ {
+ CoercePredicate *cp = getpredicate(i);
+ Predicate *p = cp->getpredicate();
+ if (!po->processpredicate(cp->getpredicate(),env))
+ return false;
+ }
+ return true;
+}
+
+
+// returns how much we pay if we satisfy this sentence
+int CoerceSentence::cost(processobject *po, Hashtable *env) {
+ int cost=0;
+ for(int i=0;i<numpreds;i++) {
+ CoercePredicate *cp=predicates[i];
+ bool pvalue;
+ if (cp->getpredicate()!=NULL)
+ pvalue=po->processpredicate(cp->getpredicate(),env);
+ if (pvalue!=cp->getcoercebool())
+ cost+=costfunction(cp);
+ }
+ return cost;
+}
+
+
+CoerceSentence::~CoerceSentence() {
+ for(int i=0;i<numpreds;i++)
+ delete(predicates[i]);
+ delete predicates;
+}
+
+
+
+
+// class NormalForm
+
+NormalForm::NormalForm(Constraint *c) {
+ SentenceArray *sa=computesentences(c->getstatement(),true);
+ this->length=sa->length;
+ this->sentences=sa->sentences;
+ this->c=c;
+ delete(sa);
+}
+
+void NormalForm::fprint(FILE *f) {
+ if (c!=NULL)
+ c->fprint(f);
+}
+
+NormalForm::NormalForm(Rule *r) {
+ int count=-1;
+ char *label, *triggerset;
+ c=NULL;
+ for(int i=0;i<r->numquants();i++) {
+ AQuantifier *aq=r->getquant(i);
+ switch(aq->gettype()) {
+ case AQUANTIFIER_SING:
+ triggerset=aq->getset()->getname();
+ label=aq->getleft()->label();
+ break;
+ default:
+ break;
+ }
+ }
+ Statementb *sb=r->getstatementb();
+ CoercePredicate *cp=NULL;
+ if(sb->gettype()==STATEMENTB_SING) {
+ cp=new CoercePredicate(triggerset,gettype(label,triggerset,sb->getleft()),sb->getsetlabel()->getname());
+ } else {
+ cp=new CoercePredicate(triggerset,gettype(label,triggerset,sb->getleft()),gettype(label,triggerset,sb->getright()),sb->getsetlabel()->getname());
+ }
+ CoercePredicate **cpa=new CoercePredicate*[1];
+ cpa[0]=cp;
+ CoerceSentence *cs=new CoerceSentence(cpa,1);
+ sentences=new CoerceSentence*[1];
+ sentences[0]=cs;
+ length=1;
+}
+
+
+char * gettype(char *label, char *set,AElementexpr *ae) {
+ switch(ae->gettype()) {
+ case AELEMENTEXPR_SUB:
+ case AELEMENTEXPR_ADD:
+ case AELEMENTEXPR_MULT:
+ case AELEMENTEXPR_DIV:
+ return "int";
+ case AELEMENTEXPR_NULL:
+ return NULL;
+ case AELEMENTEXPR_FIELD:
+ case AELEMENTEXPR_FIELDARRAY:
+ return NULL;
+ case AELEMENTEXPR_LIT:
+ switch(ae->getliteral()->gettype()) {
+ case LITERAL_NUMBER:
+ return "int";
+ case LITERAL_TOKEN:
+ return "token";
+ default:
+ printf("error in normalizer.gettype()\n");
+ exit(-1);
+ }
+ case AELEMENTEXPR_LABEL:
+ if (equivalentstrings(ae->getlabel()->label(),label))
+ return set;
+ return NULL;
+ case AELEMENTEXPR_CAST:
+ return gettype(label,set,ae->getleft());
+ }
+}
+
+
+int NormalForm::getnumsentences() {
+ return length;
+}
+
+
+CoerceSentence * NormalForm::getsentence(int i) {
+ return sentences[i];
+}
+
+
+/* returns the sentence in this constraint that can be satisfied
+ with a minimum cost, and which is different from any sentence
+ in the "badsentences" structure */
+CoerceSentence * NormalForm::closestmatch(WorkSet *badsentences, processobject *po, Hashtable *env) {
+ int totalcost=-1; int bestmatch=-1;
+ for(int i=0;i<length;i++) {
+ if (badsentences==NULL || !badsentences->contains(sentences[i]))
+ {
+ int cost=sentences[i]->cost(po,env);
+ if ((totalcost==-1)||(totalcost>cost)) {
+ totalcost=cost;
+ bestmatch=i;
+ }
+ }
+ }
+ return sentences[bestmatch];
+}
+
+int costfunction(CoercePredicate *p) {
+ return 1;
+}
+
+
+// computes the normal form of the given statement
+SentenceArray * computesentences(Statement *st,bool stat) {
+ switch(st->gettype()) {
+ case STATEMENT_OR: {
+ SentenceArray *left=computesentences(st->getleft(),stat);
+ SentenceArray *right=computesentences(st->getright(),stat);
+ if (stat) {
+ CoerceSentence **combine=new CoerceSentence *[left->length+right->length];
+ for(int i=0;i<left->length;i++)
+ combine[i]=left->sentences[i];
+ for(int i=0;i<right->length;i++)
+ combine[i+left->length]=right->sentences[i];
+ SentenceArray *sa=new SentenceArray(combine, left->length+right->length);
+ delete[](left->sentences);delete[](right->sentences);
+ delete(left);delete(right);
+ return sa;
+ } else {
+ CoerceSentence **combine=new CoerceSentence *[left->length*right->length];
+ for(int i=0;i<left->length;i++)
+ for(int j=0;j<right->length;j++) {
+ CoerceSentence *leftsent=left->sentences[i];
+ CoerceSentence *rightsent=right->sentences[j];
+ CoercePredicate **preds=new CoercePredicate *[leftsent->getnumpredicates()+rightsent->getnumpredicates()];
+ for(int il=0;il<leftsent->getnumpredicates();il++)
+ preds[il]=new CoercePredicate(leftsent->getpredicate(il)->getcoercebool(),leftsent->getpredicate(il)->getpredicate());
+ for(int ir=0;ir<rightsent->getnumpredicates();ir++)
+ preds[ir+leftsent->getnumpredicates()]=new CoercePredicate(rightsent->getpredicate(ir)->getcoercebool(),rightsent->getpredicate(ir)->getpredicate());
+ combine[i*right->length+j]=new CoerceSentence(preds,left->length*right->length);
+ }
+ SentenceArray *sa=new SentenceArray(combine, left->length*right->length);
+ for(int i=0;i<left->length;i++)
+ delete(left->sentences[i]);
+ for(int i=0;i<right->length;i++)
+ delete(right->sentences[i]);
+ delete(left->sentences);delete(right->sentences);
+ delete(left);delete(right);
+ return sa;
+ }
+ }
+ case STATEMENT_AND: {
+ SentenceArray *left=computesentences(st->getleft(),stat);
+ SentenceArray *right=computesentences(st->getright(),stat);
+ if (stat) {
+ CoerceSentence **combine=new CoerceSentence *[left->length*right->length];
+ for(int i=0;i<left->length;i++)
+ for(int j=0;j<right->length;j++) {
+ CoerceSentence *leftsent=left->sentences[i];
+ CoerceSentence *rightsent=right->sentences[j];
+ CoercePredicate **preds=new CoercePredicate *[leftsent->getnumpredicates()+rightsent->getnumpredicates()];
+ for(int il=0;il<leftsent->getnumpredicates();il++)
+ preds[il]=new CoercePredicate(leftsent->getpredicate(il)->getcoercebool(),leftsent->getpredicate(il)->getpredicate());
+ for(int ir=0;ir<rightsent->getnumpredicates();ir++)
+ preds[ir+leftsent->getnumpredicates()]=new CoercePredicate(rightsent->getpredicate(ir)->getcoercebool(),rightsent->getpredicate(ir)->getpredicate());
+ combine[i*right->length+j]=new CoerceSentence(preds,left->length*right->length);
+ }
+ SentenceArray *sa=new SentenceArray(combine, left->length*right->length);
+ for(int i=0;i<left->length;i++)
+ delete(left->sentences[i]);
+ for(int i=0;i<right->length;i++)
+ delete(right->sentences[i]);
+ delete(left->sentences);delete(right->sentences);
+ delete(left);delete(right);
+ return sa;
+ } else {
+ CoerceSentence **combine=new CoerceSentence *[left->length+right->length];
+ for(int i=0;i<left->length;i++)
+ combine[i]=left->sentences[i];
+ for(int i=0;i<right->length;i++)
+ combine[i+left->length]=right->sentences[i];
+ SentenceArray *sa=new SentenceArray(combine, left->length+right->length);
+ delete(left->sentences);delete(right->sentences);
+ delete(left);delete(right);
+ return sa;
+ }
+ }
+ case STATEMENT_NOT:
+ return computesentences(st->getleft(),!stat);
+ case STATEMENT_PRED:
+ CoercePredicate *cp=new CoercePredicate(stat, st->getpredicate());
+ CoercePredicate **cparray=new CoercePredicate *[1];
+ cparray[0]=cp;
+ CoerceSentence *cs=new CoerceSentence(cparray,1);
+ CoerceSentence **csarray=new CoerceSentence *[1];
+ csarray[0]=cs;
+ return new SentenceArray(csarray,1);
+ }
+}
+
+
+
+
+// class SentenceArray
+
+SentenceArray::SentenceArray(CoerceSentence **sentences, int l) {
+ length=l;
+ this->sentences=sentences;
+}
+
--- /dev/null
+// converts constraints into disjunctive normal form
+
+#ifndef NORMALIZER_H
+#define NORMALIZER_H
+#include "classlist.h"
+#include<stdio.h>
+
+
+class CoercePredicate {
+ public:
+ CoercePredicate(bool, Predicate *);
+ CoercePredicate(char *ts, char *lt, char *rs);
+ CoercePredicate(char *ts, char *lt, char *rt,char *rs);
+ Predicate * getpredicate();
+ bool getcoercebool();
+ bool isrule();
+ bool istuple();
+ char *gettriggerset();
+ char *getrelset();
+ char *getltype();
+ char *getrtype();
+
+ private:
+ char *triggerset;
+ bool tuple;
+ char *ltype;
+ char *rtype;
+ char *relset;
+ bool rule;
+ bool coercebool;
+ Predicate *predicate;
+};
+
+
+
+class CoerceSentence {
+ public:
+ CoerceSentence(CoercePredicate **pred, int numpredicates);
+ int getnumpredicates();
+ CoercePredicate *getpredicate(int i);
+ bool issatisfied(processobject *po, Hashtable *env);
+ int cost(processobject *po, Hashtable *env);
+ ~CoerceSentence();
+
+ private:
+ CoercePredicate **predicates;
+ int numpreds;
+};
+
+
+
+// represents a statement in normal form
+class SentenceArray {
+ public:
+ SentenceArray(CoerceSentence **sentences, int l);
+ int length;
+ CoerceSentence **sentences;
+};
+
+
+// represents a constraint in normal form
+class NormalForm {
+ public:
+ NormalForm(Constraint *c);
+ CoerceSentence * closestmatch(WorkSet *,processobject *po,Hashtable *env);
+ int getnumsentences();
+ CoerceSentence *getsentence(int i);
+ NormalForm(Rule *r);
+ void fprint(FILE *f);
+ private:
+ Constraint *c; /*keep reference for quantifiers */
+ CoerceSentence **sentences; // the number of sentences in this constraint
+ int length;
+};
+
+
+SentenceArray * computesentences(Statement *st,bool stat);
+int costfunction(CoercePredicate *p);
+char * gettype(char *label, char *set,AElementexpr *ae);
+#endif
--- /dev/null
+// Defines the Internal Constraint Language
+
+#include <stdio.h>
+#include "omodel.h"
+#include "common.h"
+#include "model.h"
+#include "Hashtable.h"
+#include "dmodel.h"
+#include "element.h"
+#include "set.h"
+#include "Relation.h"
+
+
+// class Literal
+
+Literal::Literal(char *s) {
+ str=s;
+}
+
+
+// there are three types of literals: numbers, bools, and tokens
+int Literal::gettype() {
+ int val;
+ if (sscanf(str,"%d",&val)==1)
+ return LITERAL_NUMBER;
+ else {
+ if (equivalentstrings(str,"true")||
+ equivalentstrings(str,"false"))
+ return LITERAL_BOOL;
+ return LITERAL_TOKEN;
+ }
+}
+
+bool Literal::getbool() {
+ if (equivalentstrings(str,"true"))
+ return true;
+ else
+ return false;
+}
+
+int Literal::number() {
+ int val;
+ sscanf(str,"%d",&val);
+ return val;
+}
+
+char * Literal::token() {
+ return str;
+}
+
+void Literal::print() {
+ printf("%s",str);
+}
+
+void Literal::fprint(FILE *f) {
+ fprintf(f,"%s",str);
+}
+
+
+
+
+
+
+// class Setlabel
+
+Setlabel::Setlabel(char *s) {
+ str=s;
+}
+
+char * Setlabel::getname() {
+ return str;
+}
+
+void Setlabel::print() {
+ printf("%s",str);
+}
+
+void Setlabel::fprint(FILE *f) {
+ fprintf(f,"%s",str);
+}
+
+
+
+
+
+// class Set
+
+// a set is either a label or a set of literals
+
+Set::Set(Setlabel *sl) {
+ type=SET_label;
+ setlabel=sl;
+}
+
+int Set::getnumliterals() {
+ return numliterals;
+}
+
+Literal * Set::getliteral(int i) {
+ return literals[i];
+}
+
+Set::Set(Literal **l, int nl) {
+ type=SET_literal;
+ literals=l;
+ numliterals=nl;
+}
+
+Set::~Set() {
+ if (type==SET_label)
+ delete(setlabel);
+ if (type==SET_literal) {
+ for(int i=0;i<numliterals;i++)
+ delete(literals[i]);
+ delete(literals);
+ }
+}
+
+int Set::gettype() {
+ return type;
+}
+
+char * Set::getname() {
+ return setlabel->getname();
+}
+
+void Set::print() {
+ switch(type) {
+ case SET_label:
+ setlabel->print();
+ break;
+ case SET_literal:
+ printf("{");
+ for(int i=0;i<numliterals;i++) {
+ if (i!=0)
+ printf(",");
+ literals[i]->print();
+ }
+ printf("}");
+ break;
+ }
+}
+
+void Set::fprint(FILE *f) {
+ switch(type) {
+ case SET_label:
+ setlabel->fprint(f);
+ break;
+ case SET_literal:
+ fprintf(f,"{");
+ for(int i=0;i<numliterals;i++) {
+ if (i!=0)
+ fprintf(f,",");
+ literals[i]->fprint(f);
+ }
+ fprintf(f,"}");
+ break;
+ }
+}
+
+
+
+
+
+
+// class Label
+
+Label::Label(char *s) {
+ str=s;
+}
+
+void Label::print() {
+ printf("%s",str);
+}
+
+void Label::fprint(FILE *f) {
+ fprintf(f,"%s",str);
+}
+
+
+
+
+
+// class Relation
+
+Relation::Relation(char * r) {
+ str=r;
+}
+
+char * Relation::getname() {
+ return str;
+}
+
+void Relation::print() {
+ printf("%s",str);
+}
+
+void Relation::fprint(FILE *f) {
+ fprintf(f,"%s",str);
+}
+
+
+
+
+
+// class Quantifier
+
+Quantifier::Quantifier(Label *l, Set *s) {
+ label=l;
+ set=s;
+}
+
+Label * Quantifier::getlabel() {
+ return label;
+}
+
+Set * Quantifier::getset() {
+ return set;
+}
+
+void Quantifier::print() {
+ printf("forall ");
+ label->print();
+ printf(" in ");
+ set->print();
+}
+
+void Quantifier::fprint(FILE *f) {
+ fprintf(f,"forall ");
+ label->fprint(f);
+ fprintf(f," in ");
+ set->fprint(f);
+}
+
+
+
+
+
+
+// class Setexpr
+
+Setexpr::Setexpr(Setlabel *sl) {
+ setlabel=sl;
+ type=SETEXPR_LABEL;
+}
+
+Setexpr::Setexpr(Label *l, bool invert, Relation *r) {
+ label=l;
+ type=invert?SETEXPR_INVREL:SETEXPR_REL;
+ relation=r;
+}
+
+void Setexpr::print() {
+ switch(type) {
+ case SETEXPR_LABEL:
+ setlabel->print();
+ break;
+ case SETEXPR_REL:
+ label->print();
+ printf(".");
+ relation->print();
+ break;
+ case SETEXPR_INVREL:
+ label->print();
+ printf(".~");
+ relation->print();
+ break;
+ }
+}
+
+void Setexpr::fprint(FILE *f) {
+ switch(type) {
+ case SETEXPR_LABEL:
+ setlabel->fprint(f);
+ break;
+ case SETEXPR_REL:
+ label->fprint(f);
+ fprintf(f,".");
+ relation->fprint(f);
+ break;
+ case SETEXPR_INVREL:
+ label->fprint(f);
+ fprintf(f,".~");
+ relation->fprint(f);
+ break;
+ }
+}
+
+
+void Setexpr::print_size(Hashtable *stateenv, model *m)
+{
+ switch(type) {
+ case SETEXPR_LABEL:{
+ printf("sizeof(");
+ setlabel->print();
+ printf(")=");
+
+ DomainRelation *dr = m->getdomainrelation();
+ Hashtable *env = m->gethashtable();
+ DomainSet *dset = dr->getset(setlabel->getname());
+ WorkSet *ws = dset->getset();
+
+ if (ws != NULL)
+ printf("%d", ws->size());
+ else printf("0");
+ break;
+ }
+
+ case SETEXPR_REL:{
+ printf("sizeof(");
+ label->print();
+ printf(".");
+ relation->print();
+ printf(")=");
+
+ Element *key = (Element *) stateenv->get(label->label());
+
+ DomainRelation *dr = m->getdomainrelation();
+ Hashtable *env = m->gethashtable();
+ DRelation *rel = dr->getrelation(relation->getname());
+ WorkRelation *wr = rel->getrelation();
+
+ WorkSet *ws = wr->getset(key);
+
+ if (ws != NULL)
+ printf("%d", ws->size());
+ else printf("0");
+ break;
+ }
+
+ case SETEXPR_INVREL:{
+ printf("sizeof(");
+ label->print();
+ printf(".~");
+ relation->print();
+ printf(")=");
+
+ Element *key = (Element *) stateenv->get(label->label());
+
+ DomainRelation *dr = m->getdomainrelation();
+
+ Hashtable *env = m->gethashtable();
+ DRelation *rel = dr->getrelation(relation->getname());
+ WorkRelation *wr = rel->getrelation();
+
+ WorkSet *ws = wr->invgetset(key);
+
+ if (ws != NULL)
+ printf("%d", ws->size());
+ else printf("0");
+ break;
+ }
+ }
+}
+
+
+void Setexpr::print_value(Hashtable *stateenv, model *m)
+{
+ switch(type) {
+ case SETEXPR_LABEL:{
+ //printf(" ");
+ setlabel->print();
+ printf("=");
+
+ DomainRelation *dr = m->getdomainrelation();
+ Hashtable *env = m->gethashtable();
+ DomainSet *dset = dr->getset(setlabel->getname());
+
+ WorkSet *ws = dset->getset();
+ ws->print();
+ break;
+ }
+
+ case SETEXPR_REL:{
+ /*
+ printf(" sizeof(");
+ label->print();
+ printf(".");
+ relation->print();
+ printf(") = ");
+
+ Element *key = (Element *) stateenv->get(label->label());
+
+ DomainRelation *dr = m->getdomainrelation();
+ Hashtable *env = m->gethashtable();
+ DRelation *rel = dr->getrelation(relation->getname());
+ WorkRelation *wr = rel->getrelation();
+
+ WorkSet *ws = wr->getset(key);
+
+ printf("%d\n", ws->size());
+ */
+ break;
+ }
+
+ case SETEXPR_INVREL:{
+ /*
+ printf(" sizeof(");
+ label->print();
+ printf(".~");
+ relation->print();
+ printf(") = ");
+
+ Element *key = (Element *) stateenv->get(label->label());
+
+ DomainRelation *dr = m->getdomainrelation();
+
+ Hashtable *env = m->gethashtable();
+ DRelation *rel = dr->getrelation(relation->getname());
+ WorkRelation *wr = rel->getrelation();
+
+ WorkSet *ws = wr->invgetset(key);
+
+ printf("%d\n", ws->size());
+ */
+ break;
+ }
+ }
+}
+
+
+Setlabel * Setexpr::getsetlabel() {
+ return setlabel;
+}
+
+Relation * Setexpr::getrelation() {
+ return relation;
+}
+
+Label * Setexpr::getlabel() {
+ return label;
+}
+
+int Setexpr::gettype() {
+ return type;
+}
+
+
+
+
+
+// class Valueexpr
+
+Label * Valueexpr::getlabel() {
+ return label;
+}
+
+int Valueexpr::gettype() {
+ return type;
+}
+
+Relation * Valueexpr::getrelation() {
+ return relation;
+}
+
+Valueexpr::Valueexpr(Label *l,Relation *r, bool inv) {
+ label=l;relation=r;
+ type=0;inverted=inv;
+}
+
+Valueexpr::Valueexpr(Valueexpr *ve,Relation *r,bool inv) {
+ valueexpr=ve;relation=r;
+ type=1;inverted=inv;
+}
+
+bool Valueexpr::getinverted() {
+ return inverted;
+}
+
+void Valueexpr::print() {
+ switch(type) {
+ case 0:
+ label->print();
+ printf(".");
+ if (inverted)
+ printf("~");
+ relation->print();
+ break;
+ case 1:
+ valueexpr->print();
+ printf(".");
+ if (inverted)
+ printf("~");
+ relation->print();
+ break;
+ }
+}
+
+void Valueexpr::fprint(FILE *f) {
+ switch(type) {
+ case 0:
+ label->fprint(f);
+ fprintf(f,".");
+ if (inverted)
+ fprintf(f,"~");
+ relation->fprint(f);
+ break;
+ case 1:
+ valueexpr->fprint(f);
+ fprintf(f,".");
+ if (inverted)
+ fprintf(f,"~");
+ relation->fprint(f);
+ break;
+ }
+}
+
+Element * Valueexpr::get_value(Hashtable *stateenv, model *m) {
+ Element *key=NULL;
+ if (type==0) {
+ key = (Element *) stateenv->get(label->label());
+ } else
+ key = valueexpr->get_value(stateenv,m);
+
+ DomainRelation *dr = m->getdomainrelation();
+ Hashtable *env = m->gethashtable();
+ DRelation *rel = dr->getrelation(relation->getname());
+ WorkRelation *wr = rel->getrelation();
+
+ if (inverted)
+ return (Element *) wr->invgetobj(key);
+ else
+ return (Element *) wr->getobj(key);
+
+}
+
+void Valueexpr::print_value(Hashtable *stateenv, model *m) {
+ this->print();
+ printf("=");
+ Element *elem = this->get_value(stateenv,m);
+ elem->print();
+ //printf("\n");
+}
+
+Valueexpr * Valueexpr::getvalueexpr() {
+ return valueexpr;
+}
+
+
+
+
+
+// class Elementexpr
+
+int Elementexpr::gettype() {
+ return type;
+}
+
+Relation * Elementexpr::getrelation() {
+ return relation;
+}
+
+Elementexpr::Elementexpr(Elementexpr *l,Relation *r) {
+ type=ELEMENTEXPR_RELATION;
+ left=l;
+ relation=r;
+}
+
+Setexpr * Elementexpr::getsetexpr() {
+ return setexpr;
+}
+
+Elementexpr::Elementexpr(Setexpr *se) {
+ setexpr=se;
+ type=ELEMENTEXPR_SETSIZE;
+}
+
+Label * Elementexpr::getlabel() {
+ return label;
+}
+
+Elementexpr * Elementexpr::getleft() {
+ return left;
+}
+
+Elementexpr * Elementexpr::getright() {
+ return right;
+}
+
+Literal * Elementexpr::getliteral() {
+ return literal;
+}
+
+Elementexpr::Elementexpr(Elementexpr *l, Elementexpr *r, int op) {
+ left=l;right=r;type=op;
+}
+
+Elementexpr::Elementexpr(Literal *lit) {
+ literal=lit;
+ type=ELEMENTEXPR_LIT;
+}
+
+Elementexpr::Elementexpr(Label *lab) {
+ label=lab;
+ type=ELEMENTEXPR_LABEL;
+}
+
+void Elementexpr::print() {
+ switch(type) {
+ case ELEMENTEXPR_LABEL:
+ label->print();
+ break;
+ case ELEMENTEXPR_SUB:
+ left->print();
+ printf("-");
+ right->print();
+ break;
+ case ELEMENTEXPR_ADD:
+ left->print();
+ printf("+");
+ right->print();
+ break;
+ case ELEMENTEXPR_MULT:
+ left->print();
+ printf("*");
+ right->print();
+ break;
+ case ELEMENTEXPR_LIT:
+ literal->print();
+ break;
+ case ELEMENTEXPR_SETSIZE:
+ printf("sizeof(");
+ setexpr->print();
+ printf(")");
+ break;
+ case ELEMENTEXPR_RELATION:
+ left->print();
+ printf(".");
+ relation->print();
+ break;
+ }
+}
+
+void Elementexpr::fprint(FILE *f) {
+ switch(type) {
+ case ELEMENTEXPR_LABEL:
+ label->fprint(f);
+ break;
+ case ELEMENTEXPR_SUB:
+ left->fprint(f);
+ fprintf(f,"-");
+ right->fprint(f);
+ break;
+ case ELEMENTEXPR_ADD:
+ left->fprint(f);
+ fprintf(f,"+");
+ right->fprint(f);
+ break;
+ case ELEMENTEXPR_MULT:
+ left->fprint(f);
+ fprintf(f,"*");
+ right->fprint(f);
+ break;
+ case ELEMENTEXPR_LIT:
+ literal->fprint(f);
+ break;
+ case ELEMENTEXPR_SETSIZE:
+ fprintf(f,"sizeof(");
+ setexpr->fprint(f);
+ fprintf(f,")");
+ break;
+ case ELEMENTEXPR_RELATION:
+ left->fprint(f);
+ fprintf(f,".");
+ relation->fprint(f);
+ break;
+ }
+}
+
+
+void Elementexpr::print_value(Hashtable *stateenv, model *m) {
+ switch(type) {
+ case ELEMENTEXPR_SUB:
+ case ELEMENTEXPR_ADD:
+ case ELEMENTEXPR_MULT:
+ left->print_value(stateenv, m);
+ right->print_value(stateenv, m);
+ break;
+ case ELEMENTEXPR_SETSIZE:
+ setexpr->print_size(stateenv, m);
+ break;
+ case ELEMENTEXPR_RELATION:
+ /*
+ left->print();
+ printf(".");
+ relation->print();
+ */
+ break;
+ }
+}
+
+
+
+// class Predicate
+
+Predicate::Predicate(Valueexpr *ve, int t, Elementexpr *ee) {
+ valueexpr=ve;
+ type=t;
+ elementexpr=ee;
+}
+
+Predicate::Predicate(Label *l,Setexpr *se) {
+ label=l;
+ setexpr=se;
+ type=PREDICATE_SET;
+}
+
+Predicate::Predicate(bool greaterthan, Setexpr *se) {
+ if (greaterthan)
+ type=PREDICATE_GTE1;
+ else
+ type=PREDICATE_EQ1;
+ setexpr=se;
+}
+
+Valueexpr * Predicate::getvalueexpr() {
+ return valueexpr;
+}
+
+Elementexpr * Predicate::geteleexpr() {
+ return elementexpr;
+}
+
+Label * Predicate::getlabel() {
+ return label;
+}
+
+Setexpr * Predicate::getsetexpr() {
+ return setexpr;
+}
+
+int Predicate::gettype() {
+ return type;
+}
+
+void Predicate::print() {
+ switch(type) {
+ case PREDICATE_LT:
+ valueexpr->print();
+ printf("<");
+ elementexpr->print();
+ break;
+ case PREDICATE_LTE:
+ valueexpr->print();
+ printf("<=");
+ elementexpr->print();
+ break;
+ case PREDICATE_EQUALS:
+ valueexpr->print();
+ printf("=");
+ elementexpr->print();
+ break;
+ case PREDICATE_GTE:
+ valueexpr->print();
+ printf(">=");
+ elementexpr->print();
+ break;
+ case PREDICATE_GT:
+ valueexpr->print();
+ printf(">");
+ elementexpr->print();
+ break;
+ case PREDICATE_SET:
+ label->print();
+ printf(" in ");
+ setexpr->print();
+ break;
+ case PREDICATE_EQ1:
+ case PREDICATE_GTE1:
+ printf("sizeof(");
+ setexpr->print();
+ if (type==PREDICATE_EQ1)
+ printf(")=1");
+ if (type==PREDICATE_GTE1)
+ printf(")>=1");
+ break;
+ }
+}
+
+void Predicate::fprint(FILE *f) {
+ switch(type) {
+ case PREDICATE_LT:
+ valueexpr->fprint(f);
+ fprintf(f,"<");
+ elementexpr->fprint(f);
+ break;
+ case PREDICATE_LTE:
+ valueexpr->fprint(f);
+ fprintf(f,"<=");
+ elementexpr->fprint(f);
+ break;
+ case PREDICATE_EQUALS:
+ valueexpr->fprint(f);
+ fprintf(f,"=");
+ elementexpr->fprint(f);
+ break;
+ case PREDICATE_GTE:
+ valueexpr->fprint(f);
+ fprintf(f,">=");
+ elementexpr->fprint(f);
+ break;
+ case PREDICATE_GT:
+ valueexpr->fprint(f);
+ fprintf(f,">");
+ elementexpr->fprint(f);
+ break;
+ case PREDICATE_SET:
+ label->fprint(f);
+ fprintf(f," in ");
+ setexpr->fprint(f);
+ break;
+ case PREDICATE_EQ1:
+ case PREDICATE_GTE1:
+ fprintf(f,"sizeof(");
+ setexpr->fprint(f);
+ if (type==PREDICATE_EQ1)
+ fprintf(f,")=1");
+ if (type==PREDICATE_GTE1)
+ fprintf(f,")>=1");
+ break;
+ }
+}
+
+
+
+void Predicate::print_sets(Hashtable *stateenv, model *m) {
+ switch(type) {
+ case PREDICATE_LT:
+ case PREDICATE_LTE:
+ case PREDICATE_EQUALS:
+ case PREDICATE_GTE:
+ case PREDICATE_GT:
+ valueexpr->print_value(stateenv, m);
+ printf("; ");
+ elementexpr->print_value(stateenv, m);
+ break;
+ case PREDICATE_SET:
+ setexpr->print_value(stateenv, m);
+ break;
+ case PREDICATE_EQ1:
+ case PREDICATE_GTE1:
+ setexpr->print_size(stateenv, m);
+ break;
+ }
+}
+
+
+
+
+
+// class Statement
+
+Statement::Statement(Statement *l, Statement *r, int t) {
+ left=l;
+ right=r;
+ type=t;
+}
+
+Statement::Statement(Statement *l) {
+ type=STATEMENT_NOT;
+ left=l;
+}
+
+Statement::Statement(Predicate *p) {
+ pred=p;
+ type=STATEMENT_PRED;
+}
+
+void Statement::print() {
+ switch(type) {
+ case STATEMENT_OR:
+ left->print();
+ printf(" OR ");
+ right->print();
+ break;
+ case STATEMENT_AND:
+ left->print();
+ printf(" AND ");
+ right->print();
+ break;
+ case STATEMENT_NOT:
+ printf("!");
+ left->print();
+ break;
+ case STATEMENT_PRED:
+ pred->print();
+ break;
+ }
+}
+
+void Statement::fprint(FILE *f) {
+ switch(type) {
+ case STATEMENT_OR:
+ left->fprint(f);
+ fprintf(f," OR ");
+ right->fprint(f);
+ break;
+ case STATEMENT_AND:
+ left->fprint(f);
+ fprintf(f," AND ");
+ right->fprint(f);
+ break;
+ case STATEMENT_NOT:
+ fprintf(f,"!");
+ left->fprint(f);
+ break;
+ case STATEMENT_PRED:
+ pred->fprint(f);
+ break;
+ }
+}
+
+
+void Statement::print_sets(Hashtable *stateenv, model *m) {
+ switch(type) {
+ case STATEMENT_OR:
+ case STATEMENT_AND:
+ left->print_sets(stateenv, m);
+ printf("; ");
+ right->print_sets(stateenv, m);
+ break;
+ case STATEMENT_NOT:
+ left->print_sets(stateenv, m);
+ break;
+ case STATEMENT_PRED:
+ pred->print_sets(stateenv, m);
+ break;
+ }
+ //printf("\n");
+}
+
+
+int Statement::gettype() {
+ return type;
+}
+
+Statement* Statement::getleft() {
+ return left;
+}
+
+Statement* Statement::getright() {
+ return right;
+}
+
+Predicate * Statement::getpredicate() {
+ return pred;
+}
+
+
+
+
+
+
+// class Constraint
+
+Constraint::Constraint() {
+ quantifiers=NULL;
+ numquantifiers=0;
+ statement=NULL;
+}
+
+void Constraint::setcrash(bool c) {
+ crash=c;
+}
+
+bool Constraint::getcrash() {
+ return crash;
+}
+
+Constraint::Constraint(Quantifier **q, int nq) {
+ quantifiers=q;
+ numquantifiers=nq;
+ statement=NULL;
+}
+
+void Constraint::setstatement(Statement *s) {
+ statement=s;
+}
+
+int Constraint::numquants() {
+ return numquantifiers;
+}
+
+Quantifier * Constraint::getquant(int i) {
+ return quantifiers[i];
+}
+
+Statement * Constraint::getstatement() {
+ return statement;
+}
+
+void Constraint::print() {
+ printf("[");
+ for(int i=0;i<numquantifiers;i++) {
+ if (i!=0)
+ printf(",");
+ quantifiers[i]->print();
+ }
+ printf("], ");
+ if (statement!=NULL) {
+ statement->print();
+ }
+ printf("\n");
+}
+
+void Constraint::fprint(FILE *f) {
+ printf("[");
+ for(int i=0;i<numquantifiers;i++) {
+ if (i!=0)
+ fprintf(f,",");
+ quantifiers[i]->fprint(f);
+ }
+ printf("],");
+ if (statement!=NULL) {
+ statement->fprint(f);
+ }
+}
--- /dev/null
+// Defines the Internal Constraint Language
+
+
+#ifndef ObjectModel_H
+#define ObjectModel_H
+#include<unistd.h>
+#include<stdio.h>
+#include "classlist.h"
+
+
+#define LITERAL_NUMBER 1
+#define LITERAL_TOKEN 2
+#define LITERAL_BOOL 3
+
+
+class Literal {
+ public:
+ Literal(char *s);
+ bool getbool();
+ int gettype();
+ int number();
+ char * token();
+ void print();
+ void fprint(FILE *f);
+
+ private:
+ char *str;
+};
+
+
+
+
+class Setlabel {
+ public:
+ Setlabel(char *s);
+ char * getname();
+ void print();
+ void fprint(FILE *f);
+ private:
+ char *str;
+};
+
+
+
+
+
+#define SET_label 0
+#define SET_literal 1
+
+class Set {
+ public:
+ Set(Setlabel *sl);
+ Set(Literal **l, int nl);
+ ~Set();
+ void fprint(FILE *f);
+ void print();
+ int gettype();
+ char * getname();
+ int getnumliterals();
+ Literal * getliteral(int i);
+ private:
+ int type;
+ Setlabel *setlabel;
+ int numliterals;
+ Literal **literals;
+};
+
+
+
+
+
+class Label {
+ public:
+ Label(char *s);
+ void print();
+ void fprint(FILE *f);
+ char* label() {
+ return str;
+ }
+
+ private:
+ char *str;
+};
+
+
+
+
+
+class Relation {
+ public:
+ Relation(char * r);
+ void print();
+ void fprint(FILE *f);
+ char * getname();
+
+ private:
+ char *str;
+};
+
+
+
+
+
+class Quantifier {
+ public:
+ Quantifier(Label *l, Set *s);
+ void print();
+ void fprint(FILE *f);
+ Label * getlabel();
+ Set * getset();
+
+ private:
+ Label *label;
+ Set *set;
+};
+
+
+
+
+
+
+#define SETEXPR_LABEL 1
+#define SETEXPR_REL 2
+#define SETEXPR_INVREL 3
+
+class Setexpr {
+ public:
+ Setexpr(Setlabel *sl);
+ Setexpr(Label *l, bool invert, Relation *r);
+ void print();
+ void fprint(FILE *f);
+ void print_size(Hashtable *stateenv, model *m);
+ void print_value(Hashtable *stateenv, model *m);
+ Setlabel * getsetlabel();
+ Relation * getrelation();
+ Label * getlabel();
+ int gettype();
+
+ private:
+ int type;
+ Setlabel *setlabel;
+ Label *label;
+ Relation *relation;
+};
+
+
+
+
+
+
+class Valueexpr {
+ public:
+ Valueexpr(Label *l,Relation *r, bool inv);
+ Valueexpr(Valueexpr *ve,Relation *r, bool inv);
+ void print();
+ void fprint(FILE *f);
+ void print_value(Hashtable *stateenv, model *m);
+ Element * get_value(Hashtable *stateenv, model *m);
+ int gettype();
+ Label * getlabel();
+ Valueexpr * getvalueexpr();
+ Relation * getrelation();
+ bool getinverted();
+
+ private:
+ int type;
+ bool inverted;
+ Label *label;
+ Valueexpr *valueexpr;
+ Relation *relation;
+};
+
+
+
+
+
+
+#define ELEMENTEXPR_LABEL 1
+#define ELEMENTEXPR_SUB 2
+#define ELEMENTEXPR_ADD 3
+#define ELEMENTEXPR_MULT 4
+#define ELEMENTEXPR_LIT 5
+#define ELEMENTEXPR_SETSIZE 6
+#define ELEMENTEXPR_RELATION 11
+
+class Elementexpr {
+ public:
+ Elementexpr(Setexpr *se);
+ Elementexpr(Elementexpr *l, Elementexpr *r, int op);
+ Elementexpr(Literal *lit);
+ Elementexpr(Label *lab);
+ Elementexpr(Elementexpr *l,Relation *r);
+ void print();
+ void fprint(FILE *f);
+ void print_value(Hashtable *stateenv, model *m);
+
+ int gettype();
+ Label * getlabel();
+ Elementexpr *getleft();
+ Elementexpr *getright();
+ Literal * getliteral();
+ Setexpr * getsetexpr();
+ Relation * getrelation();
+
+ private:
+ int type;
+ Relation *relation;
+ Elementexpr *left, *right;
+ Label *label;
+ Literal *literal;
+ Setexpr *setexpr;
+};
+
+
+
+
+
+#define PREDICATE_LT 1
+#define PREDICATE_LTE 2
+#define PREDICATE_EQUALS 3
+#define PREDICATE_GTE 4
+#define PREDICATE_GT 5
+#define PREDICATE_SET 6
+#define PREDICATE_EQ1 7
+#define PREDICATE_GTE1 8
+
+class Predicate {
+ public:
+ Predicate(Valueexpr *ve, int t, Elementexpr *ee);
+ Predicate(Label *l,Setexpr *se);
+ Predicate(bool greaterthan, Setexpr *se);
+ void print();
+ void fprint(FILE *f);
+ void print_sets(Hashtable *stateenv, model *m);
+ int gettype();
+ Valueexpr * getvalueexpr();
+ Elementexpr * geteleexpr();
+ Label * getlabel();
+ Setexpr * getsetexpr();
+ private:
+ int type;
+ Valueexpr *valueexpr;
+ Elementexpr *elementexpr;
+ Label *label;
+ Setexpr *setexpr;
+};
+
+
+
+
+
+
+#define STATEMENT_OR 1
+#define STATEMENT_AND 2
+#define STATEMENT_NOT 3
+#define STATEMENT_PRED 4
+
+class Statement {
+ public:
+ Statement(Statement *l, Statement *r, int t);
+ Statement(Statement *l);
+ Statement(Predicate *p);
+ void print();
+ void fprint(FILE *f);
+ void print_sets(Hashtable *env, model *m); // prints the sets and the relations involved in the statement
+ int gettype();
+ Statement *getleft();
+ Statement *getright();
+ Predicate *getpredicate();
+ private:
+ int type;
+ Statement *left,*right;
+ Predicate *pred;
+};
+
+
+
+
+
+
+class Constraint {
+ public:
+ Constraint();
+ Constraint(Quantifier **q, int nq);
+ void setstatement(Statement *s);
+ void print();
+ void fprint(FILE *f);
+ int numquants();
+ Quantifier * getquant(int i);
+ Statement * getstatement();
+ void setcrash(bool c);
+ bool getcrash();
+ private:
+ bool crash;
+ int numquantifiers;
+ Quantifier **quantifiers;
+ Statement *statement;
+};
+
+
+#endif
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "oparser.h"
+#include "omodel.h"
+#include "list.h"
+#include "common.h"
+#include "token.h"
+
+
+Constraint * Parser::parseconstraint() {
+ Token token=reader->peakahead();
+ while(token.token_type==TOKEN_EOL) {
+ skiptoken();
+ token=reader->peakahead();
+ }
+ if (token.token_type==TOKEN_EOF)
+ return NULL;
+ bool crash=false;
+ if (token.token_type==TOKEN_CRASH) {
+ crash=true;
+ skiptoken();
+ }
+ Constraint *c;
+ /*Get Quantifiers*/
+ if (token.token_type==TOKEN_OPENBRACK) {
+ skiptoken();
+ c=parsequantifiers();
+ needtoken(TOKEN_COMMA);
+ } else c=new Constraint();
+ /*Peek ahead to see if sizeof*/
+ c->setcrash(crash);
+ c->setstatement(parsestatement(false));
+ return c;
+}
+
+Statement * Parser::parsestatement(bool flag) {
+ Statement * oldst=NULL;
+ int joinflag=-1;
+ while(true) {
+ Token token=reader->peakahead();
+ switch(token.token_type) {
+ case TOKEN_EOL:
+ skiptoken();
+ return oldst;
+ case TOKEN_OPENPAREN:
+ {
+ skiptoken();
+ Statement *st=parsestatement(false);
+ if (flag)
+ return st;
+ if (oldst==NULL) {
+ oldst=st;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statement(oldst, st, STATEMENT_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statement(oldst, st, STATEMENT_OR);
+ } else {
+ error();
+ }
+ joinflag=-1;
+ }
+ }
+ break;
+ case TOKEN_CLOSEPAREN:
+ skiptoken();
+ return oldst;
+ case TOKEN_AND:
+ skiptoken();
+ if (oldst==NULL) error();
+ joinflag=TOKEN_AND;
+ break;
+ case TOKEN_OR:
+ skiptoken();
+ if (oldst==NULL) error();
+ joinflag=TOKEN_OR;
+ break;
+ case TOKEN_NOT:
+ {
+ skiptoken();
+ Statement * st=new Statement(parsestatement(true));
+ if (flag)
+ return st;
+ if (oldst==NULL) {
+ oldst=st;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statement(oldst, st, STATEMENT_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statement(oldst, st, STATEMENT_OR);
+ } else {
+ error();
+ }
+ joinflag=-1;
+ }
+ }
+ break;
+ default:
+ {
+ Statement * st=new Statement(parsepredicate());
+ if (flag) return st;
+ if (oldst==NULL) {
+ oldst=st;
+ } else {
+ if (joinflag==TOKEN_AND) {
+ oldst=new Statement(oldst, st, STATEMENT_AND);
+ } else if (joinflag==TOKEN_OR) {
+ oldst=new Statement(oldst, st, STATEMENT_OR);
+ }
+ joinflag=-1;
+ }
+ }
+ }
+ }
+}
+
+Elementexpr * Parser::parseelementexpr() {
+ Elementexpr *oldee=NULL;
+ int joinop=-1;
+ while(true) {
+ Token t=reader->peakahead();
+ switch(t.token_type) {
+ case TOKEN_SIZEOF:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ Setexpr* se=parsesetexpr();
+ needtoken(TOKEN_CLOSEPAREN);
+ if (oldee==NULL)
+ oldee=new Elementexpr(se);
+ else {
+ if (joinop!=-1) {
+ oldee=new Elementexpr(oldee,new Elementexpr(se),joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+ case TOKEN_LITERAL:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ Token literal=reader->readnext();
+ needtoken(TOKEN_CLOSEPAREN);
+ if (oldee==NULL)
+ oldee=new Elementexpr(new Literal(copystr(literal.str)));
+ else {
+ if (joinop!=-1) {
+ oldee=new Elementexpr(oldee,new Elementexpr(new Literal(copystr(literal.str))),joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+ /* case TOKEN_PARAM:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ Elementexpr *ee=parseelementexpr();
+ needtoken(TOKEN_COMMA);
+ Token number=reader->readnext();
+ needtoken(TOKEN_CLOSEPAREN);
+
+ if (oldee==NULL)
+ oldee=new Elementexpr(ee,new Literal(copystr(number.str)));
+ else {
+ if (joinop!=-1) {
+ oldee=new Elementexpr(oldee,new Elementexpr(ee,new Literal(copystr(number.str))),joinop);
+ joinop=-1;
+ } else error();
+ }
+
+ break;
+ } */
+ case TOKEN_OPENPAREN:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ Elementexpr *ee=parseelementexpr();
+ if (oldee==NULL)
+ oldee=ee;
+ else {
+ if (joinop!=-1) {
+ oldee=new Elementexpr(oldee,ee,joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+ case TOKEN_CLOSEPAREN:
+ skiptoken();
+ return oldee;
+ break;
+ case TOKEN_SUB:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=ELEMENTEXPR_SUB;
+ else
+ error();
+ break;
+ case TOKEN_ADD:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=ELEMENTEXPR_ADD;
+ else
+ error();
+ break;
+ case TOKEN_MULT:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=ELEMENTEXPR_MULT;
+ else
+ error();
+ break;
+ default:
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ if (oldee==NULL)
+ oldee=checkdot(new Elementexpr(new Label(copystr(t.str))));
+ else {
+ if (joinop!=-1) {
+ oldee=new Elementexpr(oldee,new Elementexpr(new Label(copystr(t.str))),joinop);
+ joinop=-1;
+ } else error();
+ }
+ }
+ }
+}
+
+Elementexpr * Parser::checkdot(Elementexpr * incoming) {
+ Token tdot=reader->peakahead();
+ if (tdot.token_type!=TOKEN_DOT) return incoming;
+ skiptoken();
+ Token tfield=reader->readnext();
+ Token tpeak=reader->peakahead();
+ return checkdot(new Elementexpr(incoming, new Relation(copystr(tfield.str))));
+}
+
+Predicate * Parser::parsepredicate() {
+ Token label=reader->readnext();
+
+ if (label.token_type==TOKEN_SIZEOF) {
+ needtoken(TOKEN_OPENPAREN);
+ Setexpr * setexpr=parsesetexpr();
+ needtoken(TOKEN_CLOSEPAREN);
+ Token tokentest=reader->readnext();
+ bool greaterthan=false;
+ switch(tokentest.token_type) {
+ case TOKEN_EQUALS:
+ greaterthan=false;
+ break;
+ case TOKEN_GT:
+ greaterthan=true;
+ break;
+ default:
+ error();
+ }
+ needtoken(TOKEN_ONE);
+ return new Predicate(greaterthan, setexpr);
+ }
+
+ Token nexttoken=reader->readnext();
+ bool inverted=false;
+ switch(nexttoken.token_type) {
+ case TOKEN_DOTINV:
+ inverted=true;
+ case TOKEN_DOT:
+ {
+ Token relation=reader->readnext();
+ Token compareop=reader->readnext();
+ Valueexpr *ve=new Valueexpr(new Label(copystr(label.str)),
+ new Relation(copystr(relation.str)),inverted);
+ while(compareop.token_type==TOKEN_DOT||compareop.token_type==TOKEN_DOTINV) {
+ Token nrelation=reader->readnext();
+ bool invert=(compareop.token_type==TOKEN_DOTINV);
+ compareop=reader->readnext();
+ ve=new Valueexpr(ve,
+ new Relation(copystr(nrelation.str)),invert);
+ }
+ Elementexpr * ee=parseelementexpr();
+
+
+ switch(compareop.token_type) {
+ case TOKEN_LT:
+ return new Predicate(ve,PREDICATE_LT,ee);
+ case TOKEN_LTE:
+ return new Predicate(ve,PREDICATE_LTE,ee);
+ case TOKEN_EQUALS:
+ return new Predicate(ve,PREDICATE_EQUALS,ee);
+ case TOKEN_GTE:
+ return new Predicate(ve,PREDICATE_GTE,ee);
+ case TOKEN_GT:
+ return new Predicate(ve,PREDICATE_GT,ee);
+ default:
+ error();
+ }
+ }
+ case TOKEN_IN:
+ {
+ Setexpr * se=parsesetexpr();
+ return new Predicate(new Label(copystr(label.str)),se);
+ }
+ default:
+ error();
+ }
+}
+
+void Parser::error() {
+ printf("ERROR\n");
+ reader->error();
+ exit(-1);
+}
+
+void Parser::skiptoken() {
+ reader->readnext();
+}
+
+void Parser::needtoken(int token) {
+ Token t=reader->readnext();
+ if (!(t.token_type==token)) {
+ printf("Needed token: ");
+ tokenname(token);
+ printf("\n Got token: %s ",t.str);
+ tokenname(t.token_type);
+ error();
+ }
+}
+
+Constraint * Parser::parsequantifiers() {
+ bool bool_continue=true;
+ List * list=new List();
+ do {
+ Token token2=reader->readnext();
+ switch(token2.token_type) {
+ case TOKEN_CLOSEBRACK:
+ bool_continue=false;
+ break;
+ case TOKEN_FORALL:
+ list->addobject(parsequantifier());
+ break;
+ case TOKEN_COMMA:
+ break;
+ default:
+ error();
+ }
+ } while(bool_continue);
+ Quantifier** qarray=new Quantifier* [list->size()];
+ list->toArray((void **)qarray);
+ Constraint *c=new Constraint(qarray,list->size());
+ delete(list);
+ return c;
+}
+
+Quantifier * Parser::parsequantifier() {
+ Token label=reader->readnext();
+ needtoken(TOKEN_IN);
+ return new Quantifier(new Label(copystr(label.str)),parseset());
+}
+
+Set * Parser::parseset() {
+ Token label=reader->readnext();
+ if (label.token_type==TOKEN_OPENBRACE) {
+ bool bool_continue=true;
+ List * list=new List();
+ do {
+ Token token2=reader->readnext();
+ switch(token2.token_type) {
+ case TOKEN_CLOSEBRACE:
+ bool_continue=false;
+ break;
+ case TOKEN_COMMA:
+ break;
+ default:
+ list->addobject(new Literal(copystr(token2.str)));
+ break;
+ }
+ } while(bool_continue);
+ int size=list->size();
+ Literal** qarray=new Literal* [size];
+ list->toArray((void **)qarray);
+ delete(list);
+ return new Set(qarray,size);
+ } else
+ return new Set(new Setlabel(copystr(label.str)));
+}
+
+Setexpr * Parser::parsesetexpr() {
+ Token label=reader->readnext();
+ Token peak=reader->peakahead();
+ if (peak.token_type==TOKEN_DOT) {
+ skiptoken();
+ return new Setexpr(new Label(copystr(label.str)),false,new Relation(copystr(reader->readnext().str)));
+ } else if (peak.token_type==TOKEN_DOTINV) {
+ skiptoken();
+ return new Setexpr(new Label(copystr(label.str)),true,new Relation(copystr(reader->readnext().str)));
+ } else
+ return new Setexpr(new Setlabel(copystr(label.str)));
+}
+
+Parser::Parser(Reader *r) {
+ reader=r;
+}
--- /dev/null
+#ifndef ObjectModelParser_H
+#define ObjectModelParser_H
+
+#include "common.h"
+#include <iostream.h>
+#include <stdio.h>
+#include "classlist.h"
+
+class Parser {
+ public:
+ Parser(Reader *r);
+ Constraint * parseconstraint();
+
+ private:
+ Elementexpr * checkdot(Elementexpr * incoming);
+ Constraint * parsequantifiers();
+ Quantifier * parsequantifier();
+ Set * parseset();
+ Setexpr * parsesetexpr();
+ Statement * parsestatement(bool);
+ Elementexpr * parseelementexpr();
+ Predicate * parsepredicate();
+ void skiptoken();
+ void needtoken(int);
+ void error();
+ Reader *reader;
+};
+#endif
--- /dev/null
+// evaluates model definition rules
+
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+
+#include "processabstract.h"
+#include "processconcrete.h"
+#include "amodel.h"
+#include "omodel.h"
+#include "dmodel.h"
+#include "Hashtable.h"
+#include "element.h"
+#include "common.h"
+#include "bitreader.h"
+#include "model.h"
+#include "set.h"
+#include "Relation.h"
+#include "tmap.h"
+
+static int abstractcheck=0;
+static int abstracttrigger=0;
+static int paircount=0;
+
+// class processabstract
+
+processabstract::processabstract(model *m) {
+ globalmodel=m;
+ br=new bitreader(globalmodel,m->gethashtable());
+ dirtyflag=false;
+}
+
+bool processabstract::dirtyflagstatus() {
+ return dirtyflag;
+}
+
+void processabstract::setclean() {
+ dirtyflag=false;
+}
+
+
+bool processabstract::evaluatestatementa(Statementa *sa, Hashtable *env) {
+ switch(sa->gettype()) {
+ case STATEMENTA_OR:
+ return evaluatestatementa(sa->getleft(),env)||evaluatestatementa(sa->getright(),env);
+ case STATEMENTA_AND:
+ return evaluatestatementa(sa->getleft(),env)&&evaluatestatementa(sa->getright(),env);
+ case STATEMENTA_NOT:
+ return !evaluatestatementa(sa->getleft(),env);
+ case STATEMENTA_EQUALS: {
+ Element *left=evaluateexpr(globalmodel,sa->getleftee(),env,true,true);
+ Element *right=evaluateexpr(globalmodel,sa->getrightee(),env,true,true);
+ bool tvalue=left->equals(right);
+ delete(left);
+ delete(right);
+ return tvalue;
+ }
+ case STATEMENTA_SET: {
+ Element *left=evaluateexpr(globalmodel,sa->getleftee(),env,true,true);
+ Set *set=sa->getset();
+ if (set->gettype()==SET_label) {
+ DomainSet *ds=globalmodel->getdomainrelation()->getset(set->getname());
+ if (ds->getset()->contains(left)) {
+ delete(left);
+ return true;
+ } else {
+ delete(left);
+ return false;
+ }
+ } else if (set->gettype()==SET_literal) {
+ for(int j=0;j<set->getnumliterals();j++) {
+ Literal *l=set->getliteral(j);
+ switch(l->gettype()) {
+ case LITERAL_NUMBER:
+ if(left->isnumber()&&
+ left->intvalue()==l->number()) {
+ delete(left);
+ return true;
+ }
+ case LITERAL_TOKEN:
+ if((left->type()==ELEMENT_TOKEN)&&
+ equivalentstrings(left->gettoken(),l->token())) {
+ delete(left);
+ return true;
+ }
+ }
+ }
+ delete(left);
+ return false;
+ }
+ }
+ case STATEMENTA_VALID: {
+ Element *left=evaluateexpr(globalmodel,sa->getleftee(),env,true,true);
+ if (left->type()!=ELEMENT_OBJECT) {
+ printf("ERROR in processabstract.cc\n");
+ }
+ if (left->getobject()==NULL) {
+ delete(left);
+ return new Element(false);
+ }
+ char *structuretype=sa->getvalidtype();
+ structure *st=(structuretype==NULL)?left->getstructure():globalmodel->getstructure(structuretype);
+ bool validity=globalmodel->gettypemap()->istype(left->getobject(),st);
+ delete(left);
+ return new Element(validity);
+ }
+
+ case STATEMENTA_LT: {
+ Element *left=evaluateexpr(globalmodel,sa->getleftee(),env,true,true);
+ Element *right=evaluateexpr(globalmodel,sa->getrightee(),env,true,true);
+ if (!left->isnumber()||
+ !right->isnumber()) {
+ printf("Bad lt compare\n");
+ exit(-1);
+ }
+ bool tvalue=left->intvalue()<right->intvalue();
+ delete(left);
+ delete(right);
+ return tvalue;
+ }
+ case STATEMENTA_TRUE:
+ return true;
+ }
+}
+
+
+/* a Statementb is of the type "E in S" or "<E,E> in R" so we just add the
+ respective element to S or R if the statement is not satisfied */
+void processabstract::satisfystatementb(Statementb *sb, Hashtable *env) {
+ switch(sb->gettype()) {
+ case STATEMENTB_SING: {
+ Element *ele=evaluateexpr(globalmodel,sb->getleft(),env,true,true);
+ /*if (sb->gettleft()!=NULL) {
+ Element **earray=new Element *[sb->gettleft()->getnumexpr()];
+ for(int i=0;i<sb->gettleft()->getnumexpr();i++) {
+ earray[i]=evaluateexpr(br,sb->gettleft()->getexpr(i),env);
+ }
+ ele->setnewparams(earray,sb->gettleft()->getnumexpr());
+ }*/
+ if (ele==NULL)
+ break;
+ if (!globalmodel->getdomainrelation()->getset(sb->getsetlabel()->getname())->getset()->contains(ele)) {
+ dirtyflag=true;
+#ifdef DEBUGMANYMESSAGES
+ printf("element: ");
+ ele->print();
+ printf(" into %s\n",sb->getsetlabel()->getname());
+#endif
+ globalmodel->getdomainrelation()->abstaddtoset(ele,globalmodel->getdomainrelation()->getset(sb->getsetlabel()->getname()),globalmodel);
+ } else {
+ delete(ele);
+ }
+ break;
+ }
+ case STATEMENTB_TUPLE:{
+ Element *left=evaluateexpr(globalmodel,sb->getleft(),env,true,true);
+ if (left==NULL)
+ break;
+ Element *right=evaluateexpr(globalmodel,sb->getright(),env,true,true);
+ if (right==NULL) {
+ delete(left);
+ break;
+ }
+ /* if (sb->gettleft()!=NULL) {
+ Element **earray=new Element *[sb->gettleft()->getnumexpr()];
+ for(int i=0;i<sb->gettleft()->getnumexpr();i++) {
+ earray[i]=evaluateexpr(br,sb->gettleft()->getexpr(i),env);
+ }
+ left->setnewparams(earray,sb->gettleft()->getnumexpr());
+ }*/
+ /* if (sb->gettright()!=NULL) {
+ Element **earray=new Element *[sb->gettright()->getnumexpr()];
+ for(int i=0;i<sb->gettright()->getnumexpr();i++) {
+ earray[i]=evaluateexpr(br,sb->gettright()->getexpr(i),env);
+ }
+ right->setnewparams(earray,sb->gettright()->getnumexpr());
+ }*/
+ if (!globalmodel->getdomainrelation()->getrelation(sb->getsetlabel()->getname())->getrelation()->contains(left,right)) {
+ dirtyflag=true;
+ paircount++;
+#ifdef DEBUGMANYMESSAGES
+ printf("element: <");
+ left->print();
+ printf(",");
+ right->print();
+ printf("> into %s\n",sb->getsetlabel()->getname());
+#endif
+ globalmodel->getdomainrelation()->getrelation(sb->getsetlabel()->getname())->getrelation()->put(left,right);
+ } else {
+ delete(left);
+ delete(right);
+ }
+ break;
+ }
+ }
+}
+
+void processabstract::printstats() {
+ printf("Abstraction Rules Checked: %d Triggered: %d\n",abstractcheck,abstracttrigger);
+ printf("Pair count: %d\n",paircount);
+}
+
+void processabstract::processrule(Rule *r) {
+ State *st=new State(r, globalmodel->gethashtable());
+ if (st->initializestate(br, globalmodel)) {
+ while(true) {
+ abstractcheck++;
+ if (evaluatestatementa(r->getstatementa(),st->env)) {
+ abstracttrigger++;
+ satisfystatementb(r->getstatementb(),st->env);
+ }
+ if (!st->increment(br, globalmodel))
+ break; /* done */
+ }
+ }
+ delete(st);
+}
+
+void processabstract::processrule(Rule *r, Element *ele, char *set) {
+ int count=-1;
+
+
+ for(int i=0;i<r->numquants();i++) {
+ AQuantifier *aq=r->getquant(i);
+ switch(aq->gettype()) {
+ case AQUANTIFIER_SING:
+ count=i;
+ break;
+ default:
+ break;
+ }
+ }
+
+ AQuantifier *aq=r->getquant(count);
+ if (!equivalentstrings(aq->getset()->getname(),set))
+ return;
+
+ Hashtable *env=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
+ env->setparent(globalmodel->gethashtable());
+
+ RelationSet **relset=new RelationSet*[r->numquants()-1];
+ int c=0;
+ for(int i=0;i<r->numquants();i++) {
+ if (i!=count) {
+ AQuantifier *aq=r->getquant(i);
+ RelationSet *rs=new RelationSet(aq->getleft()->label(),aq->getlower(),aq->getupper());
+ rs->incrementassignment(br,env,globalmodel);
+ relset[c++]=rs;
+ }
+ }
+
+ env->put(aq->getleft()->label(),ele);
+ bool flag=true;
+ while(flag) {
+ if (evaluatestatementa(r->getstatementa(),env))
+ satisfystatementb(r->getstatementb(),env);
+ int i=r->numquants()-2;
+ for(;i>=0;i--) {
+ if (relset[i]->incrementassignment(br,env,globalmodel)) {
+ break;
+ } else {
+ relset[i]->resetassignment(env);
+ if (!relset[i]->incrementassignment(br,env,globalmodel)) {
+ flag=false;
+ break;
+ }
+ }
+ }
+ if (i==-1)
+ flag=false;
+ }
+ for(int i=0;i<r->numquants()-1;i++) {
+ delete(relset[i]);
+ }
+ delete(relset);
+ delete(env);
+}
+
+processabstract::~processabstract() {
+ delete(br);
+}
+
+
+
+
+
+// class State
+
+State::State(Rule *r, Hashtable *oldenv) {
+ env=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);;
+ env->setparent(oldenv);
+ numrelset=r->numquants();
+ relset=new RelationSet*[numrelset];
+ for(int i=0;i<r->numquants();i++) {
+ AQuantifier *aq=r->getquant(i);
+
+ switch(aq->gettype()) {
+ case AQUANTIFIER_SING:
+ relset[i]=new RelationSet(aq->getset(),aq->getleft()->label(),aq->gettleft());
+ break;
+ case AQUANTIFIER_TUPLE:
+ relset[i]=new RelationSet(aq->getset(),aq->getleft()->label(),aq->gettleft(),aq->getright()->label(),aq->gettright());
+ break;
+ case AQUANTIFIER_RANGE:
+ relset[i]=new RelationSet(aq->getleft()->label(),aq->getlower(),aq->getupper());
+ break;
+ }
+ }
+}
+
+
+
+State::State(Constraint *c,Hashtable *oldenv) {
+ env=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);;
+ env->setparent(oldenv);
+ numrelset=c->numquants();
+ relset=new RelationSet*[numrelset];
+ for(int i=0;i<c->numquants();i++) {
+ Quantifier *q=c->getquant(i);
+ relset[i]=new RelationSet(q->getset(),q->getlabel()->label(),NULL);
+ }
+}
+
+
+
+State::~State() {
+ delete(env);
+ for(int i=0;i<numrelset;i++)
+ delete(relset[i]);
+ delete[](relset);
+}
+
+
+bool State::initializestate(bitreader *br, model * m) {
+ for(int i=0;i<numrelset;i++) {
+ if (!relset[i]->incrementassignment(br,env,m))
+ return false;
+ }
+ return true;
+}
+
+
+/* initializes all quantifiers of this constraint and returns false
+ if there exists a quantifier that cannot be initialized */
+bool State::initializestate(model * m) {
+ for(int i=0;i<numrelset;i++) {
+ if (!relset[i]->incrementassignment(env,m))
+ return false;
+ }
+ return true;
+}
+
+bool State::initializestate(processconcrete *pc,model * m) {
+ for(int i=0;i<numrelset;i++) {
+ if (!relset[i]->incrementassignment(pc,env,m))
+ return false;
+ }
+ return true;
+}
+
+bool State::increment(bitreader *br, model *m) {
+ for(int i=numrelset-1;i>=0;i--) {
+ if (relset[i]->incrementassignment(br,env,m))
+ return true;
+ else {
+ relset[i]->resetassignment(env);
+ if (!relset[i]->incrementassignment(br,env,m))
+ return false;
+ }
+ }
+ return false;
+}
+
+bool State::increment(model *m) {
+ for(int i=numrelset-1;i>=0;i--) {
+ if (relset[i]->incrementassignment(env,m))
+ return true;
+ else {
+ relset[i]->resetassignment(env);
+ if (!relset[i]->incrementassignment(env,m))
+ return false;
+ }
+ }
+ return false;
+}
+
+bool State::increment(processconcrete *pc,model *m) {
+ for(int i=numrelset-1;i>=0;i--) {
+ if (relset[i]->incrementassignment(pc,env,m))
+ return true;
+ else {
+ relset[i]->resetassignment(env);
+ if (!relset[i]->incrementassignment(pc,env,m))
+ return false;
+ }
+ }
+ return false;
+}
+
+
+
+Element * evaluateexpr(model *m,AElementexpr *ee, Hashtable *env, bool enforcetyping, bool compute) {
+ bitreader *br=m->getbitreader();
+ switch(ee->gettype()) {
+ case AELEMENTEXPR_NULL:
+ return new Element();
+ case AELEMENTEXPR_LABEL: {
+ Element *r=new Element((Element *)env->get(ee->getlabel()->label()));
+ typemap *tm=m->gettypemap();
+ if (compute)
+ if(r->type()==ELEMENT_OBJECT&&
+ r->getobject()!=NULL&&
+ !tm->asserttype(r->getobject(),r->getstructure())) {
+ delete(r);
+ return NULL;
+ }
+ return r;
+ }
+ case AELEMENTEXPR_SUB: {
+ AElementexpr *left=ee->getleft();
+ AElementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(m,left,env,true,compute);
+ if (leftval==NULL)
+ return NULL;
+ Element *rightval=evaluateexpr(m,right,env,true,compute);
+ if (rightval==NULL) {
+ delete(leftval);
+ return NULL;
+ }
+ Element *diff=new Element(leftval->intvalue()-rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return diff;
+ }
+ case AELEMENTEXPR_ADD: {
+ AElementexpr *left=ee->getleft();
+ AElementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(m,left,env,true,compute);
+ if (leftval==NULL)
+ return NULL;
+ Element *rightval=evaluateexpr(m,right,env,true,compute);
+ if (rightval==NULL) {
+ delete(leftval);
+ return NULL;
+ }
+ Element *sum=new Element(leftval->intvalue()+rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return sum;
+ }
+ case AELEMENTEXPR_MULT: {
+ AElementexpr *left=ee->getleft();
+ AElementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(m,left,env,true,compute);
+ if (leftval==NULL)
+ return NULL;
+ Element *rightval=evaluateexpr(m,right,env,true,compute);
+ if (rightval==NULL) {
+ delete(leftval);
+ return NULL;
+ }
+ Element *diff=new Element(leftval->intvalue()*rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return diff;
+ }
+ case AELEMENTEXPR_DIV: {
+ AElementexpr *left=ee->getleft();
+ AElementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(m,left,env,true,compute);
+ if (leftval==NULL)
+ return NULL;
+ Element *rightval=evaluateexpr(m,right,env,true,compute);
+ if (rightval==NULL) {
+ delete(leftval);
+ return NULL;
+ }
+ Element *diff=new Element(leftval->intvalue()/rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return diff;
+ }
+ case AELEMENTEXPR_LIT: {
+ Literal *l=ee->getliteral();
+ switch(l->gettype()) {
+ case LITERAL_NUMBER:
+ return new Element(l->number());
+ case LITERAL_TOKEN:
+ return new Element(copystr(l->token()));
+ case LITERAL_BOOL:
+ return new Element(l->getbool());
+ default:
+ printf("ERROR with lit type\n");
+ exit(-1);
+ }
+ }
+ case AELEMENTEXPR_FIELD: {
+ Element *e=evaluateexpr(m,ee->getleft(),env,true,compute);
+ if (e==NULL)
+ return NULL;
+ Element *r=br->readfieldorarray(e,ee->getfield(),NULL);
+ delete(e);
+ if (r==NULL)
+ return NULL;
+ if (enforcetyping&&compute) {
+ typemap *tm=m->gettypemap();
+ if(r->type()==ELEMENT_OBJECT&&
+ r->getobject()!=NULL&&
+ !tm->asserttype(r->getobject(),r->getstructure())) {
+ delete(r);
+ return NULL;
+ }
+ } else if (compute) {
+ typemap *tm=m->gettypemap();
+ if(r->type()==ELEMENT_OBJECT&&
+ r->getobject()!=NULL&&
+ !tm->istype(r->getobject(),r->getstructure())) {
+ delete(r);
+ return NULL;
+ }
+ }
+ return r;
+ }
+ case AELEMENTEXPR_CAST: {
+ Element *e=evaluateexpr(m,ee->getleft(),env,true,compute);
+ if (e==NULL)
+ return NULL;
+ typemap *tm=m->gettypemap();
+ if (e->getobject()!=NULL&&compute&&
+ !tm->asserttype(e->getobject(),m->getstructure(ee->getcasttype()))) {
+ delete(e);
+ return NULL;
+ }
+ Element *r=new Element(e->getobject(),m->getstructure(ee->getcasttype()));
+ delete(e);
+ return r;
+ }
+ case AELEMENTEXPR_FIELDARRAY: {
+ Element *e=evaluateexpr(m,ee->getleft(),env,true,compute);
+ if (e==NULL)
+ return NULL;
+ Element *ind=evaluateexpr(m,ee->getright(),env,true,compute);
+ if (ind==NULL) {
+ delete(e);
+ return NULL;
+ }
+ Element *r=br->readfieldorarray(e,ee->getfield(),ind);
+ delete(ind);
+ delete(e);
+ if (r==NULL)
+ return NULL;
+ if (enforcetyping&&compute) {
+ typemap *tm=m->gettypemap();
+ if(r->type()==ELEMENT_OBJECT&&
+ r->getobject()!=NULL&&
+ !tm->asserttype(r->getobject(),r->getstructure())) {
+ delete(r);
+ return NULL;
+ }
+ } else if (compute) {
+ typemap *tm=m->gettypemap();
+ if(r->type()==ELEMENT_OBJECT&&
+ r->getobject()!=NULL&&
+ !tm->istype(r->getobject(),r->getstructure())) {
+ delete(r);
+ return NULL;
+ }
+ }
+ return r;
+ }
+ }
+}
+
+
+// prints the current state
+void State::print(model *m)
+{
+ for(int i=0; i<numrelset; i++)
+ {
+ relset[i]->print(env, m);
+ printf(" ");
+ }
+}
+
+
+
+
+// class RelationSet
+
+RelationSet::RelationSet(Set *s, char *l,Type *tl) {
+ set=s;
+ type=TYPE_SET;
+ left=l;
+ tleft=tl;
+ tright=NULL;
+ right=NULL;
+}
+
+RelationSet::RelationSet(Set *s,char *l, Type *tl,char *r,Type *tr) {
+ set=s;
+ type=TYPE_RELATION;
+ left=l;
+ tleft=tl;
+ tright=tr;
+ right=r;
+}
+
+RelationSet::RelationSet(char *l,AElementexpr *lower,AElementexpr*upper) {
+ this->lower=lower;
+ this->upper=upper;
+ left=l;
+ type=TYPE_RANGE;
+}
+
+int RelationSet::gettype() {
+ return type;
+}
+
+void RelationSet::resetassignment(Hashtable *env) {
+ switch(type) {
+ case TYPE_SET:
+ env->remove(left);
+ break;
+ case TYPE_RELATION:
+ env->remove(left);
+ env->remove(right);
+ break;
+ case TYPE_RANGE:
+ env->remove(left);
+ break;
+ }
+}
+
+bool RelationSet::incrementassignment(bitreader *br,Hashtable *env, model *m) {
+ switch(type) {
+ case TYPE_SET: {
+ if (set->gettype()==SET_label) {
+ DomainSet *ds=m->getdomainrelation()->getset(set->getname());
+
+ if (!env->contains(left)) {
+ Element *fele=(Element *)ds->getset()->firstelement();
+ if (fele==NULL)
+ return false;
+ env->put(left,fele);
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==ele->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),ele->paramvalue(i));
+ }
+ }*/
+ return true;
+ }
+ Element *ele=(Element *)env->get(left);
+ Element *nextele=(Element *)ds->getset()->getnextelement(ele);
+ if (nextele==NULL)
+ return false;
+ else {
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==nextele->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),nextele->paramvalue(i));
+ }
+ }*/
+ env->put(left,nextele);
+ return true;
+ }
+ } else if(set->gettype()==SET_literal) {
+
+ if (!env->contains(left)) {
+ Literal *l=set->getliteral(0);
+ switch(l->gettype()) {
+ case LITERAL_NUMBER:
+ env->put(left,new Element(l->number()));
+ break;
+ case LITERAL_TOKEN:
+ env->put(left,new Element(l->token()));
+ break;
+ }
+ return true;
+ }
+ Element *ele=(Element *)env->get(left);
+ for(int j=0;j<set->getnumliterals();j++) {
+ Literal *l=set->getliteral(j);
+ switch(l->gettype()) {
+ case LITERAL_NUMBER:
+ if(ele->isnumber()&&
+ ele->intvalue()==l->number()) {
+ if ((j+1)<set->getnumliterals()) {
+ env->put(left,new Element(set->getliteral(j+1)->number()));
+ delete(ele);
+ return true;
+ }
+ else return false;
+ }
+ case LITERAL_TOKEN:
+ if((ele->type()==ELEMENT_TOKEN)&&
+ equivalentstrings(ele->gettoken(),l->token())) {
+ if ((j+1)<set->getnumliterals()) {
+ env->put(left,new Element(set->getliteral(j+1)->token()));
+ delete(ele);
+ return true;
+ }
+ else return false;
+ }
+ }
+ }
+ }
+ }
+ case TYPE_RELATION: {
+ DRelation *dr=m->getdomainrelation()->getrelation(set->getname());
+ Element *eleleft=(Element *)env->get(left);
+ Element *eleright=(Element *)env->get(right);
+ if ((eleleft==NULL)||(eleright==NULL)) {
+ if((eleleft!=NULL)||(eleright!=NULL)) {
+ printf("ERROR in TYPE_RELATION in processabstract.cc\n");
+ exit(-1);
+ }
+ Tuple t=dr->getrelation()->firstelement();
+ if (t.isnull())
+ return false;
+ env->put(left,t.left);
+ env->put(right,t.right);
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==((Element *)t.left)->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),((Element *)t.left)->paramvalue(i));
+ }
+ }*/
+ /* if (tright!=NULL) {
+ assert(tright->getnumlabels()==((Element *)t.right)->getnumparams());
+ for (int i=0;i<tright->getnumlabels();i++) {
+ env->put(tright->getlabel(i)->label(),((Element *)t.right)->paramvalue(i));
+ }
+ }*/
+
+ return true;
+ }
+ Tuple nextele=dr->getrelation()->getnextelement(eleleft,eleright);
+ if (nextele.isnull())
+ return false;
+ else {
+ env->put(left,nextele.left);
+ env->put(right,nextele.right);
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==((Element *)nextele.left)->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),((Element *)nextele.left)->paramvalue(i));
+ }
+ }*/
+ /* if (tright!=NULL) {
+ assert(tright->getnumlabels()==((Element *)nextele.right)->getnumparams());
+ for (int i=0;i<tright->getnumlabels();i++) {
+ env->put(tright->getlabel(i)->label(),((Element *)nextele.right)->paramvalue(i));
+ }
+ }*/
+ return true;
+ }
+ }
+ case TYPE_RANGE: {
+
+ if (!env->contains(left)) {
+ Element *lowerele=(Element *)evaluateexpr(m,lower,env,true,true);
+ env->put(left,lowerele);
+ return true;
+ }
+ Element *val=(Element *)env->get(left);
+ Element *upperele=evaluateexpr(m,upper,env,true,true);
+ if (val->intvalue()>=upperele->intvalue()) {
+ delete(upperele);
+ return false;
+ } else {
+ Element *nval=new Element(val->intvalue()+1);
+ env->put(left,nval);
+ delete(val);
+ return true;
+ }
+ }
+ }
+}
+
+bool RelationSet::incrementassignment(processconcrete *pc,Hashtable *env, model *m) {
+ switch(type) {
+ case TYPE_SET: {
+ if (set->gettype()==SET_label) {
+ DomainSet *ds=m->getdomainrelation()->getset(set->getname());
+
+ if (!env->contains(left)) {
+ Element *fele=(Element *)ds->getset()->firstelement();
+ if (fele==NULL)
+ return false;
+ env->put(left,fele);
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==ele->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),ele->paramvalue(i));
+ }
+ }*/
+ return true;
+ }
+ Element *ele=(Element *)env->get(left);
+ Element *nextele=(Element *)ds->getset()->getnextelement(ele);
+ if (nextele==NULL)
+ return false;
+ else {
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==nextele->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),nextele->paramvalue(i));
+ }
+ }*/
+ env->put(left,nextele);
+ return true;
+ }
+ } else if(set->gettype()==SET_literal) {
+
+ if (!env->contains(left)) {
+ Literal *l=set->getliteral(0);
+ switch(l->gettype()) {
+ case LITERAL_NUMBER:
+ env->put(left,new Element(l->number()));
+ break;
+ case LITERAL_TOKEN:
+ env->put(left,new Element(l->token()));
+ break;
+ }
+ return true;
+ }
+ Element *ele=(Element *)env->get(left);
+ for(int j=0;j<set->getnumliterals();j++) {
+ Literal *l=set->getliteral(j);
+ switch(l->gettype()) {
+ case LITERAL_NUMBER:
+ if(ele->isnumber()&&
+ ele->intvalue()==l->number()) {
+ if ((j+1)<set->getnumliterals()) {
+ env->put(left,new Element(set->getliteral(j+1)->number()));
+ delete(ele);
+ return true;
+ }
+ else return false;
+ }
+ case LITERAL_TOKEN:
+ if((ele->type()==ELEMENT_TOKEN)&&
+ equivalentstrings(ele->gettoken(),l->token())) {
+ if ((j+1)<set->getnumliterals()) {
+ env->put(left,new Element(set->getliteral(j+1)->token()));
+ delete(ele);
+ return true;
+ }
+ else return false;
+ }
+ }
+ }
+ }
+ }
+ case TYPE_RELATION: {
+ DRelation *dr=m->getdomainrelation()->getrelation(set->getname());
+ Element *eleleft=(Element *)env->get(left);
+ Element *eleright=(Element *)env->get(right);
+ if ((eleleft==NULL)||(eleright==NULL)) {
+ if((eleleft!=NULL)||(eleright!=NULL)) {
+ printf("ERROR in TYPE_RELATION in processabstract.cc\n");
+ exit(-1);
+ }
+ Tuple t=dr->getrelation()->firstelement();
+ if (t.isnull())
+ return false;
+ env->put(left,t.left);
+ env->put(right,t.right);
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==((Element *)t.left)->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),((Element *)t.left)->paramvalue(i));
+ }
+ }*/
+ /* if (tright!=NULL) {
+ assert(tright->getnumlabels()==((Element *)t.right)->getnumparams());
+ for (int i=0;i<tright->getnumlabels();i++) {
+ env->put(tright->getlabel(i)->label(),((Element *)t.right)->paramvalue(i));
+ }
+ }*/
+
+ return true;
+ }
+ Tuple nextele=dr->getrelation()->getnextelement(eleleft,eleright);
+ if (nextele.isnull())
+ return false;
+ else {
+ env->put(left,nextele.left);
+ env->put(right,nextele.right);
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==((Element *)nextele.left)->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),((Element *)nextele.left)->paramvalue(i));
+ }
+ }*/
+ /* if (tright!=NULL) {
+ assert(tright->getnumlabels()==((Element *)nextele.right)->getnumparams());
+ for (int i=0;i<tright->getnumlabels();i++) {
+ env->put(tright->getlabel(i)->label(),((Element *)nextele.right)->paramvalue(i));
+ }
+ }*/
+ return true;
+ }
+ }
+ case TYPE_RANGE: {
+
+ if (!env->contains(left)) {
+ env->put(left,pc->evaluateexpr((CAElementexpr *)lower, env));
+ return true;
+ }
+ Element *val=(Element *)env->get(left);
+ Element *upperele=pc->evaluateexpr((CAElementexpr *)upper,env);
+ if (val->intvalue()>=upperele->intvalue()) {
+ delete(upperele);
+ return false;
+ } else {
+ Element *nval=new Element(val->intvalue()+1);
+ env->put(left,nval);
+ delete(val);
+ return true;
+ }
+ }
+ }
+}
+
+
+/* increments the value of "left" and returns "false" if this is not possible.
+ When this method is called for the first time, it simply initializes
+ the value of the quantifier ("left") */
+bool RelationSet::incrementassignment(Hashtable *env, model *m) {
+ switch(type) {
+ case TYPE_SET: {
+ if (set->gettype()==SET_label) {
+ DomainSet *ds=m->getdomainrelation()->getset(set->getname());
+
+ Element *ele=NULL;
+ if (!env->contains(left)) {
+ ele=(Element *)ds->getset()->firstelement();
+ if (ele==NULL)
+ return false;
+ env->put(left,ele);
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==ele->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),ele->paramvalue(i));
+ }
+ }*/
+ return true;
+ }
+
+ ele=(Element *) env->get(left);
+ Element *nextele=(Element *)ds->getset()->getnextelement(ele);
+ if (nextele==NULL)
+ return false;
+ else {
+ /* if (tleft!=NULL) {
+ assert(tleft->getnumlabels()==nextele->getnumparams());
+ for (int i=0;i<tleft->getnumlabels();i++) {
+ env->put(tleft->getlabel(i)->label(),nextele->paramvalue(i));
+ }
+ }*/
+ env->put(left,nextele);
+ return true;
+ }
+ }
+ }
+ }
+}
+
+
+// prints the quantifier and its current state
+void RelationSet::print(Hashtable *env, model *m)
+{
+ switch(type) {
+ case TYPE_SET: {
+ if (set->gettype()==SET_label)
+ {
+ printf("%s=", left);
+ DomainSet *ds=m->getdomainrelation()->getset(set->getname());
+ Element *ele = (Element *) env->get(left);
+ ele->print();
+ printf("\n");
+ }
+ }}
+}
--- /dev/null
+// evaluates model definition rules
+
+#ifndef PROCESSABSTRACT_H
+#define PROCESSABSTRACT_H
+#include "classlist.h"
+
+
+Element * evaluateexpr(model *m, AElementexpr *ee, Hashtable *env,bool enforcetyping,bool compute);
+
+
+
+class processabstract {
+ public:
+ processabstract(model *m);
+ void processrule(Rule *r);
+ void setclean();
+ void printstats();
+ bool dirtyflagstatus();
+ ~processabstract();
+ void processrule(Rule *r, Element *ele, char *set);
+ private:
+ bool evaluatestatementa(Statementa *sa, Hashtable *env);
+ void satisfystatementb(Statementb *sb, Hashtable *env);
+ model * globalmodel;
+ bool dirtyflag;
+ bitreader * br;
+};
+
+
+
+
+/* A RelationSet keeps the current state of a quantifier.
+ There are three types of RelationSet's:
+ TYPE_SET: "for left in set"
+ TYPE_RELATION: "for <left,right> in set"
+ TYPE_RANGE: "for left=lower..upper */
+#define TYPE_SET 1
+#define TYPE_RELATION 2
+#define TYPE_RANGE 3
+
+class RelationSet {
+ public:
+ RelationSet(Set *s, char *l, Type *tl);
+ RelationSet(Set *s, char *l, Type *tl, char *r, Type *tr);
+ RelationSet(char *l,AElementexpr *lower,AElementexpr*upper);
+ int gettype();
+ bool incrementassignment(bitreader *br,Hashtable *env, model *m);
+ bool incrementassignment(Hashtable *env, model *m);
+ bool incrementassignment(processconcrete *pc,Hashtable *env, model *m);
+ void resetassignment(Hashtable *env);
+
+ void print(Hashtable *env, model *m); // prints the quantifier and its current state
+
+ AElementexpr *lower,*upper;
+ char *left,*right;
+ Type *tleft,*tright;
+ /* char's are not the responsibility of this class to dispose of*/
+ int type;
+ Set *set;
+};
+
+
+
+
+// Keeps the current state of the quantifiers of a given rule or constraint
+class State {
+ public:
+ State(Rule *r, Hashtable *h);
+ State(Constraint *c, Hashtable *h);
+ ~State();
+ bool initializestate(bitreader *br, model *m);
+ bool increment(bitreader *br, model *m);
+ bool initializestate(model *m);
+ bool increment(model *m);
+
+ bool initializestate(processconcrete*, model *m);
+ bool increment(processconcrete*, model *m);
+
+ void print(model *m);
+
+ Hashtable *env;
+ RelationSet **relset;
+ int numrelset;
+
+};
+#endif
--- /dev/null
+#include <stdlib.h>
+#include <assert.h>
+#include "processconcrete.h"
+#include "processabstract.h"
+#include "amodel.h"
+#include "omodel.h"
+#include "dmodel.h"
+#include "cmodel.h"
+#include "Hashtable.h"
+#include "element.h"
+#include "common.h"
+#include "bitreader.h"
+#include "bitwriter.h"
+#include "model.h"
+#include "set.h"
+#include "Relation.h"
+static int concretecheck=0;
+static int concretetrigger=0;
+
+processconcrete::processconcrete(model *m) {
+ globalmodel=m;
+ bw=new bitwriter(globalmodel,m->gethashtable());
+ br=new bitreader(globalmodel,m->gethashtable());
+}
+
+void processconcrete::printstats() {
+ printf("Concretization Rules Checked: %d Triggered: %d\n",concretecheck,concretetrigger);
+}
+
+
+void processconcrete::processrule(Rule *r) {
+ State *st=new State(r,globalmodel->gethashtable());
+ if (st->initializestate(this, globalmodel)) {
+ while(true) {
+ concretecheck++;
+ if (evaluatestatementa(r->getstatementa(),st->env)) {
+ concretetrigger++;
+ satisfystatementb((CStatementb *)r->getstatementb(),st->env);
+ }
+
+ if (!st->increment(this, globalmodel))
+ break; /* done */
+ }
+ }
+ delete(st);
+}
+
+processconcrete::~processconcrete() {
+ delete(br);
+}
+
+bool processconcrete::evaluatestatementa(Statementa *sa, Hashtable *env) {
+ switch(sa->gettype()) {
+ case STATEMENTA_OR:
+ return evaluatestatementa(sa->getleft(),env)||evaluatestatementa(sa->getright(),env);
+ case STATEMENTA_AND:
+ return evaluatestatementa(sa->getleft(),env)&&evaluatestatementa(sa->getright(),env);
+ case STATEMENTA_NOT:
+ return !evaluatestatementa(sa->getleft(),env);
+ case STATEMENTA_EQUALS: {
+ Element *left=evaluateexpr((CAElementexpr *)sa->getleftee(),env);
+ Element *right=evaluateexpr((CAElementexpr *)sa->getrightee(),env);
+ bool tvalue=left->equals(right);
+ delete(left);
+ delete(right);
+ return tvalue;
+ }
+ case STATEMENTA_LT: {
+ Element *left=evaluateexpr((CAElementexpr *)sa->getleftee(),env);
+ Element *right=evaluateexpr((CAElementexpr *)sa->getrightee(),env);
+ if (!left->isnumber()||
+ !right->isnumber()) {
+ printf("Bad lt compare\n");
+ exit(-1);
+ }
+ bool tvalue=left->intvalue()<right->intvalue();
+ delete(left);
+ delete(right);
+ return tvalue;
+ }
+ case STATEMENTA_TRUE:
+ return true;
+ }
+}
+
+void processconcrete::satisfystatementb(CStatementb *sb, Hashtable *env) {
+ Element * rvalue=evaluateexpr((CAElementexpr *)sb->getright(),env);
+ Element *index=NULL;
+ if (sb->gettype()==CSTATEMENTB_ARRAYASSIGN)
+ index=evaluateexpr((CAElementexpr *)sb->getleft(),env);
+ Field *field=sb->getfield();
+ Element *src=evaluateexpr(sb->getexpr(),env);
+ bw->writefieldorarray(src,field,index,rvalue);
+ delete(rvalue);
+ if (index!=NULL)
+ delete(index);
+ delete(src);
+}
+
+Element * processconcrete::evaluateexpr(Expr *e, Hashtable *env) {
+ switch(e->gettype()) {
+ case EXPR_LABEL:
+ return new Element((Element *)env->get(e->getlabel()->label()));
+ case EXPR_FIELD: {
+ Element *old=evaluateexpr(e->getexpr(),env);
+ Element *newe=br->readfieldorarray(evaluateexpr(e->getexpr(),env),e->getfield(),NULL);
+ delete(old);
+ return newe;
+ }
+ case EXPR_CAST: {
+ Element *old=evaluateexpr(e->getexpr(),env);
+ char *type=e->getcasttype();
+ structure *st=globalmodel->getstructure(type);
+ Element *newe=new Element(old->getobject(),st);
+ delete(old);
+ return newe;
+ }
+ case EXPR_ARRAY: {
+ Element *old=evaluateexpr(e->getexpr(),env);
+ Element *index=evaluateexpr(e->getindex(),env);
+ Element *newe=br->readfieldorarray(evaluateexpr(e->getexpr(),env),e->getfield(),index);
+ delete(old);
+ delete(index);
+ return newe;
+ }
+ }
+}
+
+Element * processconcrete::evaluateexpr(CAElementexpr *ee, Hashtable *env) {
+ switch(ee->gettype()) {
+ case CAELEMENTEXPR_LABEL:
+ {
+ return new Element((Element *)env->get(ee->getlabel()->label()));
+ }
+ case CAELEMENTEXPR_NULL:
+ {
+ return new Element();
+ }
+ case CAELEMENTEXPR_SUB:
+ {
+ CAElementexpr *left=ee->getleft();
+ CAElementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(left,env);
+ Element *rightval=evaluateexpr(right,env);
+ Element *diff=new Element(leftval->intvalue()-rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return diff;
+ }
+ case CAELEMENTEXPR_ADD:
+ {
+ CAElementexpr *left=ee->getleft();
+ CAElementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(left,env);
+ Element *rightval=evaluateexpr(right,env);
+ Element *sum=new Element(leftval->intvalue()+rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return sum;
+ }
+ case CAELEMENTEXPR_MULT:
+ {
+ CAElementexpr *left=ee->getleft();
+ CAElementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(left,env);
+ Element *rightval=evaluateexpr(right,env);
+ Element *diff=new Element(leftval->intvalue()*rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return diff;
+ }
+ case CAELEMENTEXPR_DIV:
+ {
+ CAElementexpr *left=ee->getleft();
+ CAElementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(left,env);
+ Element *rightval=evaluateexpr(right,env);
+ Element *diff=new Element(leftval->intvalue()/rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return diff;
+ }
+ case CAELEMENTEXPR_LIT:
+ {
+ Literal *l=ee->getliteral();
+ switch(l->gettype()) {
+ case LITERAL_NUMBER:
+ return new Element(l->number());
+ case LITERAL_TOKEN:
+ return new Element(copystr(l->token()));
+ case LITERAL_BOOL:
+ return new Element(l->getbool());
+ default:
+ printf("ERROR with lit type\n");
+ exit(-1);
+ }
+ }
+ case CAELEMENTEXPR_SIZEOF:
+ {
+ Setexpr * setexpr=ee->getsetexpr();
+ switch(setexpr->gettype()) {
+ case SETEXPR_LABEL:
+ return new Element(globalmodel->getdomainrelation()->getset(setexpr->getsetlabel()->getname())->getset()->size());
+ case SETEXPR_REL: {
+ Element *key=(Element *)env->get(setexpr->getlabel()->label());
+ WorkSet *ws=globalmodel->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->getset(key);
+ if (ws==NULL)
+ return new Element(0);
+ else
+ return new Element(ws->size());
+ }
+ case SETEXPR_INVREL: {
+ Element *key=(Element *)env->get(setexpr->getlabel()->label());
+ WorkSet *ws=globalmodel->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->invgetset(key);
+ if (ws==NULL)
+ return new Element(0);
+ else
+ return new Element(ws->size());
+ }
+ }
+ }
+ case CAELEMENTEXPR_ELEMENT: {
+ Element *index=evaluateexpr(ee->getleft(),env);
+ int ind=index->intvalue();
+ delete(index);
+
+ Setexpr * setexpr=ee->getsetexpr();
+ switch(setexpr->gettype()) {
+ case SETEXPR_LABEL:
+ return new Element((Element *)globalmodel->getdomainrelation()->getset(setexpr->getsetlabel()->getname())->getset()->getelement(ind));
+ case SETEXPR_REL: {
+ Element *key=(Element *)env->get(setexpr->getlabel()->label());
+ return new Element((Element *)globalmodel->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->getset(key)->getelement(ind));
+ }
+ case SETEXPR_INVREL: {
+ Element *key=(Element *)env->get(setexpr->getlabel()->label());
+ return new Element((Element *)globalmodel->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->invgetset(key)->getelement(ind));
+ }
+ }
+ }
+ case CAELEMENTEXPR_RELATION:
+ {
+ Element *e=evaluateexpr(ee->getleft(),env);
+ Element *r=(Element *)globalmodel->getdomainrelation()->getrelation(ee->getrelation()->getname())->getrelation()->getobj(e);
+ return new Element(r);
+ }
+ }
+}
--- /dev/null
+#ifndef PROCESSCONCRETE_H
+#define PROCESSCONCRETE_H
+#include "classlist.h"
+
+class processconcrete {
+ public:
+ processconcrete(model *m);
+ void processrule(Rule *r);
+ ~processconcrete();
+ Element * evaluateexpr(CAElementexpr *ee, Hashtable *env);
+ void printstats();
+ private:
+ Element * evaluateexpr(Expr *e, Hashtable *env);
+ bool evaluatestatementa(Statementa *sa, Hashtable *env);
+ void satisfystatementb(CStatementb *sb, Hashtable *env);
+ model * globalmodel;
+ bitwriter * bw;
+ bitreader * br;
+};
+
+
+#endif
--- /dev/null
+// evaluates constraints in the ICL
+
+#include <stdlib.h>
+#include "processobject.h"
+#include "processabstract.h"
+#include "omodel.h"
+#include "Hashtable.h"
+#include "element.h"
+#include "model.h"
+#include "dmodel.h"
+#include "set.h"
+#include "Relation.h"
+#include "repair.h"
+#include "normalizer.h"
+#include "Action.h"
+
+static int modelcheck=0;
+static int modeltrigger=0;
+
+processobject::processobject(model *m) {
+ globalmodel=m;
+ repair=m->getrepair();
+}
+
+void processobject::printstats() {
+ printf("Models Rules Checked: %d Triggered: %d\n",modelcheck,modeltrigger);
+}
+
+// evaluates the truth value of the given predicate
+int processobject::processpredicate(Predicate *p, Hashtable *env) {
+ switch(p->gettype()) {
+ case PREDICATE_LT: {
+ Element *left=evaluatevalueexpr(p->getvalueexpr(),env,globalmodel);
+ Element *right=evaluateexpr(p->geteleexpr(),env,globalmodel);
+ if (right==NULL) {
+ return PFAIL;
+ }
+ if (left==NULL) {
+ delete(right);
+ return false;
+ }
+ int t=left->intvalue()<right->intvalue();
+ delete(right);
+ return t;
+ }
+ case PREDICATE_LTE: {
+ Element *left=evaluatevalueexpr(p->getvalueexpr(),env,globalmodel);
+ Element *right=evaluateexpr(p->geteleexpr(),env,globalmodel);
+ if (right==NULL) {return PFAIL;}
+ if (left==NULL) {
+ delete(right);
+ return false;
+ }
+ bool t=left->intvalue()<=right->intvalue();
+ delete(right);
+ return t;
+ }
+ case PREDICATE_EQUALS: {
+ Element *left=evaluatevalueexpr(p->getvalueexpr(),env,globalmodel);
+ Element *right=evaluateexpr(p->geteleexpr(),env,globalmodel);
+ if (right==NULL) {return PFAIL;}
+ if (left==NULL) {
+ delete(right);
+ return false;
+ }
+ /* Can have more than just int's here */
+ bool t=left->equals(right); /*Just ask the equals method*/
+ delete(right);
+ return t;
+ }
+ case PREDICATE_GTE: {
+ Element *left=evaluatevalueexpr(p->getvalueexpr(),env,globalmodel);
+ Element *right=evaluateexpr(p->geteleexpr(),env,globalmodel);
+ if (right==NULL) {return PFAIL;}
+ if (left==NULL) {
+ delete(right);
+ return false;
+ }
+ bool t=left->intvalue()>=right->intvalue();
+ delete(right);
+ return t;
+ }
+ case PREDICATE_GT: {
+ Element *left=evaluatevalueexpr(p->getvalueexpr(),env,globalmodel);
+ Element *right=evaluateexpr(p->geteleexpr(),env,globalmodel);
+ if (right==NULL) {return PFAIL;}
+ if (left==NULL) {
+ delete(right);
+ return false;
+ }
+ bool t=left->intvalue()>right->intvalue();
+ delete(right);
+ return t;
+ }
+ case PREDICATE_SET: {
+ Label *label=p->getlabel();
+ Setexpr * setexpr=p->getsetexpr();
+ Element *labelele=(Element *) env->get(label->label());
+ switch(setexpr->gettype()) {
+ case SETEXPR_LABEL:
+ return globalmodel->getdomainrelation()->getset(setexpr->getsetlabel()->getname())->getset()->contains(labelele);
+ case SETEXPR_REL:
+ return globalmodel->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->getset(setexpr->getlabel()->label())->contains(labelele);
+ case SETEXPR_INVREL:
+ return globalmodel->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->invgetset(setexpr->getlabel()->label())->contains(labelele);
+ }
+ }
+ case PREDICATE_EQ1:
+ case PREDICATE_GTE1: {
+ int setsize;
+ Setexpr * setexpr=p->getsetexpr();
+ switch(setexpr->gettype()) {
+ case SETEXPR_LABEL:
+ setsize=globalmodel->getdomainrelation()->getset(setexpr->getsetlabel()->getname())->getset()->size();
+ break;
+ case SETEXPR_REL: {
+ Element *key=(Element *)env->get(setexpr->getlabel()->label());
+ WorkSet *ws=globalmodel->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->getset(key);
+ if (ws!=NULL)
+ setsize=ws->size();
+ else
+ setsize=0;
+ break;
+ }
+ case SETEXPR_INVREL: {
+ Element *key=(Element *)env->get(setexpr->getlabel()->label());
+ WorkSet *ws=globalmodel->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->invgetset(key);
+ if (ws!=NULL)
+ setsize=ws->size();
+ else
+ setsize=0;
+ break;
+ }
+ }
+ return ((p->gettype()==PREDICATE_EQ1)&&(setsize==1))||
+ ((p->gettype()==PREDICATE_GTE1)&&(setsize>=1));
+ }
+ }
+}
+
+
+// evaluates the truth value of the given statement
+int processobject::processstatement(Statement *s, Hashtable *env) {
+ switch (s->gettype()) {
+ case STATEMENT_OR: {
+ int l=processstatement(s->getleft(),env);
+ int r=processstatement(s->getright(),env);
+ if (l==PFAIL&&(r==PFAIL||r==PFALSE)) return PFAIL;
+ if ((l==PFAIL||l==PFALSE)&&r==PFAIL) return PFAIL;
+ return l||r;
+ }
+ case STATEMENT_AND: {
+ int l=processstatement(s->getleft(),env);
+ int r=processstatement(s->getright(),env);
+ if (l==PFAIL&&(r==PFAIL||r==PTRUE)) return PFAIL;
+ if (r==PFAIL&&(l==PFAIL||l==PTRUE)) return PFAIL;
+ return l&&r;
+ }
+ case STATEMENT_NOT: {
+ int l=processstatement(s->getleft(),env);
+ if (l==PFAIL) return PFAIL;
+ return !l;
+ }
+ case STATEMENT_PRED:
+ return processpredicate(s->getpredicate(),env);
+ }
+}
+
+
+// returns true if and only if the given constraint is satisfied
+bool processobject::issatisfied(Constraint *c)
+{
+ State *st=new State(c,globalmodel->gethashtable());
+ bool satisfied = true;
+ if (st->initializestate(globalmodel))
+ while (true)
+ {
+ if (c->getstatement()!=NULL)
+ if (processstatement(c->getstatement(),st->env)!=PTRUE)
+ satisfied = false;
+ if (!st->increment(globalmodel))
+ break;
+ }
+
+ delete(st);
+ return satisfied;
+}
+
+
+
+/* processed the given constraint and if it's not satisfied,
+ displays a message and tries to repair the constraint
+ The function returns true only if the constraint was initially
+ satisfied. */
+bool processobject::processconstraint(Constraint *c) {
+ State *st=new State(c,globalmodel->gethashtable());
+ bool clean=true;
+ if (st->initializestate(globalmodel)) {
+ while(true) {
+ if (c->getstatement()!=NULL) {
+ modelcheck++;
+ if (processstatement(c->getstatement(),st->env)!=PTRUE) {
+ modeltrigger++;
+#ifdef TOOL
+ printf("Constraint violation\n");
+ printf(" Violated constraint: "); c->print();
+ printf(" State for which it was violated: "); st->print(globalmodel);
+ printf(" Current value(s):");
+ c->getstatement()->print_sets(st->env, globalmodel);
+ printf("\n\n");
+ return false;
+#endif
+
+#ifdef REPAIR
+ printf("Repairing...\n");
+ if (c->getcrash()) {
+ printf("Fatal program error violating special constraint.\n");
+ exit(-1);
+ }
+ repair->repairconstraint(c,this,st->env);
+ clean=false;
+#endif
+ }
+ }
+
+ if (!st->increment(globalmodel))
+ break; /* done */
+ }
+ }
+ delete(st);
+ return clean;
+}
+
+
+
+/* breaks the given constraint by invalidating each of its satisfied sentences */
+void processobject::breakconstraint(Constraint *c)
+{
+#ifdef DEBUGMESSAGES
+ printf("Constraint to be broken: ");
+ c->print();
+ printf("\n");
+ fflush(NULL);
+#endif
+
+ // first, get get the constraint in normal form
+ NormalForm *nf = globalmodel->getnormalform(c);
+
+ // for each CoerceSentence in nf, find if it's satisfied. If so, break it.
+ for (int i=0; i<nf->getnumsentences(); i++)
+ {
+#ifdef DEBUGMESSAGES
+ printf("In processobject::breakconstraint, i=%d \n", i);
+ fflush(NULL);
+#endif
+
+ CoerceSentence *s = nf->getsentence(i);
+
+ // find if s is satisfied
+ bool satisfied = true;
+ State *st = new State(c, globalmodel->gethashtable());
+ if (st->initializestate(globalmodel))
+ while(true)
+ {
+ if (!s->issatisfied(this, st->env))
+ satisfied=false;
+
+ if (!st->increment(globalmodel))
+ break;
+ }
+ delete(st);
+
+
+ // if s is satisfied, then break it
+
+ if (satisfied)
+ {
+ // first, select an arbitrary binding, for ex. the first one
+ st = new State(c, globalmodel->gethashtable());
+
+ if (st->initializestate(globalmodel))
+ {
+#ifdef DEBUGMESSAGES
+ printf("numpredicates = %d\n", s->getnumpredicates());
+#endif
+
+ for (int j=0; j<s->getnumpredicates(); j++)
+ {
+ CoercePredicate *cp = s->getpredicate(j);
+ // break this predicate with probability prob_breakpredicate
+ if (random()<model::prob_breakpredicate*RAND_MAX)
+ {
+#ifdef DEBUGMESSAGES
+ printf("po::breakconstraint: We break predicate %d\n",j);
+ fflush(NULL);
+#endif
+
+ Action *action = repair->findbreakaction(cp);
+ action->breakpredicate(st->env, cp);
+
+#ifdef DEBUGMESSAGES
+ printf("After action->breakpredicate was called\n");
+ fflush(NULL);
+#endif
+ }
+ }
+ }
+
+ delete(st);
+ }
+ }
+}
+
+
+
+/* satisfies the given satisfied contraint in another way */
+void processobject::modifyconstraint(Constraint *c)
+{
+#ifdef DEBUGMESSAGES
+ printf("Constraint to be modified: ");
+ c->print();
+ printf("\n");
+ fflush(NULL);
+#endif
+
+ // first, get the constraint in normal form
+ NormalForm *nf = globalmodel->getnormalform(c);
+
+ /* for each CoerceSentence in nf, find if it's satisfied.
+ If it's satisfied, we break it with probability prob_breaksatisfiedsentence;
+ If it's not satisfied, we repair it with probability prob_repairbrokensentence
+ */
+
+ bool still_valid = false;
+
+ for (int i=0; i<nf->getnumsentences(); i++)
+ {
+#ifdef DEBUGMESSAGES
+ printf("In processobject::modifyconstraint, i=%d \n", i);
+ fflush(NULL);
+#endif
+
+ CoerceSentence *s = nf->getsentence(i);
+
+ // find if s is satisfied
+ bool satisfied = true;
+ State *st = new State(c, globalmodel->gethashtable());
+ if (st->initializestate(globalmodel))
+ while(true)
+ {
+ if (!s->issatisfied(this, st->env))
+ satisfied=false;
+
+ if (!st->increment(globalmodel))
+ break;
+ }
+ delete(st);
+
+ // if s is satisfied, then break it
+ if (satisfied)
+ if (random()<model::prob_breaksatisfiedsentence*RAND_MAX) // then break it
+ {
+ // first, select an arbitrary binding, for ex. the first one
+ st = new State(c, globalmodel->gethashtable());
+
+ if (st->initializestate(globalmodel))
+ {
+ for (int j=0; j<s->getnumpredicates(); j++)
+ {
+ CoercePredicate *cp = s->getpredicate(j);
+ // break this predicate with probability prob_breakpredicate
+ if (random()<model::prob_breakpredicate*RAND_MAX)
+ {
+#ifdef DEBUGMESSAGES
+ printf("po::modifyconstraint: We break predicate %d\n",j);
+ fflush(NULL);
+#endif
+
+ Action *action = repair->findbreakaction(cp);
+ action->breakpredicate(st->env, cp);
+
+#ifdef DEBUGMESSAGES
+ printf("After action->modifypredicate was called\n");
+ fflush(NULL);
+#endif
+ }
+ }
+ }
+ delete(st);
+ }
+ else still_valid = true;
+ else // if not satisfied, then repair it with prob_repairbrokensentence
+ if (random()<model::prob_repairbrokensentence)
+ {
+ // first, select an arbitrary binding, for ex. the first one
+ st = new State(c, globalmodel->gethashtable());
+
+ if (st->initializestate(globalmodel))
+ {
+ for (int j=0; j<s->getnumpredicates(); j++)
+ {
+ CoercePredicate *cp = s->getpredicate(j);
+ Action *action = repair->findrepairaction(cp);
+ action->repairpredicate(st->env, cp);
+
+#ifdef DEBUGMESSAGES
+ printf("After action->repairpredicate was called\n");
+ fflush(NULL);
+#endif
+ }
+ }
+
+ delete(st);
+ still_valid = true;
+ }
+ }
+
+ if (!still_valid) // if all sentences are broken, repair the first one
+ {
+ CoerceSentence *saux = nf->getsentence(0);
+ // first, select an arbitrary binding, for ex. the first one
+ State *st = new State(c, globalmodel->gethashtable());
+
+ if (st->initializestate(globalmodel))
+ {
+ for (int j=0; j<saux->getnumpredicates(); j++)
+ {
+ CoercePredicate *cp = saux->getpredicate(j);
+ Action *action = repair->findrepairaction(cp);
+ action->repairpredicate(st->env, cp);
+
+#ifdef DEBUGMESSAGES
+ printf("After action->repairpredicate was called\n");
+ fflush(NULL);
+#endif
+ }
+ }
+
+ delete(st);
+ }
+
+}
+
+
+processobject::~processobject() {
+}
+
+
+// computes ve = V.R
+Element * evaluatevalueexpr(Valueexpr *ve, Hashtable *env, model *m) {
+ Element *e=NULL;
+ if (ve->gettype()==0) {
+ e=(Element *) env->get(ve->getlabel()->label());
+ } else
+ e=evaluatevalueexpr(ve->getvalueexpr(),env,m);
+ if (e==NULL)
+ return e;
+ if (ve->getinverted())
+ return (Element *)m->getdomainrelation()->getrelation(ve->getrelation()->getname())->getrelation()->invgetobj(e);
+ else
+ return (Element *)m->getdomainrelation()->getrelation(ve->getrelation()->getname())->getrelation()->getobj(e);
+}
+
+
+
+// evaluates E = V | number | string | E-E | E+E | E*E | E/E | E.R |size(SE)
+Element * evaluateexpr(Elementexpr *ee, Hashtable *env, model *m) {
+ switch(ee->gettype()) {
+ case ELEMENTEXPR_LABEL: {
+ return new Element((Element *)env->get(ee->getlabel()->label()));
+ }
+ case ELEMENTEXPR_SUB: {
+ Elementexpr *left=ee->getleft();
+ Elementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(left,env,m);
+ if(leftval==NULL) return NULL;
+ Element *rightval=evaluateexpr(right,env,m);
+ if(rightval==NULL) {delete(leftval);return NULL;}
+ Element *diff=new Element(leftval->intvalue()-rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return diff;
+ }
+ case ELEMENTEXPR_ADD: {
+ Elementexpr *left=ee->getleft();
+ Elementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(left,env,m);
+ if(leftval==NULL) return NULL;
+ Element *rightval=evaluateexpr(right,env,m);
+ if(rightval==NULL) {delete(leftval);return NULL;}
+ Element *sum=new Element(leftval->intvalue()+rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return sum;
+ }
+ case ELEMENTEXPR_RELATION: {
+ Elementexpr *left=ee->getleft();
+ Relation *rel=ee->getrelation();
+ Element *leftval=evaluateexpr(left,env,m);
+ if(leftval==NULL) return NULL;
+ Element *retval=(Element *)m->getdomainrelation()->getrelation(rel->getname())->getrelation()->getobj(leftval);
+ delete(leftval);
+ return new Element(retval);
+ }
+ case ELEMENTEXPR_MULT: {
+ Elementexpr *left=ee->getleft();
+ Elementexpr *right=ee->getright();
+ Element *leftval=evaluateexpr(left,env,m);
+ if(leftval==NULL) return NULL;
+ Element *rightval=evaluateexpr(right,env,m);
+ if(rightval==NULL) {delete(leftval);return NULL;}
+ Element *diff=new Element(leftval->intvalue()*rightval->intvalue());
+ delete(leftval);delete(rightval);
+ return diff;
+ }
+ case ELEMENTEXPR_LIT: {
+ Literal *l=ee->getliteral();
+ switch(l->gettype()) {
+ case LITERAL_NUMBER:
+ return new Element(l->number());
+ case LITERAL_TOKEN:
+ return new Element(copystr(l->token()));
+ default:
+ printf("ERROR with lit type\n");
+ exit(-1);
+ }
+ }
+ /* case ELEMENTEXPR_PARAM: {
+ Element *ele=evaluateexpr(ee->getleft(),env,m);
+ Element *eec=ele->paramvalue(ee->getliteral()->number());
+ Element *retval=new Element(eec);
+ delete(ele);
+ return eec;
+ }*/ //NO OBJECT PARAMETERS
+ case ELEMENTEXPR_SETSIZE:
+ Setexpr * setexpr=ee->getsetexpr();
+ switch(setexpr->gettype()) {
+ case SETEXPR_LABEL:
+ return new Element(m->getdomainrelation()->getset(setexpr->getsetlabel()->getname())->getset()->size());
+ case SETEXPR_REL: {
+ Element *key=(Element *)env->get(setexpr->getlabel()->label());
+ WorkSet *ws=m->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->getset(key);
+ if (ws==NULL)
+ return new Element(0);
+ else
+ return new Element(ws->size());
+ }
+ case SETEXPR_INVREL: {
+ Element *key=(Element *)env->get(setexpr->getlabel()->label());
+ WorkSet *ws=m->getdomainrelation()->getrelation(setexpr->getrelation()->getname())->getrelation()->invgetset(key);
+ if (ws==NULL)
+ return new Element(0);
+ else
+ return new Element(ws->size());
+ }
+ }
+ break;
+ }
+}
--- /dev/null
+// evaluates constraints in the ICL
+
+
+#ifndef PROCESSOBJECT_H
+#define PROCESSOBJECT_H
+#include "classlist.h"
+
+#define PTRUE 1
+#define PFALSE 0
+#define PFAIL -1
+
+class processobject {
+ public:
+ processobject(model *m);
+ int processpredicate(Predicate *p, Hashtable *env);
+ bool issatisfied(Constraint *c); // returns true iff c is satisfied
+ bool processconstraint(Constraint *c); // evaluates c and if it's not satisfied, calls the repair alg.
+ void breakconstraint(Constraint *c); // breaks the given constraint by invalidating each of its satisfied sentences
+ void modifyconstraint(Constraint *c); // modifies the given constraint
+ void setclean();
+ ~processobject();
+ void printstats();
+
+ private:
+ Repair * repair;
+ int processstatement(Statement *s, Hashtable *env);
+ model * globalmodel;
+};
+
+Element * evaluateexpr(Elementexpr *ee, Hashtable *env, model *m);
+Element * evaluatevalueexpr(Valueexpr *ve, Hashtable *env, model *m);
+#endif
--- /dev/null
+static char rcsid[]="$Id: redblack.c,v 1.1 2004/05/06 21:16:22 bdemsky Exp $";
+
+/*
+ Redblack balanced tree algorithm
+ Copyright (C) Damian Ivereigh 2000
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version. See the file COPYING for details.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Implement the red/black tree structure. It is designed to emulate
+** the standard tsearch() stuff. i.e. the calling conventions are
+** exactly the same
+*/
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "redblack.h"
+//#include "dmalloc.h"
+
+#define assert(expr)
+#define RB_TRUE 1
+#define RB_FALSE 0
+
+/* Uncomment this if you would rather use a raw sbrk to get memory
+** (however the memory is never released again (only re-used). Can't
+** see any point in using this these days.
+*/
+/* #define USE_SBRK */
+
+enum nodecolour { BLACK, RED };
+
+struct rbnode {
+ struct rbnode *left; /* Left down */
+ struct rbnode *right; /* Right down */
+ struct rbnode *up; /* Up */
+ enum nodecolour colour; /* Node colour */
+ const void *key; /* Pointer to user's key (and data) */
+ const void *high;
+ const void *max;
+ void *object;
+};
+
+/* Dummy (sentinel) node, so that we can make X->left->up = X
+** We then use this instead of NULL to mean the top or bottom
+** end of the rb tree. It is a black node.
+*/
+struct rbnode rb_null={&rb_null, &rb_null, &rb_null, BLACK, NULL,NULL,NULL,NULL};
+#define RBNULL (&rb_null)
+
+#if defined(USE_SBRK)
+
+static struct rbnode *rb_alloc();
+static void rb_free(struct rbnode *);
+
+#else
+
+#define rb_alloc() ((struct rbnode *) malloc(sizeof(struct rbnode)))
+#define rb_free(x) (free(x))
+
+#endif
+
+static struct rbnode *rb_traverse(const void *, struct rbtree *);
+static struct rbnode *rb_lookup(const void *low,const void *high, struct rbtree *);
+static void rb_destroy(struct rbnode *,void (*)(void *));
+static void rb_left_rotate(struct rbnode **, struct rbnode *);
+static void rb_right_rotate(struct rbnode **, struct rbnode *);
+static void rb_delete(struct rbnode **, struct rbnode *);
+static void rb_delete_fix(struct rbnode **, struct rbnode *);
+static struct rbnode *rb_successor(const struct rbnode *);
+static struct rbnode *rb_preccessor(const struct rbnode *);
+static void rb_walk(const struct rbnode *, void (*)(const void *, const VISIT, const int, void *), void *, int);
+static RBLIST *rb_openlist(const struct rbnode *);
+static const void *rb_readlist(RBLIST *);
+static void rb_closelist(RBLIST *);
+
+/*
+** OK here we go, the balanced tree stuff. The algorithm is the
+** fairly standard red/black taken from "Introduction to Algorithms"
+** by Cormen, Leiserson & Rivest. Maybe one of these days I will
+** fully understand all this stuff.
+**
+** Basically a red/black balanced tree has the following properties:-
+** 1) Every node is either red or black (colour is RED or BLACK)
+** 2) A leaf (RBNULL pointer) is considered black
+** 3) If a node is red then its children are black
+** 4) Every path from a node to a leaf contains the same no
+** of black nodes
+**
+** 3) & 4) above guarantee that the longest path (alternating
+** red and black nodes) is only twice as long as the shortest
+** path (all black nodes). Thus the tree remains fairly balanced.
+*/
+
+/*
+ * Initialise a tree. Identifies the comparison routine and any config
+ * data that must be sent to it when called.
+ * Returns a pointer to the top of the tree.
+ */
+struct rbtree * rbinit() {
+ struct rbtree *retval;
+ char c;
+
+ c=rcsid[0]; /* This does nothing but shutup the -Wall */
+
+ if ((retval=(struct rbtree *) malloc(sizeof(struct rbtree)))==NULL)
+ return(NULL);
+
+ retval->rb_root=RBNULL;
+
+ return(retval);
+}
+
+void rbdestroy(struct rbtree *rbinfo, void (*free_function)(void *)) {
+ if (rbinfo==NULL)
+ return;
+
+ if (rbinfo->rb_root!=RBNULL)
+ rb_destroy(rbinfo->rb_root,free_function);
+
+ free(rbinfo);
+}
+
+const void * rbdelete(const void *key, struct rbtree *rbinfo) {
+ struct rbnode *x;
+ const void *y;
+
+ if (rbinfo==NULL)
+ return(NULL);
+
+ x=rb_traverse(key, rbinfo);
+
+ if (x==RBNULL) {
+ return(NULL);
+ } else {
+ y=x->key;
+ rb_delete(&rbinfo->rb_root, x);
+
+ return(y);
+ }
+}
+
+void rbwalk(const struct rbtree *rbinfo, void (*action)(const void *, const VISIT, const int, void *), void *arg) {
+ if (rbinfo==NULL)
+ return;
+
+ rb_walk(rbinfo->rb_root, action, arg, 0);
+}
+
+RBLIST * rbopenlist(const struct rbtree *rbinfo) {
+ if (rbinfo==NULL)
+ return(NULL);
+
+ return(rb_openlist(rbinfo->rb_root));
+}
+
+const void * rbreadlist(RBLIST *rblistp) {
+ if (rblistp==NULL)
+ return(NULL);
+
+ return(rb_readlist(rblistp));
+}
+
+void rbcloselist(RBLIST *rblistp) {
+ if (rblistp==NULL)
+ return;
+
+ rb_closelist(rblistp);
+}
+
+/**
+ * finds an overlapping region with low->high and returns the object associated with
+ * that region
+ */
+void * rblookup(const void *low,const void *high, struct rbtree *rbinfo) {
+ struct rbnode *x;
+
+ /* If we have a NULL root (empty tree) then just return NULL */
+ if (rbinfo==NULL || rbinfo->rb_root==NULL)
+ return(NULL);
+
+ x=rb_lookup(low, high, rbinfo);
+
+ return((x==RBNULL) ? NULL : x->object);
+}
+
+/**
+ * finds an overlapping region with low->high and returns the pair <low, high>
+ */
+struct pair rbfind(const void *low,const void *high, struct rbtree *rbinfo) {
+ struct rbnode *x;
+ struct pair p;
+ /* If we have a NULL root (empty tree) then just return NULL */
+
+ p.low=NULL;
+ p.high=NULL;
+ if (rbinfo==NULL || rbinfo->rb_root==NULL)
+ return p;
+
+ x=rb_lookup(low, high, rbinfo);
+ if (x!=NULL) {
+ p.low=x->key;
+ p.high=x->high;
+ }
+ return p;
+}
+
+
+/* --------------------------------------------------------------------- */
+
+/* Search for and if not found and insert is true, will add a new
+** node in. Returns a pointer to the new node, or the node found
+*/
+int rbinsert(const void *key, const void * high, void *object,struct rbtree *rbinfo) {
+ struct rbnode *x,*y,*z, *tmp;
+ const void *max;
+ int found=0;
+
+ y=RBNULL; /* points to the parent of x */
+ x=rbinfo->rb_root;
+
+ /* walk x down the tree */
+ while(x!=RBNULL && found==0) {
+ y=x;
+ /* printf("key=%s, x->key=%s\n", key, x->key); */
+
+ if (key<x->key)
+ x=x->left;
+ else if (key>x->key)
+ x=x->right;
+ else
+ found=1;
+ }
+
+ if (found)
+ return RB_FALSE;
+
+ if ((z=rb_alloc())==NULL) {
+ /* Whoops, no memory */
+ return RB_FALSE;
+ }
+
+ z->object=object;
+ z->high=high;
+ z->key=key;
+ z->max=high;
+ z->up=y;
+ tmp=y;
+ max=high;
+ while(tmp!=RBNULL) {
+ if (max>tmp->max)
+ tmp->max=max;
+ else
+ max=tmp->max;
+ tmp=tmp->up;
+ }
+
+ if (y==RBNULL) {
+ rbinfo->rb_root=z;
+ } else {
+ if (z->key<y->key)
+ y->left=z;
+ else
+ y->right=z;
+ }
+
+ z->left=RBNULL;
+ z->right=RBNULL;
+
+ /* colour this new node red */
+ z->colour=RED;
+
+ /* Having added a red node, we must now walk back up the tree balancing
+ ** it, by a series of rotations and changing of colours
+ */
+ x=z;
+
+ /* While we are not at the top and our parent node is red
+ ** N.B. Since the root node is garanteed black, then we
+ ** are also going to stop if we are the child of the root
+ */
+
+ while(x != rbinfo->rb_root && (x->up->colour == RED)) {
+ /* if our parent is on the left side of our grandparent */
+ if (x->up == x->up->up->left) {
+ /* get the right side of our grandparent (uncle?) */
+ y=x->up->up->right;
+ if (y->colour == RED) {
+ /* make our parent black */
+ x->up->colour = BLACK;
+ /* make our uncle black */
+ y->colour = BLACK;
+ /* make our grandparent red */
+ x->up->up->colour = RED;
+
+ /* now consider our grandparent */
+ x=x->up->up;
+ } else {
+ /* if we are on the right side of our parent */
+ if (x == x->up->right) {
+ /* Move up to our parent */
+ x=x->up;
+ rb_left_rotate(&rbinfo->rb_root, x);
+ }
+
+ /* make our parent black */
+ x->up->colour = BLACK;
+ /* make our grandparent red */
+ x->up->up->colour = RED;
+ /* right rotate our grandparent */
+ rb_right_rotate(&rbinfo->rb_root, x->up->up);
+ }
+ } else {
+ /* everything here is the same as above, but
+ ** exchanging left for right
+ */
+
+ y=x->up->up->left;
+ if (y->colour == RED) {
+ x->up->colour = BLACK;
+ y->colour = BLACK;
+ x->up->up->colour = RED;
+
+ x=x->up->up;
+ } else {
+ if (x == x->up->left) {
+ x=x->up;
+ rb_right_rotate(&rbinfo->rb_root, x);
+ }
+
+ x->up->colour = BLACK;
+ x->up->up->colour = RED;
+ rb_left_rotate(&rbinfo->rb_root, x->up->up);
+ }
+ }
+ }
+
+ /* Set the root node black */
+ (rbinfo->rb_root)->colour = BLACK;
+
+ return RB_TRUE;
+}
+
+/* Search for and if not found and insert is true, will add a new
+** node in. Returns a pointer to the new node, or the node found
+*/
+static struct rbnode * rb_traverse(const void *key, struct rbtree *rbinfo) {
+ struct rbnode *x,*y,*z;
+ int found=0;
+
+ y=RBNULL; /* points to the parent of x */
+ x=rbinfo->rb_root;
+
+ /* walk x down the tree */
+ while(x!=RBNULL && found==0) {
+ y=x;
+ if (key<x->key)
+ x=x->left;
+ else if (key>x->key)
+ x=x->right;
+ else
+ found=1;
+ }
+
+ if (found)
+ return(x);
+ return NULL;
+}
+
+/* Search for a key according (see redblack.h)
+*/
+static struct rbnode * rb_lookup(const void *low, const void *high, struct rbtree *rbinfo) {
+ struct rbnode *x;
+
+ x=rbinfo->rb_root;
+
+ /* walk x down the tree */
+ while(x!=RBNULL) {
+ if (low<x->high &&
+ x->key<high)
+ return x;
+ if (x->left!=RBNULL && x->left->max>low)
+ x=x->left;
+ else
+ x=x->right;
+ }
+
+ return(RBNULL);
+}
+
+/* Search for a key according (see redblack.h)
+*/
+int rbsearch(const void *low, const void *high, struct rbtree *rbinfo) {
+ struct rbnode *x;
+ if (rbinfo==NULL)
+ return RB_FALSE;
+
+ x=rbinfo->rb_root;
+
+ /* walk x down the tree */
+ while(x!=RBNULL) {
+ if (low<x->high &&
+ x->key<high)
+ return RB_TRUE;
+ if (x->left!=RBNULL && x->left->max>low)
+ x=x->left;
+ else
+ x=x->right;
+ }
+
+ return RB_FALSE;
+}
+
+/*
+ * Destroy all the elements blow us in the tree
+ * only useful as part of a complete tree destroy.
+ */
+static void rb_destroy(struct rbnode *x,void (*free_function)(void *)) {
+ if (x!=RBNULL) {
+ if (x->left!=RBNULL)
+ rb_destroy(x->left,free_function);
+ if (x->right!=RBNULL)
+ rb_destroy(x->right,free_function);
+ if (free_function!=NULL)
+ free_function(x->object);
+ rb_free(x);
+ }
+}
+
+/*
+** Rotate our tree thus:-
+**
+** X rb_left_rotate(X)---> Y
+** / \ / \
+** A Y <---rb_right_rotate(Y) X C
+** / \ / \
+** B C A B
+**
+** N.B. This does not change the ordering.
+**
+** We assume that neither X or Y is NULL
+*/
+
+static void rb_left_rotate(struct rbnode **rootp, struct rbnode *x) {
+ struct rbnode *y;
+ const void *max;
+ assert(x!=RBNULL);
+ assert(x->right!=RBNULL);
+
+ y=x->right; /* set Y */
+
+ /* Turn Y's left subtree into X's right subtree (move B)*/
+ x->right = y->left;
+
+ /* If B is not null, set it's parent to be X */
+ if (y->left != RBNULL)
+ y->left->up = x;
+
+ /* Set Y's parent to be what X's parent was */
+ y->up = x->up;
+
+ /* if X was the root */
+ if (x->up == RBNULL) {
+ *rootp=y;
+ } else {
+ /* Set X's parent's left or right pointer to be Y */
+ if (x == x->up->left) {
+ x->up->left=y;
+ } else {
+ x->up->right=y;
+ }
+ }
+
+ /* Put X on Y's left */
+ y->left=x;
+
+ /* Set X's parent to be Y */
+ x->up = y;
+
+ y->max=x->max; /* compute Y's max */
+ max=NULL;
+
+ if (x->left!=RBNULL)
+ max=x->left->max;
+
+ if (x->right!=RBNULL&&
+ x->right->max>max)
+ max=x->right->max;
+ if (x->high>max)
+ max=x->high;
+ x->max=max;
+}
+
+static void rb_right_rotate(struct rbnode **rootp, struct rbnode *y) {
+ struct rbnode *x;
+ const void *max;
+
+ assert(y!=RBNULL);
+ assert(y->left!=RBNULL);
+
+ x=y->left; /* set X */
+
+ /* Turn X's right subtree into Y's left subtree (move B) */
+ y->left = x->right;
+
+ /* If B is not null, set it's parent to be Y */
+ if (x->right != RBNULL)
+ x->right->up = y;
+
+ /* Set X's parent to be what Y's parent was */
+ x->up = y->up;
+
+ /* if Y was the root */
+ if (y->up == RBNULL) {
+ *rootp=x;
+ } else {
+ /* Set Y's parent's left or right pointer to be X */
+ if (y == y->up->left) {
+ y->up->left=x;
+ } else {
+ y->up->right=x;
+ }
+ }
+
+ /* Put Y on X's right */
+ x->right=y;
+
+ /* Set Y's parent to be X */
+ y->up = x;
+
+ x->max=y->max; /* compute Y's max */
+ max=NULL;
+
+ if (y->left!=RBNULL)
+ max=y->left->max;
+
+ if (y->right!=RBNULL&&
+ y->right->max>max)
+ max=y->right->max;
+ if (y->high>max)
+ max=y->high;
+ y->max=max;
+}
+
+/* Return a pointer to the smallest key greater than x
+*/
+static struct rbnode * rb_successor(const struct rbnode *x) {
+ struct rbnode *y;
+
+ if (x->right!=RBNULL) {
+ /* If right is not NULL then go right one and
+ ** then keep going left until we find a node with
+ ** no left pointer.
+ */
+ for (y=x->right; y->left!=RBNULL; y=y->left);
+ } else {
+ /* Go up the tree until we get to a node that is on the
+ ** left of its parent (or the root) and then return the
+ ** parent.
+ */
+ y=x->up;
+ while(y!=RBNULL && x==y->right) {
+ x=y;
+ y=y->up;
+ }
+ }
+ return(y);
+}
+
+/* Return a pointer to the largest key smaller than x
+*/
+static struct rbnode * rb_preccessor(const struct rbnode *x) {
+ struct rbnode *y;
+
+ if (x->left!=RBNULL) {
+ /* If left is not NULL then go left one and
+ ** then keep going right until we find a node with
+ ** no right pointer.
+ */
+ for (y=x->left; y->right!=RBNULL; y=y->right);
+ } else {
+ /* Go up the tree until we get to a node that is on the
+ ** right of its parent (or the root) and then return the
+ ** parent.
+ */
+ y=x->up;
+ while(y!=RBNULL && x==y->left) {
+ x=y;
+ y=y->up;
+ }
+ }
+ return(y);
+}
+
+/* Delete the node z, and free up the space
+*/
+static void rb_delete(struct rbnode **rootp, struct rbnode *z) {
+ struct rbnode *x, *y, *tmp;
+ const void *max;
+
+ if (z->left == RBNULL || z->right == RBNULL)
+ y=z;
+ else
+ y=rb_successor(z);
+
+ if (y->left != RBNULL)
+ x=y->left;
+ else
+ x=y->right;
+
+ x->up = y->up;
+
+ if (y->up == RBNULL) {
+ *rootp=x;
+ } else {
+ if (y==y->up->left)
+ y->up->left = x;
+ else
+ y->up->right = x;
+ }
+
+ if (y!=z) {
+ z->key = y->key;
+ z->high=y->high;
+ z->object=y->object;
+ }
+ tmp=y->up;
+ while(tmp!=RBNULL) {
+ max=NULL;
+ if (tmp->left!=RBNULL)
+ max=tmp->left->max;
+ if (tmp->right!=RBNULL&&
+ tmp->right->max>max)
+ max=tmp->right->max;
+ if (tmp->high>max)
+ max=tmp->high;
+ tmp->max=max;
+ tmp=tmp->up;
+ }
+ if (y->colour == BLACK)
+ rb_delete_fix(rootp, x);
+
+ rb_free(y);
+}
+
+/* Restore the reb-black properties after a delete */
+static void rb_delete_fix(struct rbnode **rootp, struct rbnode *x) {
+ struct rbnode *w;
+
+ while (x!=*rootp && x->colour==BLACK) {
+ if (x==x->up->left) {
+ w=x->up->right;
+ if (w->colour==RED) {
+ w->colour=BLACK;
+ x->up->colour=RED;
+ rb_left_rotate(rootp, x->up);
+ w=x->up->right;
+ }
+ if (w->left->colour==BLACK && w->right->colour==BLACK) {
+ w->colour=RED;
+ x=x->up;
+ } else {
+ if (w->right->colour == BLACK) {
+ w->left->colour=BLACK;
+ w->colour=RED;
+ rb_right_rotate(rootp, w);
+ w=x->up->right;
+ }
+ w->colour=x->up->colour;
+ x->up->colour = BLACK;
+ w->right->colour = BLACK;
+ rb_left_rotate(rootp, x->up);
+ x=*rootp;
+ }
+ } else {
+ w=x->up->left;
+ if (w->colour==RED) {
+ w->colour=BLACK;
+ x->up->colour=RED;
+ rb_right_rotate(rootp, x->up);
+ w=x->up->left;
+ }
+ if (w->right->colour==BLACK && w->left->colour==BLACK) {
+ w->colour=RED;
+ x=x->up;
+ } else {
+ if (w->left->colour == BLACK) {
+ w->right->colour=BLACK;
+ w->colour=RED;
+ rb_left_rotate(rootp, w);
+ w=x->up->left;
+ }
+ w->colour=x->up->colour;
+ x->up->colour = BLACK;
+ w->left->colour = BLACK;
+ rb_right_rotate(rootp, x->up);
+ x=*rootp;
+ }
+ }
+ }
+
+ x->colour=BLACK;
+}
+
+static void
+rb_walk(const struct rbnode *x, void (*action)(const void *, const VISIT, const int, void *), void *arg, int level) {
+ if (x==RBNULL)
+ return;
+
+ if (x->left==RBNULL && x->right==RBNULL) {
+ /* leaf */
+ (*action)(x->key, leaf, level, arg);
+ } else {
+ (*action)(x->key, preorder, level, arg);
+
+ rb_walk(x->left, action, arg, level+1);
+
+ (*action)(x->key, postorder, level, arg);
+
+ rb_walk(x->right, action, arg, level+1);
+
+ (*action)(x->key, endorder, level, arg);
+ }
+}
+
+static RBLIST * rb_openlist(const struct rbnode *rootp) {
+ RBLIST *rblistp;
+
+ rblistp=(RBLIST *) malloc(sizeof(RBLIST));
+ if (!rblistp)
+ return(NULL);
+
+ rblistp->rootp=rootp;
+ rblistp->nextp=rootp;
+
+ if (rootp!=RBNULL) {
+ while(rblistp->nextp->left!=RBNULL) {
+ rblistp->nextp=rblistp->nextp->left;
+ }
+ }
+
+ return(rblistp);
+}
+
+static const void * rb_readlist(RBLIST *rblistp) {
+ const void *key=NULL;
+
+ if (rblistp!=NULL && rblistp->nextp!=RBNULL) {
+ key=rblistp->nextp->key;
+ rblistp->nextp=rb_successor(rblistp->nextp);
+ }
+
+ return(key);
+}
+
+static void rb_closelist(RBLIST *rblistp) {
+ if (rblistp)
+ free(rblistp);
+}
+
+#if defined(USE_SBRK)
+/* Allocate space for our nodes, allowing us to get space from
+** sbrk in larger chucks.
+*/
+static struct rbnode *rbfreep=NULL;
+
+#define RBNODEALLOC_CHUNK_SIZE 1000
+static struct rbnode * rb_alloc() {
+ struct rbnode *x;
+ int i;
+
+ if (rbfreep==NULL) {
+ /* must grab some more space */
+ rbfreep=(struct rbnode *) sbrk(sizeof(struct rbnode) * RBNODEALLOC_CHUNK_SIZE);
+
+ if (rbfreep==(struct rbnode *) -1) {
+ return(NULL);
+ }
+
+ /* tie them together in a linked list (use the up pointer) */
+ for (i=0, x=rbfreep; i<RBNODEALLOC_CHUNK_SIZE-1; i++, x++) {
+ x->up = (x+1);
+ }
+ x->up=NULL;
+ }
+
+ x=rbfreep;
+ rbfreep = rbfreep->up;
+ return(x);
+}
+
+/* free (dealloc) an rbnode structure - add it onto the front of the list
+** N.B. rbnode need not have been allocated through rb_alloc()
+*/
+static void rb_free(struct rbnode *x) {
+ x->up=rbfreep;
+ rbfreep=x;
+}
+
+#endif
+
+#if 0
+int rb_check(struct rbnode *rootp) {
+ if (rootp==NULL || rootp==RBNULL)
+ return(0);
+
+ if (rootp->up!=RBNULL) {
+ fprintf(stderr, "Root up pointer not RBNULL");
+ dumptree(rootp, 0);
+ return(1);
+ }
+
+ if (rb_check1(rootp)) {
+ dumptree(rootp, 0);
+ return(1);
+ }
+
+ if (count_black(rootp)==-1)
+ {
+ dumptree(rootp, 0);
+ return(-1);
+ }
+
+ return(0);
+}
+
+int
+rb_check1(struct rbnode *x)
+{
+ if (x->left==NULL || x->right==NULL)
+ {
+ fprintf(stderr, "Left or right is NULL");
+ return(1);
+ }
+
+ if (x->colour==RED)
+ {
+ if (x->left->colour!=BLACK && x->right->colour!=BLACK)
+ {
+ fprintf(stderr, "Children of red node not both black, x=%ld", x);
+ return(1);
+ }
+ }
+
+ if (x->left != RBNULL)
+ {
+ if (x->left->up != x)
+ {
+ fprintf(stderr, "x->left->up != x, x=%ld", x);
+ return(1);
+ }
+
+ if (rb_check1(x->left))
+ return(1);
+ }
+
+ if (x->right != RBNULL)
+ {
+ if (x->right->up != x)
+ {
+ fprintf(stderr, "x->right->up != x, x=%ld", x);
+ return(1);
+ }
+
+ if (rb_check1(x->right))
+ return(1);
+ }
+ return(0);
+}
+
+count_black(struct rbnode *x)
+{
+ int nleft, nright;
+
+ if (x==RBNULL)
+ return(1);
+
+ nleft=count_black(x->left);
+ nright=count_black(x->right);
+
+ if (nleft==-1 || nright==-1)
+ return(-1);
+
+ if (nleft != nright)
+ {
+ fprintf(stderr, "Black count not equal on left & right, x=%ld", x);
+ return(-1);
+ }
+
+ if (x->colour == BLACK)
+ {
+ nleft++;
+ }
+
+ return(nleft);
+}
+
+dumptree(struct rbnode *x, int n)
+{
+ char *prkey();
+
+ if (x!=NULL && x!=RBNULL)
+ {
+ n++;
+ fprintf(stderr, "Tree: %*s %ld: left=%ld, right=%ld, colour=%s, key=%s",
+ n,
+ "",
+ x,
+ x->left,
+ x->right,
+ (x->colour==BLACK) ? "BLACK" : "RED",
+ prkey(x->key));
+
+ dumptree(x->left, n);
+ dumptree(x->right, n);
+ }
+}
+#endif
+
+/*
+ * $Log: redblack.c,v $
+ * Revision 1.1 2004/05/06 21:16:22 bdemsky
+ * Moved the interpreter
+ *
+ * Revision 1.6 2003/08/06 14:34:10 droy
+ * test
+ *
+ * Revision 1.5 2003/06/18 18:39:05 bdemsky
+ *
+ *
+ * Changed header files/etc to allow dmalloc to easily be used.
+ * Changed some delete -> delete[] for correctness.
+ * Committed out parserange call. Cristian has some memory management bugs...
+ *
+ * Revision 1.4 2003/06/18 06:08:18 bdemsky
+ *
+ *
+ * Adding support for:
+ * 1) freeing the memory we use (imagine that)...will make dan's life easier &
+ * allow us to run cooler benchmarks. (not completed yet)
+ * 2) generating dot graphs of dependencies...not completed yet - the graphs aren't
+ * appropriately labeled.
+ *
+ * Revision 1.3 2003/06/18 06:06:18 bdemsky
+ *
+ *
+ * Added option to pass in function to free items in the redblack interval tree.
+ *
+ * Revision 1.5 2002/01/30 07:54:53 damo
+ * Fixed up the libtool versioning stuff (finally)
+ * Fixed bug 500600 (not detecting a NULL return from malloc)
+ * Fixed bug 509485 (no longer needs search.h)
+ * Cleaned up debugging section
+ * Allow multiple inclusions of redblack.h
+ * Thanks to Matthias Andree for reporting (and fixing) these
+ *
+ * Revision 1.4 2000/06/06 14:43:43 damo
+ * Added all the rbwalk & rbopenlist stuff. Fixed up malloc instead of sbrk.
+ * Added two new examples
+ *
+ * Revision 1.3 2000/05/24 06:45:27 damo
+ * Converted everything over to using const
+ * Added a new example1.c file to demonstrate the worst case scenario
+ * Minor fixups of the spec file
+ *
+ * Revision 1.2 2000/05/24 06:17:10 damo
+ * Fixed up the License (now the LGPL)
+ *
+ * Revision 1.1 2000/05/24 04:15:53 damo
+ * Initial import of files. Versions are now all over the place. Oh well
+ *
+ */
+
--- /dev/null
+/*
+ * RCS $Id: redblack.h,v 1.1 2004/05/06 21:16:22 bdemsky Exp $
+ */
+
+/*
+ Redblack balanced tree algorithm
+ Copyright (C) Damian Ivereigh 2000
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version. See the file COPYING for details.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Header file for redblack.c, should be included by any code that
+** uses redblack.c since it defines the functions
+*/
+
+/* Stop multiple includes */
+#ifndef _REDBLACK_H
+
+/* For rbwalk - pinched from search.h */
+typedef enum {
+ preorder,
+ postorder,
+ endorder,
+ leaf
+} VISIT;
+
+struct rblists {
+ const struct rbnode *rootp;
+ const struct rbnode *nextp;
+};
+
+#define RBLIST struct rblists
+
+struct rbtree {
+ /* root of tree */
+ struct rbnode *rb_root;
+};
+
+struct pair {
+ const void *low,*high;
+};
+
+struct rbtree *rbinit();
+int rbinsert(const void *low, const void * high, void *object,struct rbtree *rbinfo);
+struct pair rbfind(const void *low,const void *high, struct rbtree *rbinfo);
+const void *rbdelete(const void *, struct rbtree *);
+void *rblookup(const void *, const void *,struct rbtree *);
+int rbsearch(const void *low, const void *high, struct rbtree *rbinfo);
+void rbdestroy(struct rbtree *,void (*free_function)(void *));
+void rbwalk(const struct rbtree *,
+ void (*)(const void *, const VISIT, const int, void *),
+ void *);
+RBLIST *rbopenlist(const struct rbtree *);
+const void *rbreadlist(RBLIST *);
+void rbcloselist(RBLIST *);
+
+/* Some useful macros */
+#define rbmin(rbinfo) rblookup(RB_LUFIRST, NULL, (rbinfo))
+#define rbmax(rbinfo) rblookup(RB_LULAST, NULL, (rbinfo))
+
+#define _REDBLACK_H
+#endif /* _REDBLACK_H */
+
+/*
+ *
+ * $Log: redblack.h,v $
+ * Revision 1.1 2004/05/06 21:16:22 bdemsky
+ * Moved the interpreter
+ *
+ * Revision 1.4 2003/06/18 06:08:18 bdemsky
+ *
+ *
+ * Adding support for:
+ * 1) freeing the memory we use (imagine that)...will make dan's life easier &
+ * allow us to run cooler benchmarks. (not completed yet)
+ * 2) generating dot graphs of dependencies...not completed yet - the graphs aren't
+ * appropriately labeled.
+ *
+ * Revision 1.2 2003/06/18 06:06:18 bdemsky
+ *
+ *
+ * Added option to pass in function to free items in the redblack interval tree.
+ *
+ * Revision 1.5 2002/01/30 07:54:53 damo
+ * Fixed up the libtool versioning stuff (finally)
+ * Fixed bug 500600 (not detecting a NULL return from malloc)
+ * Fixed bug 509485 (no longer needs search.h)
+ * Cleaned up debugging section
+ * Allow multiple inclusions of redblack.h
+ * Thanks to Matthias Andree for reporting (and fixing) these
+ *
+ * Revision 1.4 2000/06/06 14:43:43 damo
+ * Added all the rbwalk & rbopenlist stuff. Fixed up malloc instead of sbrk.
+ * Added two new examples
+ *
+ * Revision 1.3 2000/05/24 06:45:27 damo
+ * Converted everything over to using const
+ * Added a new example1.c file to demonstrate the worst case scenario
+ * Minor fixups of the spec file
+ *
+ * Revision 1.2 2000/05/24 06:17:10 damo
+ * Fixed up the License (now the LGPL)
+ *
+ * Revision 1.1 2000/05/24 04:15:53 damo
+ * Initial import of files. Versions are now all over the place. Oh well
+ *
+ */
+
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include "repair.h"
+#include "model.h"
+#include "normalizer.h"
+#include "list.h"
+#include "Action.h"
+#include "processobject.h"
+#include "ActionInSet.h"
+#include "ActionNotInSet.h"
+#include "ActionGEQ1.h"
+#include "ActionEQ1.h"
+#include "ActionAssign.h"
+#include "ActionNormal.h"
+#include "Relation.h"
+#include "omodel.h"
+#include "dmodel.h"
+#include "set.h"
+#include "common.h"
+#include "fieldcheck.h"
+#include "Hashtable.h"
+
+Repair::Repair(model *m) {
+ globalmodel=m;
+ removedsentences=NULL;
+ List *list=new List();
+ /* list->addobject(); --build action array */
+ list->addobject(new ActionGEQ1(m->getdomainrelation(),m));
+ list->addobject(new ActionEQ1(m->getdomainrelation(),m));
+ list->addobject(new ActionAssign(m->getdomainrelation(),m));
+ // list->addobject(new ActionNotAssign(m->getdomainrelation()));
+ list->addobject(new ActionInSet(m->getdomainrelation(),m));
+ list->addobject(new ActionNotInSet(m->getdomainrelation(),m));
+ numactions=list->size();
+ repairactions=new Action *[list->size()];
+ list->toArray((void **)repairactions);
+ delete(list);
+}
+
+
+void Repair::repaireleexpr(Constraint *c, processobject *po, Elementexpr *ee, Hashtable *env) {
+ /* We're here because we have a bad elementexpr */
+ switch(ee->gettype()) {
+ case ELEMENTEXPR_SUB:
+ case ELEMENTEXPR_ADD:
+ case ELEMENTEXPR_MULT:
+ repaireleexpr(c,po,ee->getleft(),env);
+ repaireleexpr(c,po,ee->getright(),env);
+ return;
+ case ELEMENTEXPR_RELATION: {
+ /* Could have problem here */
+ repaireleexpr(c,po,ee->getleft(),env);
+ Element *e=evaluateexpr(ee,env,globalmodel);
+ if (e==NULL) {
+ /* found bad relation */
+ FieldCheck *fc=globalmodel->getfieldcheck();
+ char *set=NULL;
+
+ {
+ Elementexpr *left=ee->getleft();
+ int tleft=left->gettype();
+ if (tleft==ELEMENTEXPR_LABEL) {
+ set=getset(c, left->getlabel()->label());
+ } else if (tleft==ELEMENTEXPR_RELATION) {
+ DRelation *drl=globalmodel->getdomainrelation()->getrelation(left->getrelation()->getname());
+ set=drl->getrange();
+ } else {
+ ee->print();
+ printf("Can't determine domain-shouldn't be here because of static analysis...\n");
+ exit(-1);
+ }
+ }
+
+ Element *e2=evaluateexpr(ee->getleft(),env,globalmodel);
+ int index=fc->getindexthatprovides(ee->getrelation()->getname(), set);
+ Hashtable *env2=new Hashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings);
+ env2->setparent(env);
+ Constraint *crep=globalmodel->getconstraint(index);
+ DomainRelation *dr=globalmodel->getdomainrelation();
+ for(int j=0;j<crep->numquants();j++) {
+ Quantifier *qrep=crep->getquant(j);
+ char *label=qrep->getlabel()->label();
+ char *setname=qrep->getset()->getname();
+ DomainSet *dset=dr->getset(setname);
+ if (dset->getset()->contains(e2)) {
+ env2->put(label,e2);
+ } else {
+ env2->put(label,dset->getset()->firstelement()); /*This shouldn't happen right now*/
+ printf("Funnyness in repair.cc\n");
+ }
+ }
+ this->repairconstraint(globalmodel->getconstraint(index),po,env2);
+ delete(e2);
+ delete(env2);
+ } else
+ delete(e);
+ return;
+ }
+ default:
+ return;
+ }
+}
+
+
+void Repair::repairconstraint(Constraint *c, processobject *po, Hashtable *env) {
+ NormalForm *nf=globalmodel->getnormalform(c);
+ CoerceSentence *coercionstate=nf->closestmatch(removedsentences,po,env);
+ /* Now we just need to coerce the predicates!!!*/
+ for(int i=0;i<coercionstate->getnumpredicates();i++) {
+ CoercePredicate *cp=coercionstate->getpredicate(i);
+ int status=po->processpredicate(cp->getpredicate(),env);
+ while (status==PFAIL) {
+ /* Bad dereference...need to fix things*/
+ repaireleexpr(c, po,cp->getpredicate()->geteleexpr(), env);
+ status=po->processpredicate(cp->getpredicate(),env);
+ }
+
+ if (status!=cp->getcoercebool()) {
+ /*Need to coerce*/
+ Action *act=findrepairaction(cp);
+ act->repairpredicate(env,cp);
+ /* Data structure fixed - well eventually*/
+ }
+ }
+}
+
+
+// returns the action that can repair the given predicate
+Action * Repair::findrepairaction(CoercePredicate *cp) {
+ for(int i=0;i<numactions;i++) {
+ if (repairactions[i]->canrepairpredicate(cp))
+ return repairactions[i];
+ }
+ return NULL;
+}
+
+
+
+// returns the action that can break the given predicate
+Action * Repair::findbreakaction(CoercePredicate *cp)
+{
+ return findrepairaction(cp);
+}
+
+
+bool Repair::analyzetermination() {
+ WorkRelation *wr=new WorkRelation(true);
+ buildmap(wr);
+ /* Map built */
+ WorkSet *cycleset=searchcycles(wr);
+ if (!cycleset->isEmpty()) {
+ WorkSet *removeedges=new WorkSet(true);
+ for(int i=1;i<=cycleset->size();i++) {
+ if (breakcycles(removeedges, i, cycleset,wr)) {
+ removedsentences=removeedges;
+ printf("Modified constraints for repairability!\n");
+ outputgraph(removeedges, wr, "cycle.dot");
+ return true;
+ }
+ }
+ delete(removeedges);
+ return false;
+ } else {
+ outputgraph(NULL,wr, "cycle.dot");
+ return true;
+ }
+}
+
+
+
+bool Repair::breakcycles(WorkSet *removeedge, int number, WorkSet *cyclelinks, WorkRelation *wr) {
+ for(CoerceSentence *cs=(CoerceSentence *)cyclelinks->firstelement();
+ cs!=NULL;cs=(CoerceSentence *)cyclelinks->getnextelement(cs)) {
+ if (!removeedge->contains(cs)) {
+ removeedge->addobject(cs);
+ if (number==1) {
+ if (!checkforcycles(removeedge, wr))
+ return true;
+ } else {
+ if (breakcycles(removeedge,number-1,cyclelinks,wr))
+ return true;
+ }
+ removeedge->removeobject(cs);
+ }
+ }
+ return false;
+}
+
+void Repair::outputgraph(WorkSet *removededges, WorkRelation *wr, char *filename) {
+ FILE * dotfile=fopen(filename,"w");
+ fprintf(dotfile,"digraph cyclegraph {\n");
+ fprintf(dotfile,"ratio=auto\n");
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ NormalForm *nf=globalmodel->getnormalform(i);
+ fprintf(dotfile, "%lu[label=\"",nf);
+ nf->fprint(dotfile);
+ fprintf(dotfile,"\"];\n");
+ for(int j=0;j<nf->getnumsentences();j++) {
+ CoerceSentence *cs=nf->getsentence(j);
+ for(int i=0;i<cs->getnumpredicates();i++) {
+ CoercePredicate *cp=cs->getpredicate(i);
+ fprintf(dotfile,"%lu -> %lu [style=dashed]\n",nf,cp);
+ WorkSet *setofnf=wr->getset(cp);
+ if (setofnf!=NULL) {
+ NormalForm *nf2=(NormalForm*)setofnf->firstelement();
+ while(nf2!=NULL) {
+ /* cp interferes with nf2 */
+ bool removed=(removededges!=NULL)&&removededges->contains(cs); /*tells what color of edge to generate*/
+ if (removed)
+ fprintf(dotfile,"%lu -> %lu [style=dotted]\n",cp,nf2);
+ else
+ fprintf(dotfile,"%lu -> %lu\n",cp,nf2);
+ nf2=(NormalForm *)setofnf->getnextelement(nf2);
+ }
+ }
+ }
+ }
+ }
+ fprintf(dotfile,"}\n");
+ fclose(dotfile);
+}
+
+bool Repair::checkforcycles(WorkSet *removededges, WorkRelation *wr) {
+ /* Check that there are no cycles and
+ that system is solvable */
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ NormalForm *nf=globalmodel->getnormalform(i);
+ bool good=false;
+ for(int j=0;j<nf->getnumsentences();j++) {
+ if (!removededges->contains(nf->getsentence(j))) {
+ CoerceSentence *cs=nf->getsentence(j);
+ bool allgood=true;
+ for(int k=0;k<cs->getnumpredicates();k++) {
+ if(cs->getpredicate(k)->isrule()&&
+ findrepairaction(cs->getpredicate(k))==NULL) {
+ allgood=false;
+ break;
+ }
+ }
+ if(allgood) {
+ good=true;
+ break;
+ }
+ }
+ }
+ if (!good)
+ return true;
+ }
+ WorkSet *tmpset=new WorkSet(true);
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ NormalForm *nf=globalmodel->getnormalform(i);
+ bool good=false;
+ for(int j=0;j<nf->getnumsentences();j++) {
+ CoerceSentence *cs=nf->getsentence(j);
+ if (checkcycles(cs,removededges,tmpset,wr)) {
+ delete(tmpset);
+ return true;
+ }
+ }
+ }
+ delete(tmpset);
+ return false; /*yeah...no cycles*/
+}
+
+
+
+bool Repair::checkcycles(CoerceSentence *cs,WorkSet *removededges, WorkSet *searchset,WorkRelation *wr) {
+ if (searchset->contains(cs)) {
+ /* found cycle */
+ return true;
+ }
+ if (removededges->contains(cs))
+ return false; /* this edge is removed...don't consider it*/
+
+ searchset->addobject(cs);
+ for(int i=0;i<cs->getnumpredicates();i++) {
+ CoercePredicate *cp=cs->getpredicate(i);
+ WorkSet *setofnf=wr->getset(cp);
+ if (setofnf!=NULL) {
+ /* Might not mess up anything */
+ NormalForm *nf=(NormalForm*)setofnf->firstelement();
+ while(nf!=NULL) {
+ for(int j=0;j<nf->getnumsentences();j++) {
+ CoerceSentence *cssearch=nf->getsentence(j);
+ if (checkcycles(cssearch, removededges, searchset, wr))
+ return true;
+ }
+ nf=(NormalForm *)setofnf->getnextelement(nf);
+ }
+ }
+ }
+ searchset->removeobject(cs);
+ return false;
+}
+
+
+
+WorkSet * Repair::searchcycles(WorkRelation *wr) {
+ /* Do cycle search */
+ WorkSet *cycleset=new WorkSet(true);
+ WorkSet *searchset=new WorkSet(true);
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ NormalForm *nf=globalmodel->getnormalform(i);
+ for(int j=0;j<nf->getnumsentences();j++) {
+ detectcycles(nf->getsentence(j),searchset,cycleset,wr);
+ }
+ }
+ delete(searchset);
+ return cycleset;
+}
+
+
+
+void Repair::detectcycles(CoerceSentence *cs,WorkSet *searchset,WorkSet *cycleset, WorkRelation *wr) {
+ if (searchset->contains(cs)) {
+ /* found cycle */
+ CoerceSentence *csptr=(CoerceSentence *)searchset->firstelement();
+ while(csptr!=NULL) {
+ cycleset->addobject(csptr);
+ csptr=(CoerceSentence *)searchset->getnextelement(csptr);
+ }
+ return;
+ }
+ searchset->addobject(cs);
+ for(int i=0;i<cs->getnumpredicates();i++) {
+ CoercePredicate *cp=cs->getpredicate(i);
+ WorkSet *setofnf=wr->getset(cp);
+ if (setofnf!=NULL) {
+ /* Might not have any interference edges*/
+ NormalForm *nf=(NormalForm*)setofnf->firstelement();
+ while(nf!=NULL) {
+ for(int j=0;j<nf->getnumsentences();j++) {
+ CoerceSentence *cssearch=nf->getsentence(j);
+ detectcycles(cssearch, searchset, cycleset, wr);
+ }
+ nf=(NormalForm*)setofnf->getnextelement(nf);
+ }
+ }
+ }
+ searchset->removeobject(cs);
+}
+
+
+
+void Repair::buildmap(WorkRelation *wr) {
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ NormalForm *nf=globalmodel->getnormalform(i);
+ for(int j=0;j<nf->getnumsentences();j++) {
+ CoerceSentence *cs=nf->getsentence(j);
+ for (int k=0;k<cs->getnumpredicates();k++) {
+ Action *repairaction=findrepairaction(cs->getpredicate(k));
+ if (repairaction==NULL) {
+ /* Nothing will repair this */
+ cs->getpredicate(k)->getpredicate()->print();
+ printf(" can't be repaired!!!");
+ exit(-1);
+ }
+ checkpredicate(repairaction,wr, globalmodel->getconstraint(i),cs->getpredicate(k));
+ }
+ }
+ }
+ ActionNormal *repairnormal=new ActionNormal(globalmodel);
+ for(int i=0;i<globalmodel->getnumrulenormal();i++) {
+ NormalForm *nf=globalmodel->getrulenormal(i);
+ CoercePredicate *cpo=nf->getsentence(0)->getpredicate(0);
+ /* Check for conflicts between abstraction functions */
+ for(int j=0;j<globalmodel->getnumrulenormal();j++) {
+ NormalForm *nfn=globalmodel->getrulenormal(j);
+ CoercePredicate *cpn=nfn->getsentence(0)->getpredicate(0);
+ if (!cpo->istuple()&&
+ equivalentstrings(cpo->getrelset(),cpn->gettriggerset()))
+ wr->put(cpo,nfn);
+ }
+
+ /* Check for conflict between abstraction functions and model constraints */
+ for(int i2=0;i2<globalmodel->getnumconstraints();i2++) {
+ NormalForm *nf2=globalmodel->getnormalform(i2);
+ for(int j2=0;j2<nf2->getnumsentences();j2++) {
+ CoerceSentence *cs2=nf2->getsentence(j2);
+ for (int k2=0;k2<cs2->getnumpredicates();k2++) {
+ if (repairnormal->conflict(NULL,cpo,globalmodel->getconstraint(i2),cs2->getpredicate(k2)))
+ wr->put(cpo,nf2);
+ }
+ }
+ }
+ }
+ delete(repairnormal);
+}
+
+
+
+void Repair::checkpredicate(Action *repair,WorkRelation *wr, Constraint *c,CoercePredicate *cp) {
+ for(int i=0;i<globalmodel->getnumconstraints();i++) {
+ NormalForm *nf=globalmodel->getnormalform(i);
+ for(int j=0;j<nf->getnumsentences();j++) {
+ CoerceSentence *cs=nf->getsentence(j);
+ for (int k=0;k<cs->getnumpredicates();k++) {
+ if (repair->conflict(c,cp,globalmodel->getconstraint(i),cs->getpredicate(k)))
+ wr->put(cp, nf);
+ }
+ }
+ }
+ for(int i=0;i<globalmodel->getnumrulenormal();i++) {
+ NormalForm *nf=globalmodel->getrulenormal(i);
+ if (repair->conflict(c,cp,NULL, nf->getsentence(0)->getpredicate(0)))
+ wr->put(cp,nf);
+ }
+}
+
--- /dev/null
+#ifndef REPAIR_H
+#define REPAIR_H
+#include "classlist.h"
+class Repair {
+ public:
+ Repair(model *m);
+ void repairconstraint(Constraint *c, processobject *po, Hashtable *env);
+ Action * findrepairaction(CoercePredicate *cp);
+ Action * findbreakaction(CoercePredicate *cp);
+ bool analyzetermination();
+
+
+ private:
+ void outputgraph(WorkSet *removededges, WorkRelation *wr, char *filename);
+ void repaireleexpr(Constraint *c, processobject *po, Elementexpr *ee, Hashtable *env);
+ void buildmap(WorkRelation *wr);
+ void checkpredicate(Action *repair,WorkRelation *wr, Constraint *c,CoercePredicate *cp);
+ bool checkforcycles(WorkSet *removededges, WorkRelation *wr);
+ bool checkcycles(CoerceSentence *cs,WorkSet *removededges, WorkSet *searchset,WorkRelation *wr);
+ bool breakcycles(WorkSet *removeedge, int number, WorkSet *cyclelinks, WorkRelation *wr);
+ void detectcycles(CoerceSentence *cs,WorkSet *searchset,WorkSet *cycleset, WorkRelation *wr);
+ WorkSet * searchcycles(WorkRelation *wr);
+ model * globalmodel;
+
+ Action ** repairactions; // the available repair actions
+ int numactions;
+
+ WorkSet *removedsentences;
+};
+#endif
+
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "rparser.h"
+#include "list.h"
+#include "common.h"
+#include "token.h"
+#include "set.h"
+#include "classlist.h"
+
+
+// class RParser
+
+RParser::RParser(Reader *r)
+{
+ reader=r;
+}
+
+
+// returns the name of the relation whose range is defined
+char* RParser::parserelation()
+{
+ Token token = reader->peakahead();
+
+ while(token.token_type==TOKEN_EOL)
+ {
+ skiptoken();
+ token = reader->peakahead();
+ }
+
+ if (token.token_type==TOKEN_EOF)
+ return NULL;
+
+ needtoken(0);
+ needtoken(TOKEN_COLON); // we need a colon
+
+ char* relation = new char[strlen(token.str)+1];
+ strcpy(relation, token.str);
+ return relation;
+}
+
+
+
+WorkSet* RParser::parseworkset()
+{
+#ifdef DEBUGMANYMESSAGES
+ printf("Parsing a new workset... \n");
+#endif
+
+ WorkSet *wset = new WorkSet(true);
+ needtoken(TOKEN_OPENBRACE); // need an open brace
+
+ Token token = reader->readnext();
+
+ while (token.token_type != TOKEN_CLOSEBRACE)
+ {
+#ifdef DEBUGMESSAGES
+ //printf("Adding %s...\n", token.str);
+ //fflush(NULL);
+#endif
+ char* newtoken = (char*) malloc(strlen(token.str));
+ strcpy(newtoken, token.str);
+
+ wset->addobject(newtoken);
+
+ token = reader->readnext();
+
+ if (token.token_type == TOKEN_COMMA)
+ token = reader->readnext();
+ }
+
+ return wset;
+}
+
+
+
+void RParser::error()
+{
+ printf("ERROR\n");
+ reader->error();
+ exit(-1);
+}
+
+
+void RParser::skiptoken()
+{
+ reader->readnext();
+}
+
+
+void RParser::needtoken(int token)
+{
+ Token t=reader->readnext();
+ if (!(t.token_type==token))
+ {
+ printf("Needed token: ");
+ tokenname(token);
+ printf("\n Got token: %s ",t.str);
+ tokenname(t.token_type);
+ error();
+ }
+}
--- /dev/null
+#ifndef RangeFileParser_H
+#define RangeFileParser_H
+
+#include "common.h"
+#include <iostream.h>
+#include <stdio.h>
+#include "classlist.h"
+
+class RParser {
+ public:
+ RParser(Reader *r);
+ char* parserelation();
+ WorkSet* parseworkset();
+
+ private:
+ void skiptoken();
+ void needtoken(int);
+ void error();
+ Reader *reader;
+};
+#endif
--- /dev/null
+#include <stdio.h>
+#include "set.h"
+#include "GenericHashtable.h"
+#include "element.h"
+
+
+
+// class WorkSet
+
+WorkSet::WorkSet() {
+ ght=genallocatehashtable((unsigned int (*)(void *)) & hashelement,(int (*)(void *,void *)) & elementequals);
+}
+
+WorkSet::WorkSet(unsigned int (*hashf)(void *),int (*equals)(void *,void *)) {
+ ght=genallocatehashtable(hashf,equals);
+}
+
+WorkSet::WorkSet(bool) {
+ ght=genallocatehashtable(NULL,NULL);
+}
+
+WorkSet::~WorkSet() {
+ genfreehashtable(ght);
+}
+
+void WorkSet::addobject(void *obj) {
+ if (!contains(obj))
+ {
+ fflush(NULL);
+ genputtable(ght,obj,obj);
+ }
+}
+
+void WorkSet::removeobject(void *obj) {
+ genfreekey(ght,obj);
+}
+
+bool WorkSet::contains(void *obj) {
+ return (gencontains(ght,obj)==1);
+}
+
+void * WorkSet::firstelement() {
+ if (ght->list==NULL)
+ return NULL;
+ else
+ return ght->list->src;
+}
+
+Iterator * WorkSet::getiterator() {
+ return new Iterator(ght);
+}
+
+void * WorkSet::getnextelement(void *src) {
+ return getnext(ght,src);
+}
+
+void * WorkSet::getelement(int i) {
+ void *v=firstelement();
+ while(i>0) {
+ i--;
+ v=getnext(ght,v);
+ }
+ return v;
+}
+
+int WorkSet::size() {
+ return hashsize(ght);
+}
+
+bool WorkSet::isEmpty() {
+ return (size()==0);
+}
+
+void WorkSet::print()
+{
+ printf("{");
+ for (int i=0; i<size(); i++)
+ {
+ Element *elem = (Element *) getelement(i);
+ elem->print();
+ if (i != size()-1)
+ printf(" ");
+ }
+ printf("}");
+}
+
+
+
+
+// class Iterator
+
+Iterator::Iterator(struct genhashtable *ght) {
+ gi=gengetiterator(ght);
+}
+
+Iterator::~Iterator() {
+ genfreeiterator(gi);
+}
+
+void * Iterator::next() {
+ return gennext(gi);
+}
--- /dev/null
+#ifndef SET_H
+#define SET_H
+
+#include "classlist.h"
+
+class WorkSet {
+ public:
+ WorkSet();
+ WorkSet(unsigned int (*hashf)(void *),int (*equals)(void *,void *));
+ WorkSet(bool);
+ ~WorkSet();
+ void addobject(void *obj);
+ void removeobject(void *obj);
+ bool contains(void *obj);
+ Iterator * getiterator();
+ void *firstelement();
+ void * getnextelement(void *src);
+ int size();
+ void * getelement(int i);
+ bool isEmpty();
+ void print();
+
+ private:
+ struct genhashtable *ght;
+};
+
+class Iterator {
+ public:
+ Iterator(struct genhashtable *ght);
+ ~Iterator();
+ void * next();
+
+ private:
+ struct geniterator * gi;
+};
+
+#endif
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include "stack.h"
+//#include "dmalloc.h"
+
+void pushstack(struct StackElement **septr,void * obj) {
+ struct StackElement * nse=(struct StackElement *)malloc(sizeof(struct StackElement));
+ nse->contents=obj;
+ nse->next=*septr;
+ *septr=nse;
+}
+
+void * popstack(struct StackElement **septr) {
+ if(*septr==NULL) {
+ printf("Empty Stack\n");
+ return NULL;/* Empty stack */
+ }
+ {
+ void *obj=(*septr)->contents;
+ struct StackElement *ose=*septr;
+ (*septr)=ose->next;
+ free(ose);
+ return obj;
+ }
+}
--- /dev/null
+#ifndef STACK_H
+#define STACK_H
+
+struct StackElement {
+ struct StackElement * next;
+ void * contents;
+};
+void pushstack(struct StackElement **septr,void * obj);
+void * popstack(struct StackElement **septr);
+#endif
--- /dev/null
+/* Defines interfaces for the applications and exports function calls that
+ the applications should use instead of the standard ones. */
+
+#include <stdlib.h>
+#include <sys/time.h>
+#include "classlist.h"
+#include "model.h"
+#include "dmodel.h"
+extern "C" {
+#include "test.h"
+}
+#include <stdio.h>
+#include "element.h"
+#include "Hashtable.h"
+#include "tmap.h"
+
+
+
+model * exportmodel;
+
+void initializeanalysis()
+{
+ exportmodel=new model("testabstract", "testmodel", "testspace", "teststruct", "testconcrete", "testrange");
+}
+
+
+
+
+void doanalysis()
+{
+ struct timeval begin,end;
+ unsigned long t;
+ gettimeofday(&begin,NULL);
+ exportmodel->doabstraction();
+ exportmodel->getdomainrelation()->fixstuff();
+ bool found = exportmodel->docheck();
+ exportmodel->doconcrete();
+ gettimeofday(&end,NULL);
+ t=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+
+#ifdef DEBUGMANYMESSAGES
+
+#endif
+ exportmodel->getdomainrelation()->print();
+ printf("Time used for analysis(us): %ld\n",t);
+}
+
+
+/* This procedure invokes the tool.
+ If the model hasn't been initialized, it simply returns.
+ If a bug was constraint violation was found, displays a message
+ and terminates the program. */
+void doanalysisfordebugging(char* msg)
+{
+ if (exportmodel == NULL) {
+ printf("Initialize tool first...\n");
+ return;
+ }
+
+ printf("%s\n", msg);
+ exportmodel->doabstraction();
+
+ //exportmodel->getdomainrelation()->fixstuff();
+ //bool found = exportmodel->docheck();
+
+ bool found = exportmodel->getdomainrelation()->fixstuff() || exportmodel->docheck();
+
+#ifdef DEBUGMANYMESSAGES
+ exportmodel->getdomainrelation()->print();
+#endif
+
+ if (found)
+ exit(1);
+
+ resetanalysis();
+ printf("\n");
+}
+
+
+
+// returns true if a violated constraint was found
+unsigned long benchmark()
+{
+ struct timeval begin,end;
+ unsigned long t;
+ gettimeofday(&begin,NULL);
+ exportmodel->doabstraction();
+ exportmodel->getdomainrelation()->fixstuff();
+ bool found = exportmodel->docheck();
+ exportmodel->doconcrete();
+ gettimeofday(&end,NULL);
+ t=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+ return t;
+}
+
+
+// insert errors that break the specs
+void doanalysis2()
+{
+ struct timeval begin,end;
+ unsigned long t;
+ gettimeofday(&begin,NULL);
+ exportmodel->doabstraction();
+ exportmodel->getdomainrelation()->fixstuff();
+
+
+ exportmodel->breakspec();
+#ifdef DEBUGMESSAGES
+ printf("\n\nSpecs BROKEN \n\n");
+ fflush(NULL);
+#endif
+
+ exportmodel->docheck();
+ exportmodel->doconcrete();
+ gettimeofday(&end,NULL);
+ t=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+
+ printf("Time used for analysis(us): %ld\n",t);
+}
+
+
+// insert errors that do not break the specs
+void doanalysis3()
+{
+ struct timeval begin,end;
+ unsigned long t;
+ gettimeofday(&begin,NULL);
+ exportmodel->doabstraction();
+ exportmodel->getdomainrelation()->fixstuff();
+
+ exportmodel->inserterrors();
+
+#ifdef DEBUGMESSAGES
+ printf("\n\nErrors INSERTED \n\n");
+ fflush(NULL);
+#endif
+
+ exportmodel->docheck();
+ exportmodel->doconcrete();
+ gettimeofday(&end,NULL);
+ t=(end.tv_sec-begin.tv_sec)*1000000+end.tv_usec-begin.tv_usec;
+
+ printf("Time used for analysis(us): %ld\n",t);
+}
+
+
+
+void resetanalysis() {
+ exportmodel->reset();
+}
+
+void addmapping(char *key, void * address, char *type) {
+ Hashtable *env=exportmodel->gethashtable();
+ env->put(key,new Element(address,exportmodel->getstructure(type)));//should be of badstruct
+}
+
+void addintmapping(char *key, int value) {
+ Hashtable *env=exportmodel->gethashtable();
+ env->put(key,new Element(value)); //should be of badstruct
+}
+
+void *ourcalloc(size_t nmemb, size_t size) {
+ typemap *tm=exportmodel->gettypemap();
+ void *oc=calloc(nmemb,size);
+ tm->allocate(oc,size*nmemb);
+ return oc;
+}
+
+void *ourmalloc(size_t size) {
+ typemap *tm=exportmodel->gettypemap();
+ void *oc=malloc(size);
+ tm->allocate(oc,size);
+ return oc;
+}
+
+void ourfree(void *ptr) {
+ typemap *tm=exportmodel->gettypemap();
+ tm->deallocate(ptr);
+ free(ptr);
+}
+
+void *ourrealloc(void *ptr, size_t size) {
+ typemap *tm=exportmodel->gettypemap();
+ void *orr=realloc(ptr,size);
+ if (size==0) {
+ tm->deallocate(ptr);
+ return orr;
+ }
+ if (orr==NULL) {
+ return orr;
+ }
+ tm->deallocate(ptr);
+ tm->allocate(ptr,size);
+}
+
+void alloc(void *ptr,int size) {
+ typemap *tm=exportmodel->gettypemap();
+ tm->allocate(ptr,size);
+}
+
+void dealloc(void *ptr) {
+ typemap *tm=exportmodel->gettypemap();
+ tm->deallocate(ptr);
+}
--- /dev/null
+/* Defines interfaces for the applications and exports function calls that
+ the applications should use instead of the standard ones. */
+
+#ifndef TEST_H
+#define TEST_H
+void initializeanalysis();
+unsigned long benchmark(); /* do analysis */
+void doanalysis(); /* do analysis */
+void doanalysis2(); /* break the specs and do analysis */
+void doanalysis3(); /* insert errors and do analysis */
+void doanalysisfordebugging(char *msg );
+void resetanalysis();
+void addmapping(char *, void *,char *);
+void addintmapping(char *key, int value);
+void alloc(void *ptr,int size);
+void dealloc(void *ptr);
+void *ourcalloc(size_t nmemb, size_t size);
+void *ourmalloc(size_t size);
+void ourfree(void *ptr);
+void *ourrealloc(void *ptr, size_t size);
+#endif
--- /dev/null
+[], true => literal(0) in SuperBlock
+[], true => literal(1) in GroupBlock
+[], d.g.InodeTableBlock < d.s.NumberofBlocks => d.g.InodeTableBlock in InodeTableBlock
+[], d.g.InodeBitmapBlock < d.s.NumberofBlocks => d.g.InodeBitmapBlock in InodeBitmapBlock
+[], d.g.BlockBitmapBlock < d.s.NumberofBlocks => d.g.BlockBitmapBlock in BlockBitmapBlock
+[], d.s.RootDirectoryInode < d.s.NumberofInodes => d.s.RootDirectoryInode in RootDirectoryInode
+delay [for j=literal(0) to d.s.NumberofInodes-literal(1)], !(j in UsedInode) => j in FreeInode
+delay [for j=literal(0) to d.s.NumberofBlocks-literal(1)], !(j in UsedBlock) => j in FreeBlock
+[forall di in DirectoryInode, forall itb in InodeTableBlock, for j=literal(0) to (d.s.blocksize/literal(128))-literal(1), for k=literal(0) to literal(11)], cast(InodeTable,d.b[itb]).itable[di].Blockptr[k] < d.s.NumberofBlocks => cast(DirectoryBlock,d.b[cast(InodeTable,d.b[itb]).itable[di].Blockptr[k]]).de[j] in DirectoryEntry
+[forall i in UsedInode, forall itb in InodeTableBlock, for j=literal(0) to literal(11)], !cast(InodeTable,d.b[itb]).itable[i].Blockptr[j]=literal(0) => <i,cast(InodeTable,d.b[itb]).itable[i].Blockptr[j]> in contents
+[forall i in UsedInode, forall itb in InodeTableBlock, for j=literal(0) to literal(11)], cast(InodeTable,d.b[itb]).itable[i].Blockptr[j]<d.s.NumberofBlocks and !cast(InodeTable,d.b[itb]).itable[i].Blockptr[j]=literal(0) => cast(InodeTable,d.b[itb]).itable[i].Blockptr[j] in FileDirectoryBlock
+[for j=literal(0) to d.s.NumberofInodes-literal(1), forall ibb in InodeBitmapBlock], cast(InodeBitmap,d.b[ibb]).inodebitmap[j]=literal(false) => <j,literal(Free)> in inodestatus
+[for j=literal(0) to d.s.NumberofInodes-literal(1), forall ibb in InodeBitmapBlock], cast(InodeBitmap,d.b[ibb]).inodebitmap[j]=literal(true) => <j,literal(Used)> in inodestatus
+[forall de in DirectoryEntry], de.inodenumber<d.s.NumberofInodes and !de.inodenumber = literal(0) => de.inodenumber in FileInode
+[forall de in DirectoryEntry], de.inodenumber<d.s.NumberofInodes => <de, de.inodenumber> in inodeof
+[forall j in UsedInode, forall itb in InodeTableBlock], true => <j,cast(InodeTable,d.b[itb]).itable[j].referencecount> in referencecount
+[forall j in UsedInode, forall itb in InodeTableBlock], true => <j,cast(InodeTable,d.b[itb]).itable[j].filesize> in filesize
+[for j=literal(0) to d.s.NumberofBlocks-literal(1), forall bbb in BlockBitmapBlock], cast(BlockBitmap,d.b[bbb]).blockbitmap[j]=literal(false) => <j,literal(Free)> in blockstatus
+[for j=literal(0) to d.s.NumberofBlocks-literal(1), forall bbb in BlockBitmapBlock], cast(BlockBitmap,d.b[bbb]).blockbitmap[j]=literal(true) => <j,literal(Used)> in blockstatus
--- /dev/null
+[forall u in InodeTableBlock], true => d.g.InodeTableBlock=u
+[forall u in InodeBitmapBlock], true => d.g.InodeBitmapBlock=u
+[forall u in BlockBitmapBlock], true => d.g.BlockBitmapBlock=u
+[forall u in RootDirectoryInode], true => d.s.RootDirectoryInode=u
+[forall i in UsedInode, forall itb in InodeTableBlock, for j=literal(0) to literal(11)], j < sizeof(i.contents) => cast(InodeTable,d.b[itb]).itable[i].Blockptr[j]=element j of i.contents
+[forall i in UsedInode, forall itb in InodeTableBlock, for j=literal(0) to literal(11)], !j<sizeof(i.contents) => cast(InodeTable,d.b[itb]).itable[i].Blockptr[j]=literal(0)
+[forall ibb in InodeBitmapBlock, forall <j,status> in inodestatus], status=literal(Free) => cast(InodeBitmap,d.b[ibb]).inodebitmap[j]=literal(false)
+[forall ibb in InodeBitmapBlock, forall <j,status> in inodestatus], status=literal(Used) => cast(InodeBitmap,d.b[ibb]).inodebitmap[j]=literal(true)
+[forall <de, u> in inodeof], true => de.inodenumber=u
+[forall itb in InodeTableBlock, forall <j,u> in referencecount], true => cast(InodeTable,d.b[itb]).itable[j].referencecount=u
+[forall itb in InodeTableBlock, forall <j,u> in filesize], true => cast(InodeTable,d.b[itb]).itable[j].filesize=u
+[forall bbb in BlockBitmapBlock, forall <j, status> in blockstatus], status=literal(Free) => cast(BlockBitmap,d.b[bbb]).blockbitmap[j] = literal(false)
+[forall bbb in BlockBitmapBlock, forall <j,status> in blockstatus], status=literal(Used) => cast(BlockBitmap,d.b[bbb]).blockbitmap[j] = literal(true)
--- /dev/null
+[forall u in UsedInode], u.inodestatus=literal(Used)
+[forall f in FreeInode], f.inodestatus=literal(Free)
+[forall u in UsedBlock], u.blockstatus=literal(Used)
+[forall f in FreeBlock], f.blockstatus=literal(Free)
+[forall i in UsedInode], i.referencecount=sizeof(i.~inodeof) or i in RootDirectoryInode
+[forall i in UsedInode], i.filesize <= sizeof(i.contents)*literal(8192)
+[forall b in FileDirectoryBlock],sizeof(b.~contents)=1
+[],sizeof(SuperBlock)=1
+[],sizeof(GroupBlock)=1
+[],sizeof(InodeTableBlock)=1
+[],sizeof(InodeBitmapBlock)=1
+[],sizeof(BlockBitmapBlock)=1
+[],sizeof(RootDirectoryInode)=1
--- /dev/null
+inodestatus: {Free, Used}
+blockstatus: {Free, Used}
--- /dev/null
+set Block(int): partition UsedBlock | FreeBlock
+set FreeBlock(int):
+set Inode(int): partition UsedInode | FreeInode
+set FreeInode(int):
+set UsedInode(int): partition FileInode | DirectoryInode
+set FileInode(int):
+set DirectoryInode(int): RootDirectoryInode
+set RootDirectoryInode(int):
+set UsedBlock(int): partition SuperBlock | GroupBlock | FileDirectoryBlock | InodeTableBlock | InodeBitmapBlock | BlockBitmapBlock
+set FileDirectoryBlock(int): DirectoryBlock | FileBlock
+set SuperBlock(int):
+set GroupBlock(int):
+set FileBlock(int):
+set DirectoryBlock(int):
+set InodeTableBlock(int):
+set InodeBitmapBlock(int):
+set BlockBitmapBlock(int):
+set DirectoryEntry(DirectoryEntry):
+inodeof: DirectoryEntry -> UsedInode (many->1)
+contents: UsedInode -> FileDirectoryBlock (1->many)
+inodestatus: Inode -> token (many->1)
+blockstatus: Block -> token (many->1)
+referencecount: Inode -> int (many->1)
+filesize: Inode -> int (many->1)
--- /dev/null
+structure Block {
+ reserved byte[d.s.blocksize];
+}
+
+structure Disk {
+ Block b[d.s.NumberofBlocks];
+ label b[literal(0)]: Superblock s;
+ label b[literal(1)]: Groupblock g;
+}
+
+structure Superblock subtype of Block {
+ int FreeBlockCount;
+ int FreeInodeCount;
+ int NumberofBlocks;
+ int NumberofInodes;
+ int RootDirectoryInode;
+ int blocksize;
+}
+
+structure Groupblock subtype of Block {
+ int BlockBitmapBlock;
+ int InodeBitmapBlock;
+ int InodeTableBlock;
+ int GroupFreeBlockCount;
+ int GroupFreeInodeCount;
+}
+
+structure InodeTable subtype of Block {
+ Inode itable[d.s.NumberofInodes];
+}
+
+structure InodeBitmap subtype of Block {
+ bit inodebitmap[d.s.NumberofInodes];
+}
+
+structure BlockBitmap subtype of Block {
+ bit blockbitmap[d.s.NumberofBlocks];
+}
+
+structure Inode {
+ int filesize;
+ int Blockptr[literal(12)];
+ int referencecount;
+}
+
+structure DirectoryBlock subtype of Block {
+ DirectoryEntry de[d.s.blocksize/literal(128)];
+}
+
+structure DirectoryEntry {
+ byte name[literal(124)];
+ int inodenumber;
+}
--- /dev/null
+#include <stdio.h>
+#include "tmap.h"
+extern "C" {
+#include "redblack.h"
+}
+#include "tmodel.h"
+#include "model.h"
+#include "processabstract.h"
+#include "element.h"
+
+#define CHECKTYPE
+#define CHECKMEMORY
+
+typemap::typemap(model *m) {
+ alloctree=rbinit();
+ typetree=rbinit();
+ globalmodel=m;
+}
+
+void freefunction(void *ptr) {
+ if(ptr!=NULL) {
+ delete((structuremap *)ptr);
+ }
+}
+
+typemap::~typemap() {
+ rbdestroy(typetree,freefunction);
+ rbdestroy(alloctree,freefunction);
+}
+
+void typemap::reset() {
+ rbdestroy(typetree,freefunction);
+ typetree=rbinit();
+}
+
+structuremap::structuremap(structure *s) {
+ str=s;
+ typetree=rbinit();
+}
+
+structuremap::~structuremap() {
+ rbdestroy(typetree,freefunction);
+}
+
+bool typemap::asserttype(void *ptr, structure *s) {
+
+#ifdef CHECKTYPE
+ bool b=checktype(true,ptr,s);
+ if (!b) {
+ printf("Assertion failure\n");
+ bool testb=checktype(true,ptr,s);
+ }
+ return b;
+#endif
+
+ return assertvalidmemory(ptr, s);
+}
+
+bool typemap::assertvalidmemory(void* low, void* high) {
+
+#ifdef CHECKMEMORY
+ return checkmemory(low, high);
+#endif
+
+ return true;
+}
+
+bool typemap::assertvalidmemory(void* ptr, structure* s) {
+
+#ifdef CHECKMEMORY
+ int size=s->getsize(globalmodel->getbitreader(),globalmodel,globalmodel->gethashtable());
+ void *low=ptr;
+ void *high=((char *)low)+size;
+ return checkmemory(low, high);
+#endif
+
+ return true;
+}
+
+bool typemap::istype(void *ptr, structure *s) {
+
+#ifdef CHECKTYPE
+ bool b=checktype(false,ptr,s);
+ if (!b) {
+ printf("Verify failure\n");
+ bool testb=checktype(false,ptr,s);
+ }
+ return b;
+#endif
+
+ return assertvalidmemory(ptr, s);
+}
+
+void typemap::allocate(void *ptr, int size) {
+ void *low=ptr;
+ void *high=((char *)ptr)+size;
+ int val=rbinsert(low,high,NULL,alloctree);
+ if (val==0)
+ printf("Error\n");
+}
+
+structure * typemap::findoffsetstructure(structure *s, int offset) {
+ int count=0;
+ for(int i=0;i<s->getnumfields();i++) {
+ int mult=1;
+ ttype *ttype=s->getfield(i)->gettype();
+ if (ttype->getsize()!=NULL) {
+ Element * number=evaluateexpr(globalmodel,ttype->getsize(),globalmodel->gethashtable(),true,false);
+ mult=number->intvalue();
+ delete(number);
+ }
+ int increment=ttype->basesize(globalmodel->getbitreader(),globalmodel,globalmodel->gethashtable());
+
+ int delt=offset-count;
+ if (delt<mult*increment) {
+ if (delt%increment==0) {
+ return globalmodel->getstructure(ttype->getname());
+ } else
+ return NULL;
+ }
+
+ count+=mult*increment;
+ }
+
+ return NULL;
+}
+
+void typemap::deallocate(void *ptr) {
+ if (rbdelete(ptr,alloctree)==NULL)
+ printf("Freeing unallocated memory\n");
+}
+
+bool typemap::checkmemory(void* low, void* high) {
+ struct pair allocp=rbfind(low,high,alloctree);
+
+ if (allocp.low == NULL) {
+ return false;
+ } else if ((allocp.low > low) || (allocp.high < high)) { /* make sure this block is used */
+ return false;
+ } else {
+ return true;
+ }
+}
+
+
+bool typemap::checktype(bool doaction,void *ptr, structure *structure) {
+ int size=structure->getsize(globalmodel->getbitreader(),globalmodel,globalmodel->gethashtable());
+ void *low=ptr;
+ void *high=((char *)low)+size;
+ struct pair allocp=rbfind(low,high,alloctree);
+ if (allocp.low==NULL)
+ return false;
+ if (allocp.low>low||allocp.high<high) /* make sure this block is used */
+ return false;
+ struct pair typep=rbfind(low,high,typetree);
+ structuremap *smap=(structuremap *)rblookup(low,high,typetree);
+
+ if (typep.low==NULL) {
+ if(!doaction)
+ return true;
+ structuremap *sm=new structuremap(structure);
+ int flag=rbinsert(low, high, sm, typetree);
+ if (flag==0) {
+ printf("Error in asserttype\n");
+ return false;
+ } else
+ return true;
+ }
+
+ return checktype(doaction, low,high, structure, typetree);
+}
+
+bool typemap::checktype(bool doaction, void *low, void *high,structure *structre, struct rbtree *ttree) {
+ struct pair typep=rbfind(low,high,ttree);
+ structuremap *smap=(structuremap *)rblookup(low,high,ttree);
+
+ if (typep.low==low&&typep.high==high) {
+ /* Recast */
+ if (globalmodel->subtypeof(structre,smap->str)) {
+ /* narrowing cast */
+ if (!doaction)
+ return true;
+ smap->str=structre;
+ return true;
+ } else if (globalmodel->subtypeof(smap->str,structre)) {
+ /* widening cast */
+ return true;
+ } else
+ return false; /* incompatible types */
+ } else if (typep.low<=low&&typep.high>=high) {
+ /* See if it matches up with structure inside typep */
+ if (rbsearch(low,high,smap->typetree)) {
+ /* recurse */
+ return checktype(doaction,low,high, structre, smap->typetree);
+ } else {
+ /* check to see if data lines up correctly */
+ int offset=((char *)low)-((char *)typep.low);
+ structure * st=findoffsetstructure(smap->str,offset);
+ if (st==NULL)
+ return false;
+ if (globalmodel->subtypeof(structre,st)) {
+ if (!doaction)
+ return true;
+ structuremap *newsm=new structuremap(structre);
+ int flag=rbinsert(low, high, newsm, smap->typetree);
+ return (flag==1);
+ } else if (globalmodel->subtypeof(st,structre)) {
+ if (!doaction)
+ return true;
+ structuremap *newsm=new structuremap(st);
+ int flag=rbinsert(low, high, newsm, smap->typetree);
+ return (flag==1);
+ } else
+ return false;
+ }
+ } else
+ return false;
+}
--- /dev/null
+#ifndef TMAP_H
+#define TMAP_H
+#include "classlist.h"
+
+class typemap {
+ public:
+ typemap(model *);
+ ~typemap();
+ void allocate(void *, int);
+ void deallocate(void *);
+ bool assertvalidmemory(void* low, void* high);
+ bool assertvalidmemory(void* ptr, structure *structure);
+ bool asserttype(void *ptr, structure *structure);
+ bool istype(void *ptr, structure *structure);
+ void reset();
+ private:
+ bool checkmemory(void* low, void* high);
+ bool checktype(bool doaction,void *ptr, structure *structure);
+ bool checktype(bool doaction, void *low, void *high,structure *structure, struct rbtree *ttree);
+ structure * findoffsetstructure(structure *s, int offset);
+ model *globalmodel;
+ struct rbtree *alloctree;
+ struct rbtree *typetree;
+};
+
+class structuremap {
+ public:
+ structuremap(structure *s);
+ ~structuremap();
+ structure *str;
+ struct rbtree *typetree;
+};
+#endif
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include "tmodel.h"
+#include "processabstract.h"
+#include "element.h"
+#include "model.h"
+#include "Hashtable.h"
+#include "common.h"
+
+
+void structure::print() {
+ printf("\nBEGIN structure:\n");
+ printf(" name=%s\n", name);
+ printf(" type=%d\n", type);
+
+ if (subtype == NULL)
+ printf(" subtype=null\n");
+ else subtype->print();
+
+ for (int i=0; i<getnumfields(); i++)
+ getfield(i)->print();
+
+ for (int i=0; i<getnumlabels(); i++)
+ getlabel(i)->print();
+
+ printf("END structure\n\n");
+}
+
+void ttype::print() {
+ printf("\nBEGIN ttype\n");
+ printf(" ttype: primtype=%ld, intlength=%ld, type=%s\n", primtype, intlength, type);
+ printf("END ttype\n\n");
+}
+
+/*void tparam::print() {
+ }*/
+
+void tlabel::print() {
+ printf("\nBEGIN tlabel\n");
+ printf(" field=%s\n", field);
+ specifictype->print();
+ printf("END tlabel\n\n");
+}
+
+void tfield::print() {
+ printf("\nBEGIN tfield\n");
+ printf(" name=\%s\n", name);
+ type->print();
+ printf("END tfield\n\n");
+}
+
+AElementexpr * ttype::getsize() {
+ return asize;
+}
+
+
+int ttype::getbytes(bitreader *br,model *m,Hashtable *env) {
+ int basesizeval=basesize(br,m,env);
+ int mult=1;
+ if (asize!=NULL) {
+ Element * number=evaluateexpr(m,asize,env,true,false);
+ mult=number->intvalue();
+ delete(number);
+ }
+ if (gettype()==TTYPE_BIT) {
+ return ((mult-1)/8)+1;
+ }
+ return mult*basesizeval;
+}
+
+int ttype::basesize(bitreader *br,model *m,Hashtable *env) {
+ if ((primtype/TTYPE_PTR)>0)
+ return pointersize;
+ if (gettype()==TTYPE_INT)
+ return intsize;
+ if (gettype()==TTYPE_SHORT)
+ return shortsize;
+ if (gettype()==TTYPE_BYTE)
+ return 1;
+ if (gettype()==TTYPE_BIT)
+ return 0;
+ if (gettype()==TTYPE_STRUCT) {
+ /* Element **earray=new Element *[numparamvalues];
+ for(int i=0;i<numparamvalues;i++) {
+ earray[i]=evaluateexpr(br,paramvalues[i],env);
+ }*/
+ structure *st=m->getstructure(type);
+ int size=st->getsize(br,m,env);
+ /* for(int i=0;i<numparamvalues;i++)
+ delete(earray[i]);
+ delete earray;*/
+ return size;
+ }
+}
+
+int structure::getsize(bitreader *br,model *m, Hashtable *env) {
+ int totalsize=0;
+ /* build parameter mapping */
+ /* for(int i=0;i<getnumparams();i++) {
+ env->put(getparam(i)->getname(),earray[i]);
+ }*/
+ /* loop through fields */
+ if (getsubtype()!=NULL) {
+ return getsubtype()->getbytes(br, m,env);
+ }
+ for(int j=0;j<getnumfields();j++)
+ totalsize+=getfield(j)->gettype()->getbytes(br,m,env);
+ //delete(env);
+ return totalsize;
+}
+char * tlabel::getname() {
+ return specifictype->getname();
+}
+ttype * tlabel::gettype() {
+ return specifictype->gettype();
+}
+
+structure::structure(char *nam) {
+ subtype=NULL;
+ name=nam;
+}
+
+void structure::settype(int t) {
+ type=t;
+}
+
+/*void structure::setparams(tparam **tp,int n) {
+ params=tp;numparams=n;
+ }*/
+
+void structure::setsubtype(ttype *sub) {
+ subtype=sub;
+}
+
+ttype * structure::getsubtype() {
+ return subtype;
+}
+
+void structure::setfields(tfield **fieldarray, int n) {
+ fields=fieldarray;
+ numfields=n;
+}
+
+void structure::setlabels(tlabel **lab,int n) {
+ labels=lab;
+ numlabels=n;
+}
+
+/*int structure::getnumparams() {
+ return numparams;
+ }*/
+
+/*tparam * structure::getparam(int i) {
+ return params[i];
+ }*/
+
+int structure::getnumlabels() {
+ return numlabels;
+}
+
+tlabel * structure::getlabel(int i) {
+ return labels[i];
+}
+
+int structure::getnumfields() {
+ return numfields;
+}
+
+tfield * structure::getfield(int i) {
+ return fields[i];
+}
+
+char * structure::getname() {
+ return name;
+}
+
+ttype::ttype(int typ) {
+ primtype=typ;
+ intlength=0;
+ type=NULL;
+ // paramvalues=NULL;
+ //numparamvalues=0;
+ asize=NULL;
+}
+
+ttype::ttype(char *t) {
+ primtype=TTYPE_STRUCT;
+ type=t;
+ intlength=0;
+ //paramvalues=NULL;
+ //numparamvalues=0;
+ asize=NULL;
+}
+
+ttype::ttype(char *t, AElementexpr *size) {
+ primtype=TTYPE_STRUCT;
+ type=t;
+ intlength=0;
+ //paramvalues=param;
+ //numparamvalues=numparam;
+ asize=size;
+}
+
+ttype::ttype(int type, AElementexpr * size) {
+ primtype=type;
+ intlength=0;
+ this->type=NULL;
+ //paramvalues=NULL;
+ //numparamvalues=0;
+ asize=size;
+}
+
+void ttype::makeptr() {
+ primtype+=TTYPE_PTR;
+}
+
+void ttype::setsize(AElementexpr *size) {
+ asize=size;
+}
+
+bool ttype::isptr() {
+ if (numderef()>0)
+ return true;
+ else
+ return false;
+}
+
+int ttype::numderef() {
+ return primtype/TTYPE_PTR;
+}
+
+int ttype::gettype() {
+ return primtype%TTYPE_PTR;
+}
+
+/*int ttype::getnumparamvalues() {
+ return numparamvalues;
+}
+
+AElementexpr * ttype::getparamvalues(int i) {
+ return paramvalues[i];
+ }*/
+
+char * ttype::getname() {
+ return type;
+}
+
+/*tparam::tparam(ttype *t,char * n) {
+ type=t;name=n;
+ }
+ char * tparam::getname() {
+ return name;
+ }
+*/
+tlabel::tlabel(tfield *f, char *fld,AElementexpr *a) {
+ index=a;
+ field=fld;
+ specifictype=f;
+}
+
+char *tlabel::getfield() {
+ return field;
+}
+
+AElementexpr * tlabel::getindex() {
+ return index;
+}
+
+tfield::tfield(ttype *tt, char *n) {
+ type=tt;name=n;
+}
+
+ttype * tfield::gettype() {
+ return type;
+}
+
+char * tfield::getname() {
+ return name;
+}
--- /dev/null
+// stores the structure definitions
+#ifndef TMODEL_H
+#define TMODEL_H
+
+#include "classlist.h"
+
+#define STYPE_STRUCT 1
+#define STYPE_INT 2
+#define STYPE_BIT 3
+#define STYPE_BYTE 4
+#define STYPE_SHORT 5
+#define STYPE_ARRAY 0x100
+
+
+class structure {
+ public:
+ structure(char *nam);
+ void settype(int t);
+ // void setparams(tparam **tp,int n);
+ void setsubtype(ttype *sub);
+ ttype * getsubtype();
+ void setfields(tfield **fieldarray, int n);
+ void setlabels(tlabel **lab,int n);
+ /* int getnumparams();
+ tparam * getparam(int i);*/
+ int getnumlabels();
+ tlabel * getlabel(int i);
+ int getnumfields();
+ tfield * getfield(int i);
+ char * getname();
+ void print();
+ int getsize(bitreader *br,model *m, Hashtable *env);
+
+ private:
+ int type;
+ char *name;
+ /* tparam ** params;
+ int numparams;*/
+ ttype *subtype;
+ tfield ** fields;
+ int numfields;
+ tlabel ** labels;
+ int numlabels;
+};
+
+#define pointersize 4
+#define intsize 4
+#define shortsize 2
+
+#define TTYPE_STRUCT 0x1
+#define TTYPE_INT 0x2
+#define TTYPE_BIT 0x3
+#define TTYPE_BYTE 0x4
+#define TTYPE_SHORT 0x5
+#define TTYPE_PTR 0x100
+
+
+
+class ttype {
+ public:
+ void print();
+ ttype(int typ);
+ ttype(char *t);
+ ttype(char *t, AElementexpr *size);
+ ttype(int type, AElementexpr * size);
+ void makeptr();
+ void setsize(AElementexpr *size);
+ AElementexpr * getsize();
+ int getbytes(bitreader *br,model *m,Hashtable *env);
+
+ bool isptr();
+ int numderef();
+ int gettype();
+ int basesize(bitreader *br,model *m,Hashtable *env);
+ /* int getnumparamvalues();
+ AElementexpr * getparamvalues(int i);*/
+ char * getname();
+
+ private:
+ int primtype;
+ int intlength; /*for variable length integers*/
+ char * type;
+ /* AElementexpr ** paramvalues;
+ int numparamvalues;*/
+ AElementexpr * asize;
+};
+
+/*class tparam {
+ public:
+ void print();
+ tparam(ttype *t,char * n);
+ char * getname();
+
+ private:
+ ttype *type;
+ char *name;
+ };*/
+
+
+
+class tlabel {
+ public:
+ void print();
+ tlabel(tfield *f, char *fld,AElementexpr *a);
+ char * getname();
+ ttype * gettype();
+ char *getfield();
+ AElementexpr * getindex();
+
+ private:
+ char *field;
+ AElementexpr *index;
+ tfield * specifictype;
+};
+
+class tfield {
+ public:
+ tfield(ttype *tt, char *n);
+ void print();
+ ttype * gettype();
+ char * getname();
+
+ private:
+ char *name;
+ ttype *type;
+ bool reserved;
+};
+#endif
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "common.h"
+#include "token.h"
+
+
+// class Token
+
+Token::Token(char *s, int tt) {
+ str=s;
+ token_type=tt;
+}
+
+Token::Token(const Token & t) {
+ token_type=t.token_type;
+ str=copystr(t.str);
+}
+
+Token::Token() {
+ token_type=-1;
+ str=NULL;
+}
+
+
+Token& Token::operator=(const Token &right) {
+ if (&right != this) {
+ token_type=right.token_type;
+ if (str!=NULL)
+ delete[](str);
+ str=copystr(right.str);
+ }
+ return *this;
+}
+
+
+Token::~Token() {
+ if (str!=NULL)
+ delete[](str);
+}
+
+
+
+
+// class Reader
+
+Reader::Reader(istream * is) {
+ readerin=is;
+ pos=0;
+}
+
+
+Token Reader::peakahead() {
+ Token t=checktoken();
+ if (t.token_type!=-1) {
+ return t;
+ }
+ while(true) {
+ int nextchar=readerin->get();
+ switch(nextchar) {
+ case ' ':
+ break;
+ case '\t':
+ break;
+ case '/':
+ if (readerin->peek()=='*') {
+ /*have comment region */
+ readerin->get();
+ int state=0;
+ for(int ch=readerin->get();ch!=EOF&&state!=2;ch=readerin->get()) {
+ switch(ch) {
+ case '*':
+ state=1;
+ break;
+ case '/':
+ if (state==1)
+ state=2;
+ break;
+ default:
+ state=0;
+ }
+ }
+ if (state!=2) error();
+ break;
+ }
+ default:
+ buf[pos++]=nextchar;
+ Token t=checktoken();
+ if (t.token_type!=-1)
+ return t;
+ }
+ }
+}
+
+
+Token Reader::readnext() {
+ Token t=peakahead();
+ pos=0;
+ return t;
+}
+
+Token Reader::checktoken() {
+ buf[pos]=0;
+ if (pos==0) return Token();
+ switch(buf[0]) {
+ case '[':
+ return Token(copystr(buf),TOKEN_OPENBRACK);
+ case ']':
+ return Token(copystr(buf),TOKEN_CLOSEBRACK);
+ case '{':
+ return Token(copystr(buf),TOKEN_OPENBRACE);
+ case '}':
+ return Token(copystr(buf),TOKEN_CLOSEBRACE);
+ case '(':
+ return Token(copystr(buf),TOKEN_OPENPAREN);
+ case ')':
+ return Token(copystr(buf),TOKEN_CLOSEPAREN);
+ case ',':
+ return Token(copystr(buf),TOKEN_COMMA);
+ case ';':
+ return Token(copystr(buf),TOKEN_SEMI);
+ case ':':
+ return Token(copystr(buf),TOKEN_COLON);
+ case '=':
+ if (pos==1) {
+ if (readerin->peek()!='>')
+ return Token(copystr(buf),TOKEN_EQUALS);
+ } else
+ return Token(copystr(buf),TOKEN_IMPLIES);
+ break;
+ case '<':
+ if (pos==1) {
+ if (readerin->peek()!='=')
+ return Token(copystr(buf),TOKEN_LT);
+ } else
+ return Token(copystr(buf),TOKEN_LTE);
+ break;
+ case '>':
+ if (pos==1) {
+ if (readerin->peek()!='=')
+ return Token(copystr(buf),TOKEN_GT);
+ } else
+ return Token(copystr(buf),TOKEN_GTE);
+ break;
+ case '.':
+ if (pos==1) {
+ if (readerin->peek()!='~')
+ return Token(copystr(buf),TOKEN_DOT);
+ } else
+ return Token(copystr(buf),TOKEN_DOTINV);
+ break;
+ case '|':
+ return Token(copystr(buf),TOKEN_BAR);
+ case '!':
+ return Token(copystr(buf),TOKEN_NOT);
+ case '-':
+ if (pos==1) {
+ if (readerin->peek()!='>')
+ return Token(copystr(buf),TOKEN_SUB);
+ } else
+ return Token(copystr(buf),TOKEN_ARROW);
+ break;
+ case '+':
+ return Token(copystr(buf),TOKEN_ADD);
+ case '*':
+ return Token(copystr(buf),TOKEN_MULT);
+ case '/':
+ return Token(copystr(buf),TOKEN_DIV);
+ case '\n':
+ return Token(copystr(buf),TOKEN_EOL);
+ case EOF:
+ return Token(copystr(buf),TOKEN_EOF);
+ default:
+ if(breakchar(readerin->peek())) {
+ /*we've got token*/
+ if (strcmp(buf,"in")==0)
+ return Token(copystr(buf),TOKEN_IN);
+ if (strcmp(buf,"isvalid")==0)
+ return Token(copystr(buf),TOKEN_ISVALID);
+ if (strcmp(buf,"and")==0)
+ return Token(copystr(buf),TOKEN_AND);
+ if (strcmp(buf,"or")==0)
+ return Token(copystr(buf),TOKEN_OR);
+ if (strcmp(buf,"crash")==0)
+ return Token(copystr(buf),TOKEN_CRASH);
+ if (strcmp(buf,"cast")==0)
+ return Token(copystr(buf),TOKEN_CAST);
+ if (strcmp(buf,"NULL")==0)
+ return Token(copystr(buf),TOKEN_NULL);
+ if (strcmp(buf,"partition")==0)
+ return Token(copystr(buf),TOKEN_PARTITION);
+ if (strcmp(buf,"many")==0)
+ return Token(copystr(buf),TOKEN_MANY);
+ if (strcmp(buf,"set")==0)
+ return Token(copystr(buf),TOKEN_SET);
+ if (strcmp(buf,"structure")==0)
+ return Token(copystr(buf),TOKEN_STRUCTURE);
+ if (strcmp(buf,"reserved")==0)
+ return Token(copystr(buf),TOKEN_RESERVED);
+ if (strcmp(buf,"label")==0)
+ return Token(copystr(buf),TOKEN_LABEL);
+ if (strcmp(buf,"int")==0)
+ return Token(copystr(buf),TOKEN_INT);
+ if (strcmp(buf,"short")==0)
+ return Token(copystr(buf),TOKEN_SHORT);
+ if (strcmp(buf,"bit")==0)
+ return Token(copystr(buf),TOKEN_BIT);
+ if (strcmp(buf,"byte")==0)
+ return Token(copystr(buf),TOKEN_BYTE);
+ if (strcmp(buf,"subtype")==0)
+ return Token(copystr(buf),TOKEN_SUBTYPE);
+ if (strcmp(buf,"of")==0)
+ return Token(copystr(buf),TOKEN_OF);
+ if (strcmp(buf,"element")==0)
+ return Token(copystr(buf),TOKEN_ELEMENT);
+ if (strcmp(buf,"forall")==0)
+ return Token(copystr(buf),TOKEN_FORALL);
+ if (strcmp(buf,"for")==0)
+ return Token(copystr(buf),TOKEN_FOR);
+ if (strcmp(buf,"sizeof")==0)
+ return Token(copystr(buf),TOKEN_SIZEOF);
+ if (strcmp(buf,"literal")==0)
+ return Token(copystr(buf),TOKEN_LITERAL);
+ if (strcmp(buf,"param")==0)
+ return Token(copystr(buf),TOKEN_PARAM);
+ if (strcmp(buf,"1")==0)
+ return Token(copystr(buf),TOKEN_ONE);
+ if (strcmp(buf,"true")==0)
+ return Token(copystr(buf),TOKEN_TRUE);
+ if (strcmp(buf,"to")==0)
+ return Token(copystr(buf),TOKEN_TO);
+ if (strcmp(buf,"delay")==0)
+ return Token(copystr(buf),TOKEN_DELAY);
+ if (strcmp(buf,"static")==0)
+ return Token(copystr(buf),TOKEN_STATIC);
+ return Token(copystr(buf),0);
+ }
+ }
+ return Token();
+}
+
+
+// return true if the given char is a separator
+bool Reader::breakchar(int chr) {
+ switch(chr) {
+ case ' ':
+ return true;
+ case '|':
+ return true;
+ case '-':
+ return true;
+ case '+':
+ return true;
+ case '*':
+ return true;
+ case '/':
+ return true;
+ case ']':
+ return true;
+ case ')':
+ return true;
+ case ';':
+ return true;
+ case ':':
+ return true;
+ case '}':
+ return true;
+ case '[':
+ return true;
+ case '(':
+ return true;
+ case '{':
+ return true;
+ case '<':
+ return true;
+ case '=':
+ return true;
+ case '\n':
+ return true;
+ case '>':
+ return true;
+ case '.':
+ return true;
+ case ',':
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+
+void Reader::error() {
+ printf("%s\n",buf);
+}
+
+
+
+void tokenname(int t) {
+ switch(t) {
+ case TOKEN_OPENBRACK:
+ printf("[");
+ break;
+ case TOKEN_CLOSEBRACK:
+ printf("]");
+ break;
+ case TOKEN_FORALL:
+ printf("forall");
+ break;
+ case TOKEN_IN:
+ printf("in");
+ break;
+ case TOKEN_OPENBRACE:
+ printf("{");
+ break;
+ case TOKEN_CLOSEBRACE:
+ printf("}");
+ break;
+ case TOKEN_COMMA:
+ printf(",");
+ break;
+ case TOKEN_SIZEOF:
+ printf("sizeof");
+ break;
+ case TOKEN_OPENPAREN:
+ printf("(");
+ break;
+ case TOKEN_CLOSEPAREN:
+ printf(")");
+ break;
+ case TOKEN_LT:
+ printf("<");
+ break;
+ case TOKEN_LTE:
+ printf("<=");
+ break;
+ case TOKEN_EQUALS:
+ printf("=");
+ break;
+ case TOKEN_GTE:
+ printf(">=");
+ break;
+ case TOKEN_GT:
+ printf(">");
+ break;
+ case TOKEN_ONE:
+ printf("1");
+ break;
+ case TOKEN_DOT:
+ printf(".");
+ break;
+ case TOKEN_DOTINV:
+ printf(".~");
+ break;
+ case TOKEN_NOT:
+ printf("!");
+ break;
+ case TOKEN_LITERAL:
+ printf("literal");
+ break;
+ case TOKEN_PARAM:
+ printf("param");
+ break;
+ case TOKEN_SUB:
+ printf("-");
+ break;
+ case TOKEN_ADD:
+ printf("+");
+ break;
+ case TOKEN_MULT:
+ printf("*");
+ break;
+ case TOKEN_AND:
+ printf("and");
+ break;
+ case TOKEN_OR:
+ printf("or");
+ break;
+ case TOKEN_EOL:
+ printf("EOL");
+ break;
+ case TOKEN_EOF:
+ printf("EOF");
+ break;
+ case TOKEN_IMPLIES:
+ printf("=>");
+ break;
+ case TOKEN_TRUE:
+ printf("true");
+ break;
+ case TOKEN_FOR:
+ printf("for");
+ break;
+ case TOKEN_TO:
+ printf("to");
+ break;
+ case TOKEN_STRUCTURE:
+ printf("structure");
+ break;
+ case TOKEN_RESERVED:
+ printf("reserved");
+ break;
+ case TOKEN_LABEL:
+ printf("label");
+ break;
+ case TOKEN_INT:
+ printf("int");
+ break;
+ case TOKEN_BIT:
+ printf("bit");
+ break;
+ case TOKEN_BYTE:
+ printf("byte");
+ break;
+ case TOKEN_SUBTYPE:
+ printf("subtype");
+ break;
+ case TOKEN_OF:
+ printf("of");
+ break;
+ case TOKEN_SEMI:
+ printf(";");
+ break;
+ case TOKEN_COLON:
+ printf(":");
+ break;
+ case TOKEN_SET:
+ printf("set");
+ break;
+ case TOKEN_ARROW:
+ printf("->");
+ break;
+ case TOKEN_MANY:
+ printf("many");
+ break;
+ case TOKEN_BAR:
+ printf("|");
+ break;
+ case TOKEN_PARTITION:
+ printf("partition");
+ break;
+ case TOKEN_ELEMENT:
+ printf("element");
+ break;
+ default:
+ printf("undefined token");
+ }
+}
--- /dev/null
+#ifndef Token_H
+#define Token_H
+
+#include "common.h"
+#include <iostream.h>
+#include <stdio.h>
+#include "classlist.h"
+
+class Token {
+ public:
+ Token(char *s, int tt);
+ Token(const Token & t);
+ Token & operator=(const Token &right);
+ Token();
+ ~Token();
+ int token_type;
+ char* str;
+
+ private:
+};
+void tokenname(int t);
+
+#define TOKEN_OPENBRACK 1
+#define TOKEN_CLOSEBRACK 2
+#define TOKEN_FORALL 3
+#define TOKEN_IN 4
+#define TOKEN_OPENBRACE 5
+#define TOKEN_CLOSEBRACE 6
+#define TOKEN_COMMA 7
+#define TOKEN_SIZEOF 8
+#define TOKEN_OPENPAREN 9
+#define TOKEN_CLOSEPAREN 10
+#define TOKEN_LT 11
+#define TOKEN_LTE 12
+#define TOKEN_EQUALS 13
+#define TOKEN_GTE 14
+#define TOKEN_GT 15
+#define TOKEN_ONE 16
+#define TOKEN_DOT 17
+#define TOKEN_DOTINV 18
+#define TOKEN_NOT 19
+#define TOKEN_LITERAL 20
+#define TOKEN_PARAM 21
+#define TOKEN_SUB 22
+#define TOKEN_ADD 23
+#define TOKEN_MULT 24
+#define TOKEN_AND 25
+#define TOKEN_OR 26
+#define TOKEN_EOL 27
+#define TOKEN_EOF 28
+#define TOKEN_IMPLIES 29
+#define TOKEN_TRUE 30
+#define TOKEN_ISVALID 31
+#define TOKEN_FOR 32
+#define TOKEN_TO 33
+#define TOKEN_STRUCTURE 34
+#define TOKEN_RESERVED 35
+#define TOKEN_LABEL 36
+#define TOKEN_INT 37
+#define TOKEN_BIT 38
+#define TOKEN_BYTE 39
+#define TOKEN_SUBTYPE 40
+#define TOKEN_OF 41
+#define TOKEN_SEMI 42
+#define TOKEN_COLON 43
+#define TOKEN_SET 44
+#define TOKEN_ARROW 45
+#define TOKEN_MANY 46
+#define TOKEN_BAR 47
+#define TOKEN_PARTITION 48
+#define TOKEN_ELEMENT 49
+#define TOKEN_DELAY 50
+#define TOKEN_STATIC 51
+#define TOKEN_DIV 52
+#define TOKEN_CAST 53
+#define TOKEN_SHORT 54
+#define TOKEN_NULL 55
+#define TOKEN_CRASH 56
+
+
+
+class Reader{
+ public:
+ Reader(istream * is);
+ Token readnext();
+ Token peakahead();
+ void error();
+
+ private:
+ bool breakchar(int);
+ Token checktoken();
+ istream *readerin;
+ char buf[200];
+ int pos;
+};
+
+#endif
--- /dev/null
+#include <stdlib.h>
+#include "typeparser.h"
+#include "list.h"
+#include "common.h"
+#include "token.h"
+#include "tmodel.h"
+#include "amodel.h"
+#include "omodel.h"
+
+Typeparser::Typeparser(Reader *r) {
+ reader=r;
+}
+
+structure * Typeparser::parsestructure() {
+ Token t=reader->peakahead();
+ while(true) {
+ if (t.token_type==TOKEN_EOF)
+ return NULL;
+ if (t.token_type!=TOKEN_EOL)
+ break;
+ skiptoken();
+ t=reader->peakahead();
+ }
+ needtoken(TOKEN_STRUCTURE);
+ Token typenam=reader->readnext();
+ structure *pstructure=new structure(copystr(typenam.str));
+ /* needtoken(TOKEN_OPENPAREN);
+ bool continueparse=true;
+ List *list=new List();
+ while(continueparse) {
+ Token t=reader->readnext();
+ switch(t.token_type) {
+ case TOKEN_CLOSEPAREN:
+ continueparse=false;
+ break;
+ case TOKEN_INT:
+ {
+ Token name=reader->readnext();
+ tparam * tpar=new tparam(new ttype(TTYPE_INT),copystr(name.str));
+ list->addobject(tpar);
+ commaorcloseparen();
+ break;
+ }
+ case TOKEN_BIT:
+ {
+ Token name=reader->readnext();
+ tparam * tpar=new tparam(new ttype(TTYPE_BIT),copystr(name.str));
+ list->addobject(tpar);
+ commaorcloseparen();
+ break;
+ }
+ case TOKEN_BYTE:
+ {
+ Token name=reader->readnext();
+ tparam * tpar=new tparam(new ttype(TTYPE_BYTE),copystr(name.str));
+ list->addobject(tpar);
+ commaorcloseparen();
+ break;
+ }
+ default:
+ {
+ Token name=reader->readnext();
+ tparam *tpar=new tparam(new ttype(copystr(typenam.str)),copystr(name.str));
+ list->addobject(tpar);
+ commaorcloseparen();
+ break;
+ }
+ }
+ }
+ tparam **tp=new tparam*[list->size()];
+ list->toArray((void**) tp);
+ pstructure->setparams(tp,list->size());
+ delete(list);*/
+
+ Token t2=reader->peakahead();
+ if (t2.token_type==TOKEN_SUBTYPE) {
+ skiptoken();
+ needtoken(TOKEN_OF);
+ pstructure->setsubtype(parsettype());
+ }
+
+ List *list=new List();
+ List *labellist=new List();
+ needtoken(TOKEN_OPENBRACE);
+ while(true) {
+ while (reader->peakahead().token_type==TOKEN_EOL)
+ skiptoken();
+ Token t=reader->peakahead();
+ if (t.token_type==TOKEN_CLOSEBRACE)
+ break;
+ if (t.token_type==TOKEN_LABEL) {
+ labellist->addobject(parsetlabel());
+ } else
+ list->addobject(parsetfield());
+ }
+ tfield **tarray=new tfield*[list->size()];
+ tlabel **larray=new tlabel*[labellist->size()];
+ list->toArray((void **)tarray);
+ labellist->toArray((void**)larray);
+ pstructure->setfields(tarray,list->size());
+ pstructure->setlabels(larray,labellist->size());
+ needtoken(TOKEN_CLOSEBRACE);
+ delete(list);
+ delete(labellist);
+ return pstructure;
+}
+
+tlabel * Typeparser::parsetlabel() {
+ needtoken(TOKEN_LABEL);
+ Token fieldname=reader->readnext();
+ AElementexpr *index=NULL;
+ if (reader->peakahead().token_type==TOKEN_OPENBRACK) {
+ skiptoken();
+ index=parseaelementexpr(true);
+ needtoken(TOKEN_CLOSEBRACK);
+ }
+ needtoken(TOKEN_COLON);
+ tfield *tf=parsetfield();
+ return new tlabel(tf,copystr(fieldname.str),index);
+}
+
+tfield * Typeparser::parsetfield() {
+ static int rcount=0;
+ Token t=reader->peakahead();
+ bool reserved=false;
+ if (t.token_type==TOKEN_RESERVED) {
+ reserved=true;
+ skiptoken();
+ }
+ ttype *tt=parsettype();
+ while(true) {
+ Token isptr=reader->peakahead();
+ if (isptr.token_type==TOKEN_MULT) {
+ tt->makeptr();
+ skiptoken();
+ break; /*Only support direct pointers right now*/
+ } else
+ break;
+ }
+ Token fieldname;
+ if (!reserved)
+ fieldname=reader->readnext();
+ AElementexpr *size=parseindex();
+ tt->setsize(size);
+ needtoken(TOKEN_SEMI);
+ if (reserved)
+ return new tfield(tt,copystr("RESERVED"+(rcount++)));
+ else
+ return new tfield(tt,copystr(fieldname.str));
+}
+
+ttype * Typeparser::parsettype() {
+ Token name=reader->readnext();
+ switch(name.token_type) {
+ case TOKEN_BIT:
+ {
+ return new ttype(TTYPE_BIT);
+ }
+ case TOKEN_INT:
+ {
+ return new ttype(TTYPE_INT);
+ }
+ case TOKEN_SHORT:
+ {
+ return new ttype(TTYPE_SHORT);
+ }
+ case TOKEN_BYTE:
+ {
+ return new ttype(TTYPE_BYTE);
+ }
+ default:
+ {
+ /*
+ needtoken(TOKEN_OPENPAREN);
+ List *list=new List();
+ while(reader->peakahead().token_type!=TOKEN_CLOSEPAREN) {
+ list->addobject(parseaelementexpr(false));
+ commaorcloseparen();
+ }
+ skiptoken();
+ AElementexpr **earray=new AElementexpr*[list->size()];
+ list->toArray((void**)earray);*/
+ ttype *ntt=new ttype(copystr(name.str),NULL);
+ //delete(list);
+ return ntt;
+ }
+ }
+}
+
+AElementexpr * Typeparser::parseindex() {
+ Token t=reader->peakahead();
+ if (t.token_type!=TOKEN_OPENBRACK)
+ return NULL;
+ skiptoken();
+ AElementexpr * ae=parseaelementexpr(true);
+ needtoken(TOKEN_CLOSEBRACK);
+ return ae;
+}
+
+void Typeparser::commaorcloseparen() {
+ Token t=reader->peakahead();
+ if (t.token_type!=TOKEN_CLOSEPAREN)
+ needtoken(TOKEN_COMMA);
+}
+
+AElementexpr * Typeparser::parseaelementexpr(bool isstruct) {
+ AElementexpr *oldee=NULL;
+ int joinop=-1;
+ while(true) {
+ Token t=reader->peakahead();
+ switch(t.token_type) {
+ case TOKEN_LITERAL:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ needtoken(TOKEN_OPENPAREN);
+ Token literal=reader->readnext();
+ needtoken(TOKEN_CLOSEPAREN);
+ if (oldee==NULL)
+ oldee=new AElementexpr(new Literal(copystr(literal.str)));
+ else {
+ if (joinop!=-1) {
+ oldee=new AElementexpr(oldee,new AElementexpr(new Literal(copystr(literal.str))),joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+
+ case TOKEN_OPENPAREN:
+ {
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ AElementexpr *ee=parseaelementexpr(false);
+ if (oldee==NULL)
+ oldee=ee;
+ else {
+ if (joinop!=-1) {
+ oldee=new AElementexpr(oldee,ee,joinop);
+ joinop=-1;
+ } else error();
+ }
+ break;
+ }
+ case TOKEN_CLOSEBRACK:
+ if (isstruct)
+ return oldee;
+ case TOKEN_CLOSEPAREN:
+ skiptoken();
+ return checkdot(oldee);
+ break;
+ case TOKEN_SUB:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=AELEMENTEXPR_SUB;
+ else
+ error();
+ break;
+ case TOKEN_ADD:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=AELEMENTEXPR_ADD;
+ else
+ error();
+ break;
+ case TOKEN_MULT:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=AELEMENTEXPR_MULT;
+ else
+ error();
+ break;
+ case TOKEN_DIV:
+ skiptoken();
+ if ((oldee!=NULL)&&(joinop==-1))
+ joinop=AELEMENTEXPR_DIV;
+ else
+ error();
+ break;
+ default:
+ if ((joinop==-1)&&(oldee!=NULL))
+ return oldee;
+ skiptoken();
+ if (oldee==NULL)
+ oldee=checkdot(new AElementexpr(new Label(copystr(t.str))));
+ else {
+ if (joinop!=-1) {
+ oldee=new AElementexpr(oldee,checkdot(new AElementexpr(new Label(copystr(t.str)))),joinop);
+ joinop=-1;
+ } else error();
+ }
+ }
+ }
+}
+
+AElementexpr * Typeparser::checkdot(AElementexpr * incoming) {
+ Token tdot=reader->peakahead();
+ if (tdot.token_type!=TOKEN_DOT) return incoming;
+ skiptoken();
+ Token tfield=reader->readnext();
+ Token tpeak=reader->peakahead();
+ if (tpeak.token_type==TOKEN_OPENBRACK) {
+ skiptoken();
+ AElementexpr *index=parseaelementexpr(false);
+ return checkdot(new AElementexpr(incoming, new Field(copystr(tfield.str)),index));
+ } else {
+ return checkdot(new AElementexpr(incoming, new Field(copystr(tfield.str))));
+ }
+}
+
+void Typeparser::error() {
+ printf("ERROR\n");
+ reader->error();
+ exit(-1);
+}
+
+void Typeparser::skiptoken() {
+ reader->readnext();
+}
+
+void Typeparser::needtoken(int token) {
+ Token t=reader->readnext();
+ if (!(t.token_type==token)) {
+ printf("Needed token: ");
+ tokenname(token);
+ printf("\n Got token: %s ",t.str);
+ tokenname(t.token_type);
+ error();
+ }
+}
--- /dev/null
+#ifndef TYPEPARSER_H
+#define TYPEPARSER_H
+
+#include "common.h"
+#include <iostream.h>
+#include <stdio.h>
+#include "classlist.h"
+
+
+// This class defines a parser for the structure definitions
+
+class Typeparser {
+ public:
+ Typeparser(Reader *r);
+ structure * parsestructure();
+ private:
+ void commaorcloseparen();
+ AElementexpr *checkdot(AElementexpr* incoming);
+ AElementexpr *parseaelementexpr(bool);
+ tlabel * parsetlabel();
+ tfield * parsetfield();
+ ttype * parsettype();
+ AElementexpr * parseindex();
+ Reader *reader;
+ void skiptoken();
+ void needtoken(int);
+ void error();
+};
+#endif