Index: libabac/abac_pl.c
===================================================================
--- libabac/abac_pl.c	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/abac_pl.c	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,258 @@
+
+/* abac.c using prolog */
+
+#include <assert.h>
+#include <err.h>
+#include <glob.h>
+
+#include <chunk.h>
+
+#include "abac.h"
+#include "abac_pl.h"
+#include "abac_pl_yap.h"
+
+#ifdef DEBUG_IT
+#include "abac_pl_yap_dbg.h"
+#endif
+
+#include "abac_util.h"
+#include "abac_verifier.h"
+
+static int debug = 1;
+
+struct _abac_context_t {
+    abac_pl_t *pl;
+#ifdef DEBUG_IT
+/* this is just for debugging */
+    abac_pl_yap_dbg_t *dpl;
+#endif
+};
+
+/**
+ * Init the library.
+ */
+void libabac_init(void) {
+    void libabac_deinit(void);
+    static int has_been_init = 0;
+
+    // called every time a context is created, so only do it once
+    if (!has_been_init) {
+        abac_verifier_init();
+        atexit(libabac_deinit);
+        has_been_init = 1;
+    }
+}
+
+/**
+ * Deinit the library.
+ */
+void libabac_deinit(void) {
+    abac_verifier_deinit();
+}
+
+/**
+ * Create a new abac context.
+ */
+abac_context_t *abac_context_new(void) {
+    libabac_init();
+
+    abac_context_t *ctx = abac_xmalloc(sizeof(abac_context_t));
+    ctx->pl = abac_pl_new();
+#ifdef DEBUG_IT
+    if (debug) {
+        ctx->dpl = abac_pl_yap_dbg_new();
+    } else ctx->dpl = NULL;
+#endif
+    return ctx;
+}
+
+
+/**
+ * Free an abac context.
+ */
+void abac_context_free(abac_context_t *ctx) {
+    assert(ctx != NULL);
+
+    abac_pl_free(ctx->pl);
+#ifdef DEBUG_IT
+    if (ctx->dpl)
+        abac_pl_yap_dbg_free(ctx->dpl);
+#endif
+    free(ctx);
+}
+
+/**
+ * Load an ID cert from a file.
+ */
+int abac_context_load_id_file(abac_context_t *ctx, char *filename) {
+    assert(ctx != NULL); assert(filename != NULL);
+    int ret = abac_verifier_load_id_file(filename);
+    if (ret == ABAC_CERT_SUCCESS) {
+        // add into yap
+    }
+    return ret;
+}
+
+/**
+ * Load an ID cert from a chunk.
+ */
+int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert) {
+    assert(ctx != NULL);
+    chunk_t cert_chunk = { cert.ptr, cert.len };
+    return abac_verifier_load_id_chunk(cert_chunk);
+}
+
+/**
+ * Load an attribute cert from a file.
+ */
+int abac_context_load_attribute_file(abac_context_t *ctx, char *filename) {
+    int ret, add_ret;
+    abac_credential_t *cred;
+
+    assert(ctx != NULL); assert(filename != NULL);
+
+    ret = abac_verifier_load_attribute_cert_file(filename, &cred);
+    if (ret == ABAC_CERT_SUCCESS) {
+        add_ret = abac_pl_add_credential(ctx->pl, cred);
+        assert(add_ret != ABAC_PL_CRED_INVALID);
+/* MEI, XXX this is weird..
+        abac_credential_free(cred);
+**/
+    }
+
+    return ret;
+}
+
+/**
+ * Load an attribute cert from a chunk.
+ */
+int abac_context_load_attribute_chunk(abac_context_t *ctx, abac_chunk_t cert) {
+    int ret, add_ret;
+    abac_credential_t *cred;
+
+    assert(ctx != NULL);
+
+    chunk_t cert_chunk = { cert.ptr, cert.len };
+
+    ret = abac_verifier_load_attribute_cert_chunk(cert_chunk, &cred);
+    if (ret == ABAC_CERT_SUCCESS) {
+        add_ret = abac_pl_add_credential(ctx->pl, cred);
+        assert(add_ret != ABAC_PL_CRED_INVALID);
+        abac_credential_free(cred);
+    }
+
+    return ret;
+}
+
+#define ID_PAT "/*_ID.{der,pem}"
+#define ATTR_PAT "/*_attr.der"
+
+/**
+ * Load a directory full of certs.
+ */
+void abac_context_load_directory(abac_context_t *ctx, char *path) {
+    char *glob_pat;
+    glob_t glob_buf;
+    int i, ret;
+
+    assert(ctx != NULL); assert(path != NULL);
+
+    int dirlen = strlen(path);
+    glob_pat = abac_xmalloc(dirlen + sizeof(ID_PAT));
+    memcpy(glob_pat, path, dirlen);
+
+    // first load ID certs
+    memcpy(glob_pat + dirlen, ID_PAT, sizeof(ID_PAT));
+    glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error
+    for (i = 0; i < glob_buf.gl_pathc; ++i) {
+        char *cert_file = glob_buf.gl_pathv[i];
+
+        printf("--> ID cert... %s\n", cert_file);
+        ret = abac_context_load_id_file(ctx, cert_file);
+        if (ret != ABAC_CERT_SUCCESS)
+            warnx("Couldn't load ID cert %s", cert_file);
+    }
+    globfree(&glob_buf);
+
+    // then load attr certs
+    memcpy(glob_pat + dirlen, ATTR_PAT, sizeof(ATTR_PAT));
+    glob(glob_pat, 0, NULL, &glob_buf); // TODO check for error
+    for (i = 0; i < glob_buf.gl_pathc; ++i) {
+        char *cert_file = glob_buf.gl_pathv[i];
+
+        printf("--> attr cert... %s\n", cert_file);
+        ret = abac_context_load_attribute_file(ctx, cert_file);
+        if (ret != ABAC_CERT_SUCCESS)
+            warnx("Couldn't load attribute cert %s", cert_file);
+    }
+    globfree(&glob_buf);
+
+    free(glob_pat);
+}
+
+/**
+ * Run a query on the data in an abac context. Returns a NULL-terminated array
+ * of abac_credential_t. Success/failure in *success.
+ */
+abac_credential_t **abac_context_query(abac_context_t *ctx, char *role, char *principal, int *success) {
+    abac_credential_t **credentials = NULL, *cur;
+    int i = 0;
+
+    assert(ctx != NULL); assert(role != NULL); assert(principal != NULL); assert(success != NULL);
+
+    abac_list_t *result = abac_pl_query(ctx->pl, role, principal);
+
+    int size = abac_list_size(result);
+    if (size > 0)
+        *success = 1;
+
+    else {
+    // XXX NOT SURE YET..
+    // return partial proof
+    }
+
+    // make the array (leave space to NULL terminate it)
+    //      n.b., even if the list is empty, we still return an array that
+    //            only contains the NULL terminator
+    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
+    if(size) {
+        abac_list_foreach(result, cur,
+            credentials[i++] = cur;
+        );
+    }
+    credentials[i] = NULL;
+
+    abac_list_free(result);
+
+    return credentials;
+}
+
+/**
+ * A NULL-terminated array of all the credentials in the context.
+ */
+abac_credential_t **abac_context_credentials(abac_context_t *ctx) {
+    assert(ctx != NULL);
+}
+
+/**
+ * Frees a NULL-terminated list of credentials.
+ */
+void abac_context_credentials_free(abac_credential_t **credentials) {
+    int i;
+
+    if (credentials == NULL)
+        return;
+
+    for (i = 0; credentials[i] != NULL; ++i)
+        abac_credential_free(credentials[i]);
+    free(credentials);
+}
+
+#ifdef DEBUG_IT
+// for debugging only
+void abac_context_debug_run(abac_context_t *ctx) {
+    if (ctx) {
+        abac_pl_yap_dbg_run_can(ctx->dpl);
+    }
+}
+#endif
Index: libabac/abac_pl.h
===================================================================
--- libabac/abac_pl.h	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/abac_pl.h	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,81 @@
+#ifndef __ABAC_H__
+#define __ABAC_H__
+
+#include <abac_common.h>
+
+typedef struct _abac_context_t abac_context_t;
+typedef struct _abac_credential_t abac_credential_t;
+typedef struct _abac_role_t abac_role_t;
+
+/*
+ * ABAC functions, operating on an ABAC context.
+ */
+abac_context_t *abac_context_new(void);
+void abac_context_free(abac_context_t *ctx);
+
+/* see the bottom of the file for possible return codes */
+int abac_context_load_id_file(abac_context_t *ctx, char *filename);
+int abac_context_load_id_chunk(abac_context_t *ctx, abac_chunk_t cert);
+int abac_context_load_attribute_file(abac_context_t *ctx, char *filename);
+int abac_context_load_attribute_chunk(abac_context_t *ctx, abac_chunk_t cert);
+
+/* load an entire directory full of certs */
+void abac_context_load_directory(abac_context_t *ctx, char *path);
+
+/* abac query, returns a NULL-terminated array of credentials on success, NULL on fail */
+abac_credential_t **abac_context_query(abac_context_t *ctx, char *role, char *principal, int *success);
+
+/* get all the credentials from the context, returns a NULL-terminated array of credentials */
+abac_credential_t **abac_context_credentials(abac_context_t *ctx);
+
+/* use this to free the results of either of the previous two functions */
+void abac_context_credentials_free(abac_credential_t **credentials);
+
+/*
+ * Operations on credentials
+ */
+abac_role_t *abac_credential_head(abac_credential_t *cred);
+abac_role_t *abac_credential_tail(abac_credential_t *cred);
+abac_chunk_t abac_credential_attribute_cert(abac_credential_t *cred);
+abac_chunk_t abac_credential_issuer_cert(abac_credential_t *cred);
+abac_credential_t *abac_credential_lookup(char *cred_string);
+char* abac_credential_clause(abac_credential_t *cred);
+
+abac_credential_t *abac_credential_dup(abac_credential_t *cred);
+void abac_credential_free(abac_credential_t *cred);
+
+/*
+ * Operations on roles.
+ */
+abac_role_t *abac_role_principal_new(char *principal);
+abac_role_t *abac_role_role_new(char *principal, char *abac_role_name);
+abac_role_t *abac_role_linking_new(char *principal, char *linked_role, char *abac_role_name);
+
+void abac_role_free(abac_role_t *role);
+
+abac_role_t *abac_role_from_string(char *string);
+abac_role_t *abac_role_dup(abac_role_t *role);
+
+int abac_role_is_principal(abac_role_t *role);
+int abac_role_is_role(abac_role_t *role);
+int abac_role_is_linking(abac_role_t *role);
+int abac_role_is_intersection(abac_role_t *role);
+
+char *abac_role_string(abac_role_t *role);
+char *abac_role_linked_role(abac_role_t *role);
+char *abac_role_role_name(abac_role_t *role);
+char *abac_role_principal(abac_role_t *role);
+
+char *abac_role_attr_key(abac_role_t *head_role, abac_role_t *tail_role);
+
+/*
+ * Error codes for loading certificates.
+ */
+#define ABAC_CERT_SUCCESS           0   // certificate loaded, all is well
+#define ABAC_CERT_INVALID           -1  // invalid format; also file not found
+#define ABAC_CERT_BAD_SIG           -2  // invalid signature
+#define ABAC_CERT_MISSING_ISSUER    -3  // missing ID cert that issued the attribute cert
+#define ABAC_CERT_BAD_CN            -4  // ID cert is not matching CN=principal format
+#define ABAC_CERT_BAD_YAP           -5  // failed to insert into prolog engine
+
+#endif /* __ABAC_H__ */
Index: libabac/abac_pl_yap.c
===================================================================
--- libabac/abac_pl_yap.c	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/abac_pl_yap.c	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,288 @@
+
+/* copied from abac_graph.c 
+   implementation of the low level using
+   yap prolog
+*/
+
+#include <err.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <Yap/YapInterface.h>
+
+#include "abac_pl.h"
+#include "abac_pl_yap.h"
+
+#include "abac_list.h"
+#include "abac_util.h"
+
+#include "uthash.h"
+
+static int _insert_clause(char*);
+static void _show_yap_db(char*);
+
+extern char *abac_cn_with_role(abac_role_t *);
+
+// pl
+struct _abac_pl_t {
+    FILE *fptr;
+    char *fname;
+    char *yap_certs;
+};
+
+/**
+ * Create a new yap structure.
+ */
+abac_pl_t *abac_pl_new(void) {
+
+    if (YAP_FastInit(NULL) == YAP_BOOT_ERROR)
+        YAP_Exit(1);
+
+    if (YAP_RunGoal(YAP_MkAtomTerm(YAP_LookupAtom("source")))) {
+        printf("calling source..\n");
+        } else {
+        printf("calling source failed..\n");
+        YAP_Exit(1);
+    }
+    abac_pl_t *pl = abac_xmalloc(sizeof(abac_pl_t));
+    pl->fptr=NULL;
+    pl->fname=NULL;
+    pl->yap_certs=NULL;
+    return pl;
+}
+
+/**
+ * Add a credential to the credential pl.
+ */
+int abac_pl_add_credential(abac_pl_t *pl, abac_credential_t *cred)
+{
+    int rc=0;
+    char *str = abac_credential_clause(cred);
+    if (str != NULL) {
+        rc=_insert_clause(str);
+    }
+    _show_yap_db("calling within abac_pl_add_credential");
+    return rc;
+}
+
+static int _insert_clause(char *cstr)
+{
+    int ret=ABAC_CERT_SUCCESS;
+    YAP_Term *eterm;
+    YAP_Term goalArgs=YAP_ReadBuffer(cstr, eterm);
+    char *tmp=YAP_CompileClause(goalArgs);
+    if (tmp!=NULL) { /* something is wrong */
+        printf("error: result of compile clause (%s)\n", tmp);
+        ret=ABAC_CERT_BAD_YAP;
+    }
+    return ret;
+}
+
+static void _show_yap_db(char *msg)
+{
+    char lstr[]="listing";
+    YAP_Term *eterm;
+
+    YAP_Term goal=YAP_ReadBuffer(lstr, eterm);
+    printf("calling listing..from(%s) \n",msg);
+    int rc =YAP_RunGoal( goal );
+    if (rc) {
+        printf("listing ok.. \n");
+    } else {
+        printf("listing's rc is bad.. \n");
+        YAP_Exit(1);
+    }
+}
+
+static void _set_dbg(abac_pl_t *pl)
+{
+    char *fname=strdup( "/tmp/abac_yap-XXXXXX.pl" );
+    int fd = mkstemps( pl->fname, 3 );
+    if ( fd == -1) {
+        printf("Couldn't get a valid temp name %s\n", fname);
+        free((void*)fname);
+        YAP_Exit(1);
+    }
+    FILE *fptr = fdopen(fd, "w");
+    if (fptr == NULL) {
+        printf("Couldn't open %s for writing\n", fname);
+        free((void*)fname);
+        YAP_Exit(1);
+    }
+    pl->fptr=fptr;
+    pl->fname=fname;
+}
+
+static abac_list_t *_linked_query(abac_pl_t *pl, abac_role_t* role, abac_role_t* role_prin )
+{
+    abac_list_t *cred_list = abac_list_new();
+    return cred_list;
+}
+
+static abac_list_t *_intersect_query(abac_pl_t *pl, abac_role_t* role, abac_role_t* role_prin )
+{
+    abac_list_t *cred_list = abac_list_new();
+    return cred_list;
+}
+
+
+/* cases,
+     ['str']
+     ['str1','str2']
+     ([] is not possible, and don't care)
+*/
+static void _credentials_from_string(abac_list_t *credentials,char *slist) {
+    char *cptr=slist; /* current ptr */
+    char *sptr; /* string ptr */
+    char *ptr;
+    int len=strlen(ptr);
+    char *string;
+    abac_credential_t *cred=NULL;
+
+    /* find first [' */  
+    ptr=strstr(cptr,"['");
+    if(ptr == NULL) 
+         return;
+    cptr=ptr+2;
+    sptr=cptr;
+    while (1) {
+        /* find next ',' or '] */
+        ptr=strstr(cptr,"','");
+        if(ptr!=NULL) {
+             cptr=ptr+3;
+             len=ptr-sptr;
+             string=strndup(sptr,len);
+             printf("string found(%s)\n", string); 
+             cred=abac_credential_lookup(string);
+             if(cred) {
+                 abac_list_add(credentials, abac_credential_dup(cred));
+                 } else {
+                 printf("BAD BAD BAD\n");
+             }
+             sptr=cptr;
+             } else {
+             ptr=strstr(cptr,"']");
+             if(ptr!=NULL) {
+                 len=ptr-sptr;
+                 string=strndup(sptr,len);
+                 printf("last string found(%s)\n", string); 
+                 cred=abac_credential_lookup(string);
+                 if(cred) {
+                     abac_list_add(credentials, abac_credential_dup(cred));
+                     } else {
+                     printf("BAD BAD BAD\n");
+                 }
+                 break;
+             }
+        }
+    }
+}
+
+/* 2 types 
+      acme.buys_rocket <- coyote 
+      acme.buys_rocket <- acme.preferred_customer  -- NOT DONE YET */
+static abac_list_t *_query(abac_pl_t *pl, abac_role_t* role, abac_role_t* role_prin )
+{
+    YAP_Term *eterm;
+    YAP_Term arg[3];
+    char tmp[1000];
+    abac_list_t *cred_list = NULL;
+
+    char *cn_prin=abac_cn_with_role(role_prin);
+    char *cn_role=abac_cn_with_role(role);
+
+    if(abac_role_role_name(role_prin)!=NULL) {
+        printf("NOT YET DONE, role_prin is B.R !!!\n");
+        YAP_Exit(1);
+    }
+
+    if (cn_prin == NULL || cn_role == NULL) {
+        printf("fail, query's call got bad roles.. \n");
+        YAP_Exit(1);
+    }
+    sprintf(tmp,"role(%s,%s)", cn_role, abac_role_role_name(role));
+    arg[0]=YAP_MkAtomTerm(YAP_LookupAtom(cn_prin));
+    arg[1]=YAP_ReadBuffer(tmp,eterm);
+    arg[2]=YAP_MkVarTerm();
+    YAP_Atom f = YAP_LookupAtom("isMember");
+    YAP_Functor func = YAP_MkFunctor(f, 3);
+    YAP_Term goal=YAP_MkApplTerm(func, 3, arg);
+    int rc =YAP_RunGoal( goal );
+    if (rc) {
+        cred_list = abac_list_new();
+        printf("success, query call ok.. \n");
+        YAP_WriteBuffer(arg[2], tmp, 1000,YAP_WRITE_HANDLE_VARS);
+        printf("    answer : %s(%d)\n", tmp, strlen(tmp));
+        /* this is returned as ['string1','string2'] */
+        _credentials_from_string(cred_list,tmp); 
+        while (YAP_RestartGoal()) {
+            printf("another success\n");
+            YAP_WriteBuffer(arg[2], tmp, 1000,YAP_WRITE_HANDLE_VARS);
+            printf("    answer : %s\n", tmp);
+            _credentials_from_string(cred_list,tmp); 
+        }
+    } else {
+        printf("fail, query's call is bad.. \n");
+        YAP_Exit(1);
+    }
+    return cred_list;
+}
+
+/**
+ * Make a query into prolog db
+--role acme.preferred_customer --principal coyote
+--role acme.prefer_customer.buy_rockets --principlal coyote
+ */
+abac_list_t *abac_pl_query(abac_pl_t *pl, char *role_name, char *principal)
+{
+    abac_role_t *role = abac_role_from_string(role_name);
+    abac_role_t *prin_role = abac_role_from_string(principal);
+    char *query_clause = NULL;
+    abac_list_t *ret=NULL;
+
+    // give up on bogus roles
+    if (role == NULL || prin_role == NULL) {
+        free(role);
+        free(prin_role);
+        return NULL;
+    }
+
+    /* should be using yacc */
+/* if role->prereqs != NULL (&) */
+    if (abac_role_is_intersection(role)) {
+/* XXX */
+        ret=_intersect_query(pl,role,prin_role);
+    /* prin.role.role1 */
+    } else if( abac_role_linked_role(role) ) {
+/* XXX */
+        ret=_linked_query(pl,role,prin_role);
+    } else {  /* prin.role,  */
+        ret=_query(pl,role,prin_role);
+    }
+
+    return ret;
+}
+
+/**
+ * Get all the credentials (attribute/issuer cert pairs) from prolog
+ * (which returns in string form)
+ */
+abac_list_t *abac_pl_credentials(abac_pl_t *pl) {
+    abac_list_t *credentials = abac_list_new();
+    /* fix up a stream to stream the credentials from prolog engine */
+    return credentials;
+}
+
+void abac_pl_free(abac_pl_t *pl) {
+    if(pl->fptr) {
+        fflush(pl->fptr);
+        free(pl->fptr);
+    }
+    if(pl->fname) {
+        unlink(pl->fname);
+        free(pl->fname);
+    }
+    free(pl);
+}
+
Index: libabac/abac_pl_yap.h
===================================================================
--- libabac/abac_pl_yap.h	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/abac_pl_yap.h	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,27 @@
+#ifndef __PL_YAP_H__
+#define __PL_YAP_H__
+
+#include "abac.h"
+#include "abac_list.h"
+#include "abac_verifier.h"
+
+#define ABAC_PL_CRED_OK          0   // adding a credential succeeded
+#define ABAC_PL_CRED_INVALID     -1  // the credential was invalid
+#define ABAC_PL_CRED_DUP         -2  // the credential is already present 
+
+typedef struct _abac_pl_t abac_pl_t;
+
+abac_pl_t *abac_pl_new(void);
+
+int abac_pl_add_credential(abac_pl_t *pl, abac_credential_t *cred);
+abac_pl_t *abac_pl_dup(abac_pl_t *pl);
+/* return a list of credentials */
+abac_list_t *abac_pl_query(abac_pl_t *pl, char *role, char *principal);
+
+/* return a list of all credentials in the pl file */
+abac_list_t *abac_pl_credentials(abac_pl_t *pl);
+
+void abac_pl_free(abac_pl_t *pl);
+
+
+#endif /* __PL_YAP_H__ */
Index: libabac/abac_rt0.h
===================================================================
--- libabac/abac_rt0.h	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/abac_rt0.h	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,17 @@
+
+/************************************************
+************************************************/
+/* on yacc */
+extern FILE *abac_yyin, *abac_yyout;
+extern int yyparse();
+extern void abac_init_yy();
+extern char *abac_get_yap_clause();
+extern char *abac_free_yap_clause();
+
+/* on lex */
+extern void abac_rest_yyin(FILE *);
+extern void abac_rest_yyout(FILE *);
+extern FILE *abac_get_yyin();
+extern FILE *abac_get_yyout();
+extern void abac_reset_yyfptr(char *);
+extern char* abac_get_yyfptr();
Index: libabac/abac_stack.c
===================================================================
--- libabac/abac_stack.c	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/abac_stack.c	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,52 @@
+#include <stdlib.h>
+
+#include "abac_stack.h"
+#include "abac_util.h"
+
+abac_stack_t *abac_stack_new(void) {
+    abac_stack_t *ret = abac_xmalloc(sizeof(abac_stack_t));
+    ret->elts = NULL;
+    ret->size = 0;
+    return ret;
+}
+
+void abac_stack_push(abac_stack_t *stack, void *elt) {
+    abac_stack_element_t *new_element = abac_xmalloc(sizeof(abac_stack_element_t));
+
+    new_element->ptr = elt;
+    DL_APPEND(stack->elts, new_element);
+    ++stack->size;
+}
+
+void *abac_stack_pop(abac_stack_t *stack) {
+    abac_stack_element_t *cur;
+    void *ret;
+
+    if(stack->size>0) {
+        cur=stack->elts;
+        ret=cur->ptr;
+        DL_DELETE(list->elts, cur);
+        free(cur);
+        --list->size;
+        return ret;
+    }
+    // reutrn false if we don't
+    return NULL;
+}
+
+int abac_stack_size(abac_stack_t *stack) {
+    return stack->size;
+}
+
+void abac_stack_free(abac_stack_t *stack) {
+    abac_stack_element_t *elt, *tmp;
+
+    // free everthing in the stack
+    DL_FOREACH_SAFE(stack->elts, elt, tmp) {
+        DL_DELETE(stack->elts, elt);
+        free(elt);
+    }
+
+    // free the list
+    free(stack);
+}
Index: libabac/abac_stack.h
===================================================================
--- libabac/abac_stack.h	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/abac_stack.h	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,33 @@
+#ifndef __STACK_H__
+#define __STACK_H__
+
+#include "utlist.h"
+
+typedef struct _abac_stack_t abac_stack_t;
+typedef struct _abac_stack_element_t abac_stack_element_t;
+
+struct _abac_stack_element_t {
+    void *ptr;
+    abac_stack_element_t *prev, *next;
+};
+
+struct _abac_stack_t {
+    abac_stack_element_t *elts;
+    int size;
+};
+
+abac_stack_t *abac_stack_new(void);
+void abac_stack_push(abac_stack_t *stack, void *elt);
+void *abac_stack_pop(abac_stack_t *stack);
+int abac_stack_size(abac_stack_t *stack);
+void abac_stack_free(abac_stack_t *stack);
+
+#define abac_stack_foreach(STACK, CURRENT, BODY) do {  \
+    abac_stack_element_t *_elt;                  \
+    DL_FOREACH(STACK->elts, _elt) {              \
+        CURRENT = (typeof(CURRENT))_elt->ptr;   \
+        BODY                                    \
+    }                                           \
+} while (0)
+
+#endif /* __STACK_H__ */
Index: libabac/ort0.l
===================================================================
--- libabac/ort0.l	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/ort0.l	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,68 @@
+%{
+#include <stdio.h>
+#include <string.h>
+#include "ort0.h"
+
+int debug=0;
+
+/* with yacc */
+extern YYSTYPE yylval; 
+/* with just lex */
+/* YYSTYPE yylval; */ 
+
+/* if using canned fixed test string */
+char INPUT_LINE[] = "usc.playground <- usc.employee.friend";
+char *yyfptr = INPUT_LINE; /* default */
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+    { \
+    if(yyfptr != NULL) { \
+      char* c = strncpy(buf,yyfptr,max_size); \
+      if (max_size > 0) buf[max_size-1] = '\0'; \
+      if(strlen(yyfptr) > max_size) yyfptr = yyfptr + max_size-1;  \
+        else yyfptr=NULL; \
+      result = (c == NULL ) ? YY_NULL : strlen(buf); \
+      } else { \
+         buf[0] = '\0'; \
+         result = YY_NULL; \
+    } \
+    }
+
+void abac_reset_yyfptr(char *str) {
+    yyfptr=str;
+}
+
+char* abac_get_yyfptr() {
+    return yyfptr;
+}
+
+/* if using external file input, output */
+void abac_reset_yyin(FILE *new_yyin) {
+    yyin=new_yyin;
+}
+void abac_reset_yyout(FILE *new_yyout) {
+    yyout=new_yyout;
+}
+FILE *abac_get_yyin() {
+    if(yyin) return yyin;
+    else return stdin;
+}
+FILE *abac_get_yyout() {
+    if(yyout) return yyout;
+    else return stdout;
+}
+
+%}
+%%
+[a-zA-Z0-9][_a-zA-Z0-9]*    { yylval.string=strdup(yytext); 
+                          if(debug) fprintf(yyout,"IDEN ");
+                          return IDEN; }
+\<-                     { if(debug) fprintf(yyout,"DERIVE ");
+                          return DERIVE; }
+\.                      { if(debug) fprintf(yyout, "DOT " );
+                          return DOT; }
+\n                      { /* ignore end-of-line */; }
+[ \t]+                  { /* ignore whitespace */; }
+%%
+
Index: libabac/ort0.y
===================================================================
--- libabac/ort0.y	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/ort0.y	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,155 @@
+
+
+/* bison grammar rules for process old rt0 statements */
+/*
+   isi.employee <- ted
+   ted.friend <- mike
+   usc.employee <- isi.employee
+   usc.playground <- usc.employee.friend
+   query,
+      usc.playground <- ?Z
+      isi.playground <- mike
+*/
+
+%{
+/* C declarations */
+#include <stdio.h>
+#include <string.h>
+#include <abac_stack.h>
+
+extern char *abac_cn_with_sha(char*);
+
+FILE *abac_yyin = NULL;
+FILE *abac_yyout = NULL;
+char *abac_yap_clause = NULL;
+char *abac_yyfptr = NULL;
+char *tmp_cred_list = NULL;
+
+int sz_overhead = 0;
+
+%}
+/* Bison declarations */
+%union {
+int  number;
+char *string;   /* For returning char strings */
+}
+%type <string> keypart rolepart left right stmt
+
+%token <string> IDEN       /* keyname or rolename */
+
+%token  <operator>  DERIVE    "<-"
+%token  <operator>  DOT       "."
+
+%%
+/* Grammar rules */
+
+input:      /* empty */
+             { }
+        | stmt 
+             { fprintf (abac_yyout,"stmt (%s)\n", $1);
+               abac_yap_clause = $1;
+             }
+ 
+stmt : left DERIVE right
+             { int sz;
+               char *ptr=strstr($3,"role(");
+               char *tmp;
+               if(ptr==NULL) {
+                 sz=strlen($3)+strlen($1)+sz_overhead;
+                 tmp=(char *)abac_xmalloc(sz);
+                 printf("before.. (%s)\n", $3);
+                 sprintf(tmp,"isMember(%s,%s,['%s'])",$3,$1,abac_yyfptr);
+                 printf("after.. (%s)\n", tmp);
+               } else {
+                 sz=strlen($3)+strlen($1)+sz_overhead;
+                 tmp=(char *)abac_xmalloc(sz);
+                 if (tmp_cred_list==NULL) { 
+                     sprintf(tmp,"isMember(X,%s,['%s']):-%s",
+                                        $1, abac_yyfptr, $3);
+                     } else {
+                     sprintf(tmp,"isMember(X,%s,['%s',%s]):-%s",
+                                        $1, abac_yyfptr, tmp_cred_list, $3);
+                     free(tmp_cred_list);
+                     tmp_cred_list=NULL;
+                 }
+               }
+               $$=tmp;
+               free($3);free($1);
+             }
+
+left : keypart DOT rolepart
+             { 
+               int sz=strlen($1)+strlen($3)+sz_overhead;
+               char *tmp=(char *)abac_xmalloc(sz);
+               sprintf(tmp,"role(%s,%s)", $1, $3);
+               $$=tmp; 
+               free($3);free($1);
+             }
+/* isi */
+keypart : IDEN 
+             { 
+             char *cn=abac_cn_with_sha($1);
+             $$=strdup(cn);
+             }
+
+/* friend */
+rolepart : IDEN
+             { $$=strdup($1); }
+
+right : keypart DOT IDEN DOT IDEN
+             { 
+               int sz=strlen($1)+strlen($3)+strlen($5)+sz_overhead;
+               char *tmp=(char *)abac_xmalloc(sz);
+               sprintf(tmp,"isMember(Y,role(%s,%s),[C1]),isMember(X,role(Y,%s),[C2])",$1,$3,$5);
+               tmp_cred_list = strdup("C1,C2");
+               $$=tmp; 
+               free($1);free($3);free($5);
+             }
+      | keypart DOT IDEN
+             { 
+               int sz=strlen($1)+strlen($3)+sz_overhead;
+               char *tmp=(char *)abac_xmalloc(sz);
+               sprintf(tmp,"isMember(X,role(%s,%s),[C1])", $1, $3);
+               tmp_cred_list = strdup("C1");
+               $$=tmp; 
+               free($1);free($3);
+             }
+      | keypart
+             { 
+             $$=$1;
+             }
+
+%%
+#include "abac_rt0.h"
+
+/* Additional C code */
+int yywrap()
+{
+     /* exit when done lexing the current input */
+     return 1;
+} 
+
+int yyerror (char *s)
+{
+     fprintf (abac_yyout,"yyerror: %s\n", s);
+}
+
+/* setting defaults */
+void abac_yyinit()
+{
+    abac_yyin=abac_get_yyin();
+    abac_yyout=abac_get_yyout();
+    abac_yyfptr = abac_get_yyfptr();
+    sz_overhead = strlen(abac_yyfptr)+2000;
+} 
+
+char *abac_get_yap_clause()
+{
+    return abac_yap_clause;
+}
+
+char *abac_free_yap_clause()
+{
+    if (abac_yap_clause != NULL)
+        free(abac_yap_clause);
+}
Index: libabac/prover_yap.c
===================================================================
--- libabac/prover_yap.c	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
+++ libabac/prover_yap.c	(revision e95d652a2cd6131b110bcb0e946047818f4fe954)
@@ -0,0 +1,39 @@
+
+
+#include <err.h>
+#include <stdio.h>
+
+#include <abac_pl.h>
+
+#include "options.h"
+
+int main(int argc, char **argv) {
+    int i, success;
+    abac_credential_t *cred;
+
+    options_t opts = { 0, };
+    get_options(argc, argv, &opts);
+    abac_context_t *ctx = abac_context_new();
+    abac_context_load_directory(ctx, opts.keystore);
+    abac_credential_t **credentials = abac_context_query(ctx,
+        opts.role, opts.principal,
+        &success
+    );
+    if (success)
+        puts("prover success!!");
+
+    if (credentials != NULL)
+        puts("credentials needed :");
+        for (i = 0; credentials[i] != NULL; ++i) {
+            cred = credentials[i];
+            printf("(%d) %s <- %s\n", i,
+                    abac_role_string(abac_credential_head(cred)),
+                    abac_role_string(abac_credential_tail(cred))
+                  );
+        }
+    abac_context_credentials_free(credentials);
+
+    abac_context_free(ctx);
+
+    return 0;
+}
