Index: libabac/abac_pl_yap.c
===================================================================
--- libabac/abac_pl_yap.c	(revision 5d1b6dcc3aa9073e56f03f5fe64fcd509c5d488c)
+++ libabac/abac_pl_yap.c	(revision 646e57eb457a4e25ff3eb78027c0373b858bdbca)
@@ -31,13 +31,40 @@
 static char *constraint_label="isABAC_constraint";
 
+/*
+x    can pLadybug buy_rockets from pAcme ? (_arg_for_fact)
+x    can pLadybug What from pAcme ? (_arg_for_what)
+x    Who can buy_rockets from pAcme ? (_arg_for_who)
+x    can pLadybug buy_rockets from Whom ? (_arg_for_whom)
+x    can pLadybug What from Whom ? (_arg_for_what_whom)
+the type ordering also dictates the order of partial proof query
+sequence
+*/
+enum _query_type_t {
+   e_PL_FACT=0,
+   e_PL_WHAT=1,
+   e_PL_WHAT_DFLT=2,
+   e_PL_WHO=3,   
+   e_PL_WHOM=4,
+   e_PL_WHAT_WHOM=5,
+   e_PL_NOMORE=6
+};
+
 // pl -- place holder for now 
 struct _abac_pl_t {
    /* a_term <- prin */
-    char *aspect_term;
-    char *prin_term;
+    char *whom;
+    char *who;
+    char *aspect;
+    char *what;
+    char *whatwith;
+    int pcnt; /* pcnt=number of params in whatwith */
+
     int query_made; /* 1+ yes, 0 no, rc is valid only if a query is made */
     int query_rc; /* rc of query call */
     int next_rc; /* rc of next-last query */
       /* proof count = abac_list_size(proof_list) */
+    int is_partial;
+    int want_partial;
+    int query_type;
     abac_list_t *proof_list; /* list of list of cred_list */ 
     long safe_t; /* holding the YAP slot for the goal */
@@ -137,10 +164,17 @@
   
     abac_pl_t *pl = abac_xmalloc(sizeof(abac_pl_t));
-    pl->aspect_term=NULL;
-    pl->prin_term=NULL;
+
+    pl->who=NULL;
+    pl->whom = NULL;
+    pl->what = NULL;
+    pl->whatwith = NULL;
+    pl->aspect = NULL;
+    pl->pcnt=0;
     pl->query_made=0;
     pl->query_rc=0;
+    pl->is_partial=0;
+    pl->want_partial=1;
+    pl->query_type=e_PL_FACT;
     pl->next_rc=0;
-      /* proof count = abac_list_size(proof_list) */
     pl->proof_list=NULL;
     pl->safe_t=0;
@@ -148,4 +182,9 @@
 }
 
+int abac_pl_returning_partial(abac_pl_t *pl)
+{
+    return pl->is_partial;
+}
+
 /* returns the number of solution so far */
 int abac_pl_proof_cnt(abac_pl_t *pl)
@@ -154,4 +193,9 @@
         return abac_list_size(pl->proof_list);
     return 0;
+}
+
+int abac_pl_is_partial(abac_pl_t *pl)
+{
+    return pl->is_partial;
 }
 
@@ -167,4 +211,14 @@
     }
     return 0;
+}
+
+void abac_pl_set_no_partial(abac_pl_t *pl)
+{
+   pl->want_partial=0;
+}
+
+void abac_pl_set_want_partial(abac_pl_t *pl)
+{
+   pl->want_partial=1;
 }
 
