Index: libabac/abac_m64.c
===================================================================
--- libabac/abac_m64.c	(revision a9494ad1c5e523f94b0d172045537662de58fd54)
+++ libabac/abac_m64.c	(revision a9494ad1c5e523f94b0d172045537662de58fd54)
@@ -0,0 +1,183 @@
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int debug=1;
+char* abac_decode_string(char *);
+
+/* encode table */
+static const char encode64url[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* decode table Tables */
+/*
+static const char decode64url[]="=====rstuvwxyz========>?@ABCDEFGHIJKLMNOPQRSTUVW======XYZ[\\]^_=abcdefghijklmnopq";
+*/
+/*                                    6       14          26                   48      5557      65              81*/
+
+static const char decode64url[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
+
+/* in 3, out 4 */
+static void _encode_block( char in[3], char out[4] , int len )
+{
+    out[0] = encode64url[ in[0] >> 2 ];
+    out[1] = encode64url[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
+    out[2] = (unsigned char) (len > 1 ? encode64url[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
+    out[3] = (unsigned char) (len > 2 ? encode64url[ in[2] & 0x3f ] : '=');
+if(0) {
+    printf("len: %d\n", len);
+    printf("IN: (%c)  (%c)  (%c)\n", in[0], in[1], in[2]);
+    printf("OUT: (%c)  (%c)  (%c) (%c)\n", out[0], out[1], out[2], out[3]);
+}
+}
+
+/* in 4, out 3 */
+void _decode_block( char in[4], char out[3] )
+{   
+    out[0] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
+    out[1] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
+    out[2] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
+if(0) {
+    printf("IN: (%c)  (%c)  (%c) (%c)\n", in[0], in[1], in[2], in[3]);
+    printf("OUT: (%c)  (%c)  (%c)\n", out[0], out[1], out[2]);
+}
+}
+
+
+/*
+return a deep copy of encoded string
+*/
+char* abac_encode_string(char* string)
+{
+    char *inbufptr, *outbufptr;
+    int len=strlen(string);
+    int olen, nlen;
+    char *orig_string, *new_string;
+    int hops;
+    int i;
+
+    if(len == 0) return strdup("");
+
+    if((len/3)*3 != len) {
+        hops=(len/3)+1;
+        orig_string=malloc(sizeof(char)*olen); 
+        strcpy(orig_string,string);
+        for(i=len; i< olen; i++)
+            orig_string[i]=0;
+        } else {
+        hops=len/3;
+        orig_string=strdup(string);
+    }
+    olen=hops*3;
+    nlen=(olen*4/3 +1);
+    new_string = (char *) malloc(sizeof(char)*nlen);
+ 
+    inbufptr=orig_string;
+    outbufptr=new_string;
+
+    int idx=0;
+    for(i=1; i<=hops;i++) {
+        int v=(len>(i*3))?3:(len-((i-1)*3));
+        _encode_block(inbufptr,outbufptr,v);
+        inbufptr=inbufptr+3;
+        outbufptr=outbufptr+4;
+        idx=idx+3;
+    }
+    free(orig_string);
+    new_string[nlen-1]='\0';
+
+    if(debug) {
+        char *d=abac_decode_string(new_string);
+        if(strcmp(d,string) !=0) {
+            printf("ERROR, base64 encoding NOT OKAY\n");
+            printf("orig,(%s)\n", string);
+            printf("new,(%s)\n", new_string);
+            printf("decode,(%s)\n",d);
+        } else printf(" base64 encoding OKAY\n");
+        /* free(d); */
+    }
+    return new_string;
+}
+
+char* abac_decode_string(char *string)
+{
+    char *inbufptr, *outbufptr;
+    int len=strlen(string);
+    int nlen;
+    char *new_string;
+    char *orig_string;
+    int idx=0;
+    int v=0;
+
+    if(len==0) return strdup("");
+    int hops=len/4; // ignore any that is not in the size 4 blocks
+    new_string=(char *)malloc(sizeof(char)*(hops*3+1));
+    new_string[hops*3]='\0';
+    orig_string=strdup(string);
+
+    inbufptr=orig_string;
+    outbufptr=new_string;
+    char inbuf[4];
+    int i, j;
+
+    for(i=1; i<=hops; i++) {
+        for(j=0; j<4; j++) {
+            char c=inbufptr[j];
+            if(c > 122 || c <43) {
+                c=0;
+                } else {
+                   if(0) printf("from %d, (%c)\n", c, c);
+                   c=decode64url[c-43];
+                   if(0) printf("to %d, (%c)\n", c, c);
+            }
+            if(c) { 
+                if(c=='$') c=0;
+                    else c=c-61;
+            }
+            if(c) {
+                inbufptr[j]=(c-1);
+                } else {
+                    inbufptr[j]=0;
+            }              
+        }
+        _decode_block( inbufptr, outbufptr );
+        outbufptr=outbufptr+3;
+        inbufptr=inbufptr+4;
+    }
+    free(orig_string);
+    return new_string;
+}
+
+
+/*****************
+int main( int argc, char **argv )
+{
+ 
+    if(argc != 2) return 1;
+
+    FILE *infile = fopen( argv[1], "r" );
+
+    int num=1000;
+    char *string=(char *)malloc(sizeof(char)*num);
+
+    int cnt=getline(&string,&num,infile);
+    fclose(infile);
+    if(cnt==0) return 0;
+    if(string[cnt-1]=='\n')
+        string[cnt-1]='\0';
+
+    char *i=abac_encode_string(string);
+    printf("encoding into (%s)\n", i);
+    char *o=abac_decode_string(i);
+    printf("decode into (%s)\n", o);
+
+    printf(" %d:%d:%d\n", strlen(string),strlen(i), strlen(o));
+    if(strcmp(string,o)==0)
+         printf("OKAY \n");
+         else
+              printf("NOT OKAY \n");
+    free(string);
+    free(o);
+}
+****************/
Index: libabac/abac_pl_yy.c
===================================================================
--- libabac/abac_pl_yy.c	(revision a9494ad1c5e523f94b0d172045537662de58fd54)
+++ libabac/abac_pl_yy.c	(revision a9494ad1c5e523f94b0d172045537662de58fd54)
@@ -0,0 +1,662 @@
+
+/* C declarations */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "uthash.h"
+#include "abac_util.h"
+
+#include "abac_pl_yy.h"
+
+static int debug=0;
+
+extern abac_list_t *generate_pl_clauses(abac_role_t *, abac_role_t *);
+extern void panic(char*);
+extern char *generate_pl_type_clause(char *, int);
+void _add_yy_id_certs(char *, int);
+
+abac_list_t *abac_yap_clauses=NULL;
+/* this is to track individual id credentials */
+abac_stack_t *abac_yap_id_clauses=NULL;
+
+abac_role_t *abac_yap_head_role=NULL;
+abac_role_t *abac_yap_tail_role=NULL;
+
+/* XXX do we want to check whether the id cert is preexisting or not */
+/* this is to track id certs within a rule clause */
+typedef struct _abac_yy_id_cert_t {
+    char *principalname;
+    int type; /* keyidtype */
+    char *clause;
+
+    UT_hash_handle hh;
+} abac_yy_id_cert_t;
+
+abac_list_t *abac_yy_id_certs = NULL;
+
+/* local principal structure  [keyid:USC] */
+struct _abac_yy_principal_t {
+    int type;
+    char *sha;
+    char *cn;
+};
+
+/* like  [principal:?Z]:..., must match a principal name */
+struct _abac_yy_param_principal_t {
+    int type; /* this needs to be implicitly determined */
+    char *name;
+    char *condition;
+};
+
+/* if has condition, then it is a variable,
+   ie,
+    [int:?Year]:<1930..1932>,
+   if no condition, then it is a constant, 
+    ie,
+    [int:10]
+*/
+struct _abac_yy_param_data_t {
+    int is_variable;
+    int type;
+    char *name;
+    char *condition;
+};
+
+/* local dterm structure, will distinguish it in the future */
+struct _abac_yy_dterm_t {
+    union {
+         abac_yy_principal_t *n_ptr;
+         abac_yy_param_principal_t *p_ptr;
+         abac_yy_param_data_t *d_ptr;
+    } term;
+    int type;
+    struct _abac_yy_dterm_t *next;
+    int bcnt; /* this is to track number of dterms in this linked up list */
+};
+
+/* local role structure */
+struct _abac_yy_role_t {
+   int type;
+   char *name;
+   abac_yy_dterm_t *dterms;
+   struct _abac_yy_role_t *next;
+   int bcnt; /* this is to track number of roles in this linked up list */
+};
+
+struct _abac_yy_role_expression_t {
+   int rtype;
+   abac_yy_principal_t *principal;
+   abac_yy_role_t *linked_role;
+   abac_yy_role_t *role;
+   struct _abac_yy_role_expression_t *next;
+   int bcnt;
+};
+
+static void _free_yy_dterm(abac_yy_dterm_t *ptr);
+
+/************************************************************************/
+abac_stack_t *abac_get_yap_id_clauses()
+{
+    return abac_yap_id_clauses;
+}
+
+abac_stack_t *abac_init_yap_id_clauses()
+{
+    abac_yap_id_clauses=abac_stack_new();
+    return abac_yap_id_clauses;
+}
+
+void abac_free_yap_id_clauses()
+{
+    if (abac_yap_id_clauses != NULL)
+        abac_stack_free(abac_yap_id_clauses);
+}
+
+void set_yap_clauses(abac_list_t *clauses)
+{
+    abac_yap_clauses=clauses;
+    if(debug) {
+         printf("printing out abac_yap_clauses:\n");
+         abac_print_clauses(abac_yap_clauses);
+    }
+}
+
+abac_list_t *abac_get_yap_clauses()
+{
+    return abac_yap_clauses;
+}
+
+void abac_free_yap_clauses()
+{
+    if (abac_yap_clauses != NULL) {
+        char *cur;
+        abac_list_foreach(abac_yy_id_certs, cur,
+            if(cur) free(cur);
+        );
+        abac_list_free(abac_yap_clauses);
+    }
+}
+
+abac_role_t *abac_get_yap_head_role()
+{
+    return abac_yap_head_role;
+}
+
+abac_role_t *abac_get_yap_tail_role()
+{
+    return abac_yap_tail_role;
+}
+
+void abac_init_yy_id_certs()
+{
+    abac_yy_id_certs = abac_list_new();
+}
+
+void abac_free_yy_id_certs()
+{
+    abac_yy_id_cert_t *id;
+    abac_list_foreach(abac_yy_id_certs, id,
+        if(id) 
+            free(id->principalname);
+            free(id->clause);
+            free(id);
+    );
+    abac_list_free(abac_yy_id_certs);
+}
+
+int abac_cnt_yy_id_certs()
+{
+    return abac_list_size(abac_yy_id_certs);
+}
+
+char *abac_string_yy_id_certs()
+{
+    int first=1;
+    char *tmp=NULL;
+    abac_yy_id_cert_t *cur;
+    abac_list_foreach(abac_yy_id_certs, cur,
+        if(cur) 
+            if(first) {
+                tmp=abac_xstrdup(cur->clause);
+                first=0;
+                } else {
+                    int cnt=asprintf(&tmp,"%s,%s", tmp, cur->clause);
+            }
+    );
+    return tmp;
+}
+
+void _add_yy_id_certs(char *principalname, int type)
+{
+    abac_yy_id_cert_t *id_cert=NULL;
+
+    int found=0;
+    abac_yy_id_cert_t *cur;
+    abac_list_foreach(abac_yy_id_certs, cur,
+        if(cur) 
+            if(strcmp(cur->principalname,principalname)==0) {
+               found=1;
+               break;
+            }
+    );
+
+    if (found) {
+        return;
+        } else {
+            id_cert=abac_xmalloc(sizeof(abac_yy_id_cert_t));
+            id_cert->principalname=abac_xstrdup(principalname);
+            id_cert->type=type;
+            id_cert->clause=generate_pl_type_clause(principalname,type);
+            abac_list_add(abac_yy_id_certs, id_cert);
+    }
+}
+
+/****************************************************************************/
+abac_yy_principal_t *make_yy_principal(char *sha, char *cn, int type)
+{
+    abac_yy_principal_t *ptr=
+               (abac_yy_principal_t*)abac_xmalloc(sizeof(abac_yy_principal_t));
+    ptr->sha=abac_xstrdup(sha);
+    ptr->cn=abac_xstrdup(cn);
+    ptr->type=type;
+    return ptr;
+}
+
+static void _free_yy_principal(abac_yy_principal_t *ptr)
+{
+    free(ptr->sha);
+    if(ptr->cn)
+        free(ptr->cn);
+    free(ptr);
+}
+
+abac_yy_role_t *make_yy_role(char *name, abac_yy_dterm_t *dterms)
+{
+    abac_yy_role_t *ptr=(abac_yy_role_t*)abac_xmalloc(sizeof(abac_yy_role_t));
+    ptr->name=abac_xstrdup(name);
+    ptr->dterms=dterms;
+    ptr->next=NULL;
+    ptr->bcnt=1;
+    return ptr;
+}
+
+static void _free_yy_role(abac_yy_role_t *ptr)
+{
+    free(ptr->name);
+    if(ptr->dterms)
+        _free_yy_dterm(ptr->dterms);
+    if(ptr->next)
+        _free_yy_role(ptr->next);
+    free(ptr);
+}
+
+abac_yy_role_expression_t *make_yy_role_expression(int rtype,
+abac_yy_principal_t *principal, abac_yy_role_t *role, abac_yy_role_t *linked_role)
+{
+    abac_yy_role_expression_t *ptr=
+         (abac_yy_role_expression_t*)abac_xmalloc(sizeof(abac_yy_role_expression_t));
+    ptr->rtype = rtype;
+    ptr->principal = principal;
+    ptr->role = role;
+    ptr->linked_role=linked_role;
+    ptr->next=NULL;
+
+    return ptr;
+}
+
+abac_yy_role_expression_t *add_yy_role_expression(abac_yy_role_expression_t *nexpr,
+                                               abac_yy_role_expression_t *exprs)
+{
+    int i=exprs->bcnt;
+    nexpr->next=exprs;
+    nexpr->bcnt=i+1;
+    return nexpr;
+}
+
+
+static void _free_yy_role_expression(abac_yy_role_expression_t *ptr)
+{
+    if(ptr->principal)
+        _free_yy_principal(ptr->principal);
+    if(ptr->role)
+        _free_yy_role(ptr->role);
+    if(ptr->linked_role)
+        _free_yy_role(ptr->linked_role);
+    if(ptr->next)
+        _free_yy_role_expression(ptr->next);
+
+    free(ptr);
+}
+
+abac_yy_param_data_t *make_yy_param_data(char* name, char* typestr)
+{
+    int type=abac_verify_dterm_type(typestr);
+    abac_yy_param_data_t *ptr=
+              (abac_yy_param_data_t*)abac_xmalloc(sizeof(abac_yy_param_data_t));
+    ptr->name=abac_xstrdup(name);
+    ptr->type=type;
+    ptr->condition=NULL;
+    ptr->is_variable=0;
+    return ptr;
+}
+
+void set_yy_param_data_is_variable(abac_yy_param_data_t *ptr)
+{
+    ptr->is_variable=1;
+}
+
+static void _free_yy_param_data(abac_yy_param_data_t *ptr)
+{
+    free(ptr->name);
+    if(ptr->condition)
+        free(ptr->condition);
+    free(ptr);
+}
+
+abac_yy_param_principal_t *make_yy_param_principal(char* name)
+{
+    abac_yy_param_principal_t *ptr=
+            (abac_yy_param_principal_t*)abac_xmalloc(sizeof(abac_yy_param_principal_t));
+    ptr->name=abac_xstrdup(name);
+    ptr->condition=NULL;
+    return ptr;
+}
+
+static void _free_yy_param_principal(abac_yy_param_principal_t *ptr)
+{
+    free(ptr->name);
+    if(ptr->condition)
+        free(ptr->condition);
+    free(ptr);
+}
+
+abac_yy_dterm_t *make_yy_dterm_anonymous()
+{
+    abac_yy_dterm_t *ptr=(abac_yy_dterm_t*)abac_xmalloc(sizeof(abac_yy_dterm_t));
+    ptr->type = DTERM_ANONYMOUS;
+    ptr->next=NULL;
+    ptr->bcnt=1;
+    return ptr;
+}
+
+abac_yy_dterm_t *make_yy_dterm_principal(abac_yy_param_principal_t *pptr)
+{
+    abac_yy_dterm_t *ptr=(abac_yy_dterm_t*)abac_xmalloc(sizeof(abac_yy_dterm_t));
+    ptr->type = DTERM_PRINCIPAL;
+    ptr->term.p_ptr=pptr;
+    ptr->next=NULL;
+    ptr->bcnt=1;
+    return ptr;
+}
+
+abac_yy_dterm_t *make_yy_dterm_named(abac_yy_principal_t *nptr)
+{
+    abac_yy_dterm_t *ptr=(abac_yy_dterm_t*)abac_xmalloc(sizeof(abac_yy_dterm_t));
+    ptr->type = DTERM_NAMED;
+    ptr->term.n_ptr=nptr;
+    ptr->next=NULL;
+    ptr->bcnt=1;
+    return ptr;
+}
+
+abac_yy_dterm_t *make_yy_dterm_data(abac_yy_param_data_t *dptr)
+{
+    abac_yy_dterm_t *ptr=(abac_yy_dterm_t*)abac_xmalloc(sizeof(abac_yy_dterm_t));
+    ptr->type = DTERM_DATA;
+    ptr->term.d_ptr=dptr;
+    ptr->next=NULL;
+    ptr->bcnt=1;
+    return ptr;
+}
+
+abac_yy_dterm_t *add_yy_dterm(abac_yy_dterm_t *nterm, abac_yy_dterm_t *dterms)
+{
+    int i=dterms->bcnt;
+    nterm->next=dterms;
+    nterm->bcnt=i+1;
+    return nterm;
+}
+
+static void _free_yy_dterm(abac_yy_dterm_t *ptr)
+{
+    switch (ptr->type) {
+        case DTERM_DATA:
+            _free_yy_param_data(ptr->term.d_ptr);
+            break;
+        case DTERM_NAMED:
+            _free_yy_principal(ptr->term.n_ptr);
+            break;
+        case DTERM_PRINCIPAL:
+            _free_yy_param_principal(ptr->term.p_ptr);
+            break;
+        case DTERM_ANONYMOUS:
+            break;
+    }
+    if(ptr->next)
+        _free_yy_dterm(ptr->next);
+    free(ptr);
+}
+
+/****************************************************************/
+static void _role_add_dterms(int linked, abac_role_t *role, abac_yy_dterm_t *dterms)
+{
+    abac_yy_dterm_t *curr = dterms;
+    int type;
+    char *name=NULL;
+    char *cond=NULL;
+    while (curr) {
+        switch (curr->type) {
+           case DTERM_DATA:
+           {
+               abac_yy_param_data_t *ptr=curr->term.d_ptr;
+               type=ptr->type;
+               name=abac_xstrdup(ptr->name);
+               cond=abac_xstrdup(ptr->condition);
+               if(ptr->is_variable) {
+/* XXX do some tracking */
+               }
+               break;
+           }
+           case DTERM_PRINCIPAL:
+           {
+              abac_yy_param_principal_t *ptr=curr->term.p_ptr;
+              type=abac_verify_dterm_type("principal");
+              name=abac_xstrdup(ptr->name);
+              cond=abac_xstrdup(ptr->condition);
+/* XXX variable one, do some tracking */
+              break;
+           }
+           case DTERM_NAMED:
+           {
+              abac_yy_principal_t *ptr=curr->term.n_ptr;
+              type=ptr->type;
+/* XXX should be switching to sha in the future */
+              name=abac_xstrdup(ptr->cn);
+              cond=NULL;
+              break;
+           }
+           case DTERM_ANONYMOUS:
+           {
+              type=0;
+              name=abac_xstrdup("_");
+              cond=NULL;
+              break;
+           }
+       }
+       if (linked) 
+           abac_role_role_add_linked_param(role, type, name, cond);
+           else
+                abac_role_role_add_param(role, type, name, cond);
+       curr=curr->next;
+   }
+}
+
+static void _role_add_linked_dterms(abac_role_t *role, abac_yy_dterm_t *dterms)
+{
+    int linked=1;
+    _role_add_dterms(linked, role, dterms);
+}
+
+static void _role_add_role_dterms(abac_role_t *role, abac_yy_dterm_t *dterms)
+{
+    int linked=0;
+    _role_add_dterms(linked, role, dterms);
+}
+
+
+abac_role_t *validate_intersected_tail_role(abac_role_t *role)
+{
+    abac_role_t *ret_role=NULL;
+    abac_list_t *prereqs = abac_list_new();
+    abac_list_add(prereqs, role);
+    ret_role = abac_role_intersection_new("intersectingROLE", prereqs);
+    return ret_role;
+}
+
+abac_role_t *validate_head_role(abac_yy_role_expression_t *expr)
+{
+     abac_yy_principal_t *principal=expr->principal;
+     abac_yy_role_t *role=expr->role;
+
+     char *principalname=principal->sha;
+     char *rolename=role->name;
+     abac_yy_dterm_t *dterms=role->dterms;
+     abac_role_t *ret_role=NULL;
+
+     ret_role=abac_role_role_new(principalname, rolename);
+     if (ret_role==NULL) {
+         set_error_code(ABAC_RT_ROLE_INVALID);
+         goto error;
+     }
+     if (!abac_role_is_role(ret_role)) {
+         set_error_code(ABAC_RT_CERT_INVALID);
+         goto error;
+     }
+     // insert the params for the role
+     if(dterms) {
+          _role_add_role_dterms(ret_role, dterms);
+     }
+
+     _add_yy_id_certs(principal->cn,principal->type);
+
+     return ret_role;
+
+error:
+     return NULL;
+}
+
+abac_role_t *validate_named_tail_role(abac_yy_role_expression_t *expr)
+{
+     abac_yy_principal_t *principal=expr->principal;
+     char *principalname=principal->sha;
+     abac_role_t *ret_role=NULL;
+
+     ret_role = abac_role_principal_new(principalname);
+
+     _add_yy_id_certs(principal->cn,principal->type);
+
+     if (ret_role==NULL)
+         goto error;
+     return ret_role;
+
+error:
+     panic("can not generate a simple named tail role");
+     return NULL;
+}
+
+abac_role_t *validate_role_tail_role(abac_yy_role_expression_t *expr)
+{
+     abac_yy_principal_t *principal=expr->principal;
+     abac_yy_role_t *role=expr->role;
+
+     char *principalname=principal->sha;
+
+     char *rolename=role->name;
+     abac_yy_dterm_t *dterms=role->dterms;
+
+     int ret;
+     abac_role_t *ret_role=NULL;
+
+     ret_role = abac_role_role_new(principalname, rolename);
+     if (ret_role==NULL)
+         goto error;
+
+     if(dterms) {
+         _role_add_role_dterms(ret_role, dterms);
+     }
+
+     _add_yy_id_certs(principal->cn,principal->type);
+
+     return ret_role;
+
+error:
+     panic("can not generate a simple tail role");
+     return NULL;
+}
+/* need to validate/generate a linked role out of this */
+abac_role_t *validate_linked_tail_role(abac_yy_role_expression_t *expr)
+{
+     abac_yy_principal_t *principal=expr->principal;
+     abac_yy_role_t *role=expr->role;
+     abac_yy_role_t *linked_role=expr->linked_role;
+
+     char *principalname=principal->sha;
+
+     char *rolename=role->name;
+     abac_yy_dterm_t *dterms=role->dterms;
+
+     char *linkedrolename=linked_role->name;
+     abac_yy_dterm_t *linked_dterms=linked_role->dterms;
+
+     int ret;
+     abac_role_t *ret_role=NULL;
+
+     ret_role = abac_role_linking_new(principalname, linkedrolename, rolename);
+     if (ret_role==NULL)
+         goto error;
+
+     if(linked_dterms) {
+         _role_add_linked_dterms(ret_role, linked_dterms);
+     }
+     if(dterms) {
+         _role_add_role_dterms(ret_role, dterms);
+     }
+
+     _add_yy_id_certs(principal->cn,principal->type);
+
+     return ret_role;
+
+error:
+     panic("can not generate linked tail role");
+     return NULL;
+}
+
+
+abac_list_t *make_statement(abac_yy_role_expression_t *headexpr,
+                       abac_yy_role_expression_t *tailexpr) 
+{ 
+    abac_role_t *head_role=NULL;
+    abac_role_t *tail_role=NULL;
+
+/* build up left side's abac role structure */
+    head_role=validate_head_role(headexpr);
+    if(head_role == NULL)
+        goto error;
+
+/* build up the right side's abac role structure */
+    abac_yy_role_expression_t *curr_tail = tailexpr;
+    int intersecting=(tailexpr->next != NULL)? 1:0;
+    abac_role_t *curr_role = NULL;
+        while (curr_tail) {
+            switch(curr_tail->rtype) {
+                case EXPR_NAMED:
+                    curr_role=validate_named_tail_role(curr_tail);
+                    break;
+                case EXPR_ROLE:
+                    curr_role=validate_role_tail_role(curr_tail);
+                    break;
+                case EXPR_LINKED:
+                    curr_role=validate_linked_tail_role(curr_tail);
+                    break;
+            }
+            if(curr_role==NULL)
+                goto error;
+
+            /* check if first one */
+            if(tail_role==NULL) {
+                if(intersecting) 
+                    tail_role=validate_intersected_tail_role(curr_role);
+                    else 
+                        tail_role=curr_role;
+                } else {  
+                    abac_role_add_intersecting_role(tail_role,curr_role);
+            }
+            curr_tail=curr_tail->next;
+        } /* while */
+
+/* collect up type clauses and generate rule clauses */
+        abac_list_t *tmp=generate_pl_clauses(head_role,tail_role);
+        if(tmp == NULL)
+            goto error;
+
+        if(debug) {
+            abac_print_role_string_with_condition(head_role);
+            abac_print_role_string_with_condition(tail_role);
+        }
+
+        _free_yy_role_expression(headexpr);
+        _free_yy_role_expression(tailexpr);
+        abac_yap_head_role=head_role;
+        abac_yap_tail_role=tail_role;
+        return tmp;
+
+error:
+        _free_yy_role_expression(headexpr);
+        _free_yy_role_expression(tailexpr);
+        if(head_role)
+            abac_role_free(head_role);
+        if(tail_role)
+            abac_role_free(tail_role);
+        return NULL;
+}
Index: libabac/abac_pl_yy.h
===================================================================
--- libabac/abac_pl_yy.h	(revision a9494ad1c5e523f94b0d172045537662de58fd54)
+++ libabac/abac_pl_yy.h	(revision a9494ad1c5e523f94b0d172045537662de58fd54)
@@ -0,0 +1,30 @@
+#ifndef __ABAC_PL_YY_H__
+#define __ABAC_PL_YY_H__
+
+/* C declarations */
+#include "abac_pl.h"
+#include "abac_list.h"
+#include "abac_util.h"
+#include "abac_rt.h"
+
+typedef struct _abac_yy_principal_t abac_yy_principal_t;
+typedef struct _abac_yy_param_principal_t abac_yy_param_principal_t;
+typedef struct _abac_yy_param_data_t abac_yy_param_data_t;
+typedef struct _abac_yy_dterm_t abac_yy_dterm_t;
+typedef struct _abac_yy_role_t abac_yy_role_t;
+typedef struct _abac_yy_role_expression_t abac_yy_role_expression_t;
+
+enum expr_rtype {
+    EXPR_NAMED=1,
+    EXPR_ROLE=2,
+    EXPR_LINKED=3
+};
+
+enum dterm_type {
+    DTERM_PRINCIPAL=1,
+    DTERM_NAMED=2,
+    DTERM_DATA=3,
+    DTERM_ANONYMOUS=4
+};
+
+#endif /* __ABC_PL_YY_H__ */