@@ -197,6 +251,9 @@
 
 void abac_pl_free(abac_pl_t *pl) {
-    if(pl->aspect_term) free(pl->aspect_term);
-    if(pl->prin_term) free(pl->prin_term);
+    if(pl->who) free(pl->who);
+    if(pl->whom) free(pl->whom);
+    if(pl->what) free(pl->what);
+    if(pl->whatwith) free(pl->whatwith);
+    if(pl->aspect) free(pl->aspect);
     _free_pf_list(pl->proof_list);
     free(pl);
@@ -204,5 +261,6 @@
 
 /* this is done whenever a new query starts in */
-static void _reset_pl(abac_pl_t *pl, char *aspect_term, char *prin_term)
+static void _reset_pl(abac_pl_t *pl, char *who,
+char *what, char *whom, char *aspect, char *whatwith, int pcnt)
 {
     if(pl->safe_t) {
@@ -211,15 +269,26 @@
     }
     /* free the old ones */
-    if(pl->aspect_term) free(pl->aspect_term);
-    if(pl->prin_term) free(pl->prin_term);
-    pl->aspect_term = abac_xstrdup(aspect_term);
-    pl->prin_term = abac_xstrdup(prin_term);
+    if(pl->who) free(pl->who);
+    if(pl->whom) free(pl->whom);
+    if(pl->what) free(pl->what);
+    if(pl->whatwith) free(pl->whatwith);
+    if(pl->aspect) free(pl->aspect);
+
+    pl->who = (who !=NULL)?abac_xstrdup(who):NULL;
+    pl->whom = (whom !=NULL)?abac_xstrdup(whom):NULL;
+    pl->what = (what!=NULL)?abac_xstrdup(what):NULL;
+    pl->whatwith = (whatwith!=NULL)?abac_xstrdup(whatwith):NULL;
+    pl->aspect = (aspect!=NULL)?abac_xstrdup(aspect):NULL;
+
+    pl->pcnt=pcnt;
+
     pl->query_made=0;
     pl->query_rc=0;
     pl->next_rc=0;
+    pl->is_partial=0;
+    pl->query_type=e_PL_FACT;
     _free_pf_list(pl->proof_list);
     pl->proof_list=abac_list_new();
     pl->safe_t=0;
-    
 }
 
@@ -354,29 +423,7 @@
 }
 
-/* make a query and extract just first set of result */
-static abac_list_t *_make_yap_query(abac_pl_t *pl, char *prin, char *nm, char* estring)
-{
-    YAP_Term eterm0;
-    YAP_Term eterm1;
-    YAP_Term arg[3];
-
-    abac_list_t *cred_list = abac_list_new();
-
-    if(debug) { 
-       fprintf(stderr," the principal part(%s)\n", prin);
-       fprintf(stderr," the role/oset part(%s)\n", estring);
-       fprintf(stderr," nm part(%s)\n", nm);
-    } 
-    if(prin[0]=='\'' || prin[0]=='"') {
-        arg[0]=YAP_ReadBuffer(prin,&eterm0);
-        } else {
-            arg[0]=YAP_MkAtomTerm(YAP_LookupAtom(prin)); 
-    }
-    if(debug) fprintf(stderr," the role/oset part(%s)\n", estring);
-    arg[1]=YAP_ReadBuffer(estring,&eterm1);
-
-    /* var for credential list */
-    arg[2]=YAP_MkVarTerm();
-
+abac_list_t *run_goal(abac_pl_t *pl, YAP_Term *arg)
+{
+    abac_list_t *cred_list=abac_list_new();
     YAP_Atom f = YAP_LookupAtom("isMember");
     YAP_Functor func = YAP_MkFunctor(f, 3);
@@ -388,5 +435,7 @@
     pl->next_rc=pl->query_rc;
     if (pl->query_rc) {
-        printf("YAP query succeed\n");
+        if(pl->is_partial) 
+            printf("A partial proof(type:%d)\n",pl->query_type);
+            else printf("YAP query succeed\n");
         char *tmp=NULL;
         int tmp_sz=try_again(0, &tmp);
@@ -421,8 +470,251 @@
         YAP_FreeSpaceFromYap(tmp);
     } else {
-        printf("YAP query failed\n");
-        /* YAP_Exit(1); */
+        /* don't print anything if it is running a parital proof goal */
+        if(!pl->is_partial) 
+            printf("YAP query failed\n");
+  
     }
     return cred_list;
+}
+
+/*************************************************************************/
+YAP_Term _make_term(char *term) {
+    YAP_Term eterm;
+    YAP_Term ret;
+    if(term[0]=='\'' || term[0]=='"') {
+        ret =YAP_ReadBuffer(term,&eterm);
+        } else {
+            ret = YAP_MkAtomTerm(YAP_LookupAtom(term));
+    }
+}
+
+// isMember(who,aspect(whom,what,whatwith)) 
+/* aspect(whom, what, whatwith) */
+YAP_Term _aspect_base(char *whom,char *aspect, char *what, char *whatwith)
+{
+    YAP_Term eterm;
+    YAP_Term ret;
+
+    char *estring=NULL;
+    if(whatwith)
+       asprintf(&estring, "%s(%s,%s,%s)",aspect,whom,what,whatwith);
+       else asprintf(&estring, "%s(%s,%s)",aspect,whom,what);
+    if(debug) fprintf(stderr,"_aspect_base, doing %s\n",estring);
+    ret=YAP_ReadBuffer(estring,&eterm);
+    free(estring);
+    return ret;
+}
+
+/* generate a string of whatwith that are of ?variable */
+char *_make_whatwith_var(char *whatwith, int pcnt)
+{
+/* this is a dumb count since it is in porting directory */
+   if(whatwith==NULL || pcnt==0) return NULL;  
+   char *tmp=NULL;
+   char *ptr=NULL;
+   int i;
+   for(i=0;i<pcnt;i++) {
+       ptr=tmp;
+       tmp=NULL;
+       if(i == 0)
+           asprintf(&tmp,"Whatwith%d",i);
+           else asprintf(&tmp,"%s,Whatwith%d",ptr,i);
+   }
+   return tmp;
+}
+
+/* aspect(X, Y, Whatwith) */
+YAP_Term _aspect_what_whom(char *whom,char *aspect, char *what, char *whatwith)
+{
+    YAP_Term ret=_aspect_base("Whom",aspect,"What",whatwith);
+    return ret;
+}
+
+/* aspect(whom,Y,Whatwith) */
+/* call with char *tmp=_make_whatwith_var(whatwith); */
+YAP_Term _aspect_what(char *whom,char *aspect, char *what, char *whatwith)
+{
+    YAP_Term ret=_aspect_base(whom,aspect,"What",whatwith);
+    return ret;
+}
+
+/* aspect(X,what,whatwith) */
+YAP_Term _aspect_whom(char *whom,char *aspect, char *what, char *whatwith)
+{
+    YAP_Term ret=_aspect_base("Whom",aspect,what,whatwith);
+    return ret;
+}
+
+/* aspect(whom,what,whatwith) */
+YAP_Term _aspect_fact(char *whom,char *aspect, char *what, char* whatwith)
+{
+    YAP_Term ret=_aspect_base(whom,aspect,what,whatwith);
+    return ret;
+}
+
+// Whom.What <- ladybug
+// isMember(ladybug, role(W1, W2), R)
+static void _arg_for_what_whom(YAP_Term *arg,char *who, char *whom,
+char *aspect, char*what, char *whatwith, int pcnt)
+{
+    arg[0] = _make_term(who);
+    char *tmp=_make_whatwith_var(whatwith,pcnt); 
+    arg[1] = _aspect_what_whom(who,aspect,what,tmp);
+    if(tmp) free(tmp);
+    arg[2] = YAP_MkVarTerm();
+}
+
+// pAcme.What <- ladybug
+// isMember(ladybug, role(pAcme, W), R)
+static void _arg_for_what(YAP_Term *arg,char *who, char* whom, 
+char *aspect, char*what, char*whatwith, int pcnt)
+{
+    arg[0] = _make_term(who);
+    char *tmp=_make_whatwith_var(whatwith,pcnt); 
+    arg[1] = _aspect_what(whom,aspect,what,tmp);
+    if(tmp) free(tmp);
+    arg[2] = YAP_MkVarTerm();
+}
+
+// W.rocket <- ladybug
+// isMember(ladybug, role(W, buy_rockets), R)
+static void _arg_for_whom(YAP_Term *arg, char *who, char*whom,
+char *aspect, char *what, char*whatwith)
+{
+    arg[0] = _make_term(who);
+    arg[1] = _aspect_whom(whom,aspect,what,whatwith);
+    arg[2] = YAP_MkVarTerm();
+}
+
+// Acme.rocket <- V
+// isMember(V, role(pAcme, buy_rockets), R)
+static int _arg_for_who(YAP_Term *arg, char *who,char *whom, 
+char *aspect, char* what, char*whatwith)
+{
+    arg[0] = YAP_MkVarTerm();
+    arg[1] = _aspect_fact(whom, aspect, what, whatwith);
+    arg[2] = YAP_MkVarTerm();
+}
+
+// Acme.rocket <- x 
+// isMember(x, role(pAcme, buy_rockets), R)
+static void _arg_for_fact(YAP_Term *arg,char *who,char *whom, 
+char* aspect, char *what, char*whatwith)
+{
+    arg[0] = _make_term(who);
+    arg[1] = _aspect_fact(whom, aspect, what, whatwith);
+    arg[2] = YAP_MkVarTerm();
+}
+
+
+static abac_list_t *_make_partial_query(abac_pl_t *pl)
+{
+    abac_list_t *ret=abac_list_new();
+    pl->is_partial=1;
+    char *who=pl->who;
+    char *whom=pl->whom;
+    char *aspect=pl->aspect;
+    char *what=pl->what;
+    char *whatwith=pl->whatwith;
+    int pcnt=pl->pcnt;
+    if(debug) fprintf(stderr,"making make_partial_query..\n");
+
+    switch (pl->query_type) { 
+        case e_PL_FACT: /* try what */
+            {
+            YAP_Term arg[3];
+            if(debug) fprintf(stderr,"... 1st partial attempt\n");
+            pl->query_type = e_PL_WHAT;
+            _arg_for_what(arg,who,whom, aspect, what, whatwith, pcnt);
+            ret=run_goal(pl,arg);
+            if(pcnt==0) pl->query_type= e_PL_WHAT_DFLT;
+            if(pl->query_rc) return ret;
+            break;
+            }
+        case e_PL_WHAT: /* try what with no params if need to */
+            {
+            YAP_Term arg[3];
+            if(debug) fprintf(stderr,"... 2nd partial attempt\n");
+            pl->query_type = e_PL_WHAT_DFLT;
+            _arg_for_what(arg,who,whom, aspect, what, whatwith, 0);
+            ret=run_goal(pl,arg);
+            if(pl->query_rc) return ret;
+            break;
+            }
+        case e_PL_WHAT_DFLT: /* try who */
+            {
+            YAP_Term arg[3];
+            if(debug) fprintf(stderr,"... 2nd half partial attempt\n");
+            pl->query_type = e_PL_WHO;
+            _arg_for_who(arg,who,whom, aspect, what, whatwith);
+            ret=run_goal(pl,arg);
+            if(pl->query_rc) return ret;
+            break;
+            }
+        case e_PL_WHO: /* try whom */
+            {
+            YAP_Term arg[3];
+            if(debug) fprintf(stderr,"... 3rd partial attempt\n");
+            pl->query_type = e_PL_WHOM;
+            _arg_for_whom(arg,who,whom, aspect, what, whatwith);
+            ret=run_goal(pl,arg);
+            if(pl->query_rc) return ret;
+            break;
+            }
+        case e_PL_WHOM: /* try what-whom */
+            {
+            YAP_Term arg[3];
+            if(debug) fprintf(stderr,"... 4th partial attempt\n");
+            pl->query_type = e_PL_WHAT_WHOM;
+            _arg_for_what_whom(arg,who,whom, aspect, what, whatwith,pcnt);
+            ret=run_goal(pl,arg);
+            if(pl->query_rc) return ret;
+            break;
+            }
+        default :
+            {
+            if(debug) fprintf(stderr,"... no more partial query to try\n");
+            pl->query_type = e_PL_NOMORE;
+            }
+    }
+    return ret;
+}
+
+/* make a query and extract just first set of result,
+   simple = rt0
+   aspect => role/oset
+   aspect_string => rest of params
+   prin => principal
+   issuer => issuer
+   estring =>  aspect(issuer, aspect_type_string) 
+*/
+static abac_list_t *_make_yap_query(abac_pl_t *pl, char *who,
+char *whom, char *aspect, char *what, char *whatwith, int pcnt)
+{
+    if(debug) { 
+       fprintf(stderr,"_make_yap_query: the who part(%s)\n", who);
+       fprintf(stderr,"_make_yap_query: whom part(%s)\n", whom);
+       fprintf(stderr,"_make_yap_query: the role/oset (%s)\n", aspect);
+       fprintf(stderr,"_make_yap_query: aspect what (%s)\n", what);
+       fprintf(stderr,"_make_yap_query: pcnt (%d)\n", pcnt);
+       if(whatwith)
+           fprintf(stderr,"_make_yap_query: aspect what part(%s)\n", whatwith);
+    } 
+    if(debug) fprintf(stderr,"making a yap query..\n");
+
+/* run query on fact goal */
+    YAP_Term arg[3];
+    _arg_for_fact(arg, who,whom, aspect, what, whatwith);
+    abac_list_t *ret=run_goal(pl,arg);
+
+/* fact query failed and so run partial query */
+    if(!pl->query_rc && pl->want_partial) {
+        while(pl->query_type != e_PL_NOMORE) {
+            abac_list_free(ret);
+            ret=_make_partial_query(pl);
+            if( pl->query_rc ) break;
+        }
+    }
+    return ret;
 }
 
@@ -432,7 +724,7 @@
     abac_list_t *cred_list=abac_list_new();
 
+    if(debug) fprintf(stderr,"making query_again call..\n");
     pl->next_rc=YAP_RestartGoal();
     pl->query_made++;
-    if(debug) fprintf(stderr,"query_again: another success\n");
 
     char *tmp=NULL;
@@ -440,4 +732,7 @@
     YAP_Term argterm=YAP_ArgOfTerm(3,YAP_GetFromSlot(pl->safe_t));
     if(pl->next_rc) {
+        if(debug) fprintf(stderr,"query_again: another success\n");
+        if(pl->is_partial)
+            printf("A partial proof(type:%d)\n",pl->query_type);
         while(1) {
             YAP_WriteBuffer(argterm, tmp, tmp_sz,YAP_WRITE_HANDLE_VARS);
@@ -459,4 +754,13 @@
         abac_list_add(pl->proof_list, cred_list);
         YAP_FreeSpaceFromYap(tmp);
+        } else {
+            if(debug) fprintf(stderr,"query_again: fail finding next\n");
+            if(pl->is_partial) { /* if there is more partial query to make */
+                while(pl->query_type != e_PL_NOMORE) {
+                    abac_list_free(cred_list);
+                    cred_list=_make_partial_query(pl);
+                    if( pl->query_rc ) break;
+                }
+            }
     }
     return cred_list;
@@ -496,13 +800,13 @@
         show_yap_db("DEBUG:calling within _query_with_aspect");
 
-    char *nm;
-    PROLOG(nm=abac_aspect_principal_name(head););
+    char *whom=NULL;
+    PROLOG(whom=abac_aspect_principal_name(head););
 
     /* could be obj or principal */
-    char *prin_nm=NULL;
+    char *who=NULL;
     if(abac_aspect_is_object(tail)) {
-        prin_nm=abac_aspect_object_name(tail);
+        who=abac_aspect_object_name(tail);
         } else {
-            PROLOG(prin_nm=abac_aspect_principal_name(tail););
+            PROLOG(who=abac_aspect_principal_name(tail););
     }
 
@@ -512,5 +816,5 @@
     }
 
-    if (prin_nm == NULL || nm == NULL) {
+    if (who == NULL || whom == NULL) {
         printf("fail, query's call got bad aspect names .. \n");
         YAP_Exit(1);
@@ -522,16 +826,20 @@
     PROLOG(pstring=abac_aspect_aspect_param_string(head););
 
-    char *stub=abac_aspect_type_string(head);
-    if(pstring) {
-        asprintf(&tmp,"%s(%s,%s,%s)", stub, nm, abac_aspect_aspect_name(head),pstring);
-        free(pstring);
-        } else {
-            asprintf(&tmp,"%s(%s,%s)", stub, nm, abac_aspect_aspect_name(head));
-    }
-
-    _reset_pl(pl,tmp,prin_nm);
-    abac_list_t *rlist=_make_yap_query(pl,prin_nm,nm,tmp);
+    char *aspect=abac_aspect_type_string(head);
+    int pcnt=abac_aspect_aspect_param_cnt(head);
+    char *what=abac_aspect_aspect_name(head);
+
+    _reset_pl(pl, who, what, whom, aspect, pstring, pcnt);
+
+    abac_list_t *rlist=NULL;
+    if(pcnt)
+        rlist=_make_yap_query(pl,who,whom,aspect,abac_aspect_aspect_name(head),pstring,pcnt);
+        else
+            rlist=_make_yap_query(pl,who,whom,aspect,abac_aspect_aspect_name(head),NULL,0);
+
     /* generate the resulting stack from a list */
     ret=_make_cred_stack(rlist);
+    if(tmp) free(tmp);
+    if(pstring) free(pstring);
     return ret;
 }
