Index: libabac/abac_term.c
===================================================================
--- libabac/abac_term.c	(revision 8bd77b59df89993868555d3b87f91fc241b09228)
+++ libabac/abac_term.c	(revision 8bd77b59df89993868555d3b87f91fc241b09228)
@@ -0,0 +1,560 @@
+
+/***********************************************************
+   abac_term.c
+
+ dterm=data term of rt1
+ term is a kind of dterm
+***********************************************************/
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "abac_internal.h"
+#include "abac_util.h"
+
+static int debug=0;
+
+/* string will contain either 
+     the range literal (static constraint)
+       or
+     the oset/role prologized string (dynamic constraint)
+   union ptr will only be set if it is a dynamic
+   constraint */
+struct _abac_condition_t {
+    int type;
+    char *string; 
+    abac_aspect_t *of_aspect;
+};
+
+struct _abac_term_t {
+    int type;
+    char *name;
+    char *cn;
+    abac_condition_t *constraint;
+}; 
+
+/* new, free, add one of terms */
+struct _abac_param_list_t {
+    abac_list_t *list;
+};
+
+
+/******************************************************************/
+char *abac_condtype_name(int i)
+{
+    if(i>_condname_cnt)
+        panic("abac_condtype_name: went out of range on condname");
+    return _condname[i];
+}
+
+abac_condition_t *abac_condition_new(int type,char* condstr,abac_aspect_t *cptr)
+{
+     if(debug) {
+         printf("   abac_condition_new: \n");
+         printf("     type is %d(%s)\n", type, abac_condtype_name(type));
+         printf("     condstr is (%s)\n", condstr);
+         if(cptr) printf("     yes on cptr\n");
+             else printf("     no on cptr\n");
+     }
+     abac_condition_t *ptr=
+             (abac_condition_t *)abac_xmalloc(sizeof(abac_condition_t));
+     ptr->type=type;
+     ptr->string=abac_xstrdup(condstr);
+     if(cptr) ptr->of_aspect=abac_aspect_dup(cptr);
+         else ptr->of_aspect=NULL;
+     return ptr;
+}
+
+void abac_condition_free(abac_condition_t *ptr)
+{
+     switch(ptr->type) {
+        case e_COND_OSET:
+        case e_COND_ROLE:
+            abac_aspect_free(ptr->of_aspect);
+            break;
+        case e_COND_RANGE:
+            /* do nothing */
+            break;
+     }
+     if(ptr->string) free(ptr->string);
+     free(ptr);
+}
+
+abac_condition_t *abac_condition_from_string(char *string)
+{
+     assert(string);
+     abac_condition_t *nptr=
+             (abac_condition_t *)abac_xmalloc(sizeof(abac_condition_t));
+     nptr->type=e_COND_RANGE;
+     nptr->string=abac_xstrdup(string);
+     nptr->of_aspect=NULL;
+     return nptr;
+}
+
+abac_condition_t *abac_condition_from_aspect(abac_aspect_t *ptr)
+{
+     assert(ptr);
+     abac_condition_t *nptr=
+             (abac_condition_t *)abac_xmalloc(sizeof(abac_condition_t));
+     if(abac_aspect_is_role(ptr))
+         nptr->type=e_COND_ROLE;
+         else nptr->type=e_COND_OSET;
+     nptr->string=NULL;
+     nptr->of_aspect=abac_aspect_dup(ptr);
+     return nptr;
+}
+
+/* made a copy */
+abac_condition_t *abac_condition_dup(abac_condition_t *ptr)
+{
+     abac_condition_t *nptr=
+             (abac_condition_t *)abac_xmalloc(sizeof(abac_condition_t));
+     nptr->type=ptr->type;
+     if(ptr->string)
+         nptr->string=abac_xstrdup(ptr->string);
+         else nptr->string=NULL;
+     if(ptr->of_aspect)
+         nptr->of_aspect=abac_aspect_dup(ptr->of_aspect);
+         else nptr->of_aspect=NULL;
+     return nptr;
+}
+
+char *abac_condition_string(abac_condition_t *ptr)
+{
+     char *string=NULL;
+     switch(ptr->type) {
+        case e_COND_OSET:
+        case e_COND_ROLE:
+            string=abac_aspect_string_with_condition(ptr->of_aspect);
+            break;
+        case e_COND_RANGE:
+            string=abac_xstrdup(ptr->string);
+            break;
+     }
+     return string;
+}
+
+char *abac_condition_typed_string(abac_condition_t *ptr)
+{
+     char *string=NULL;
+     switch(ptr->type) {
+        case e_COND_OSET:
+        case e_COND_ROLE:
+            string=abac_aspect_typed_string_with_condition(ptr->of_aspect);
+            break;
+        case e_COND_RANGE:
+            string=abac_xstrdup(ptr->string);
+            break;
+     }
+     return string;
+}
+
+/******************************************************************/
+
+char *abac_term_name(abac_term_t *term)
+{
+    return term->name;
+}
+
+char *abac_term_cn(abac_term_t *term)
+{
+    return term->cn;
+}
+
+abac_condition_t *abac_term_constraint(abac_term_t *term)
+{
+    return term->constraint;
+}
+
+char *abac_termtype_name(int i)
+{
+    if(i>_termname_cnt)
+        panic("abac_termtype_name: went out of range on termname");
+    return _termname[i];
+}
+
+char *abac_term_type_name(abac_term_t *term)
+{
+    return abac_termtype_name(term->type);
+}
+
+int abac_term_type(abac_term_t *term)
+{
+    return term->type;
+}
+
+static bool _abac_termtype_is_time_type(int i)
+{
+    if (i == e_TERM_TIME) 
+       return 1;
+    return 0;
+}
+
+bool abac_term_is_time_type(abac_term_t *term)
+{
+    return _abac_termtype_is_time_type(term->type);
+}
+
+static bool _abac_termtype_is_string_type(int i)
+{
+    if (i == e_TERM_STRING) 
+       return 1;
+    return 0;
+}
+
+bool abac_term_is_string_type(abac_term_t *term)
+{
+    return _abac_termtype_is_string_type(term->type);
+}
+
+static bool _abac_termtype_is_integer_type(int i)
+{
+    if (i == e_TERM_INTEGER) 
+       return 1;
+    return 0;
+}
+
+bool abac_term_is_integer_type(abac_term_t *term)
+{
+    return _abac_termtype_is_integer_type(term->type);
+}
+
+static bool _abac_termtype_is_urn_type(int i)
+{
+    if (i == e_TERM_URN) 
+       return 1;
+    return 0;
+}
+
+bool abac_term_is_urn_type(abac_term_t *term)
+{
+    return _abac_termtype_is_urn_type(term->type);
+}
+
+int abac_term_verify_term_type(char *type) {
+    int i;
+
+    if (type == NULL)
+        return 0;
+
+    for (i = 1; i <= _termname_cnt ; i++)
+        if(strcmp(type,_termname[i])==0)
+            return i;
+    return 0;
+}
+
+char *abac_term_to_time(char *string)
+{
+    struct tm tm1;
+    char buf[255];
+
+    strptime(string, "%Y%m%dT%H%M%S", &tm1);
+    strftime(buf, sizeof(buf), "time(%Y,%m,%d,%H,%M,%S)", &tm1);
+    return strdup(buf);
+}
+
+/* called from yy */
+abac_term_t *abac_term_new(int type, char *name, char *cond, abac_aspect_t *cptr)
+{
+     if(debug) {
+         printf("abac_term_new: \n");
+         printf("  type is %d(%s)\n", type, abac_termtype_name(type));
+         printf("  name is (%s)\n", name);
+         if(cond)
+             printf("  cond is %s\n", cond);
+             else printf("  no cond \n");
+         if(cptr)
+             printf("  cptr is (%s)\n", abac_aspect_string_with_condition(cptr));
+             else printf("  there is no cptr\n");
+     }
+     abac_condition_t *constraint=NULL;
+     if (cond) {
+         if(type==e_TERM_PRINCIPAL) {
+             constraint=abac_condition_new(e_COND_ROLE,cond,cptr);
+             } else {
+                 if(cptr == NULL)
+                    constraint=abac_condition_new(e_COND_RANGE,cond,NULL);
+                    else
+                        constraint=abac_condition_new(e_COND_OSET,cond,cptr);
+         }
+     }
+     abac_term_t *ptr=abac_xmalloc(sizeof(abac_term_t));
+     ptr->type=type;
+     /* reformat the term name if it is a time type */
+     if((!constraint) && _abac_termtype_is_time_type(type) && isdigit(name[0])) {
+         char *tmp=abac_term_to_time(name);
+         ptr->name=tmp;
+         } else {
+             ptr->name=abac_xstrdup(name);
+     }
+     ptr->constraint=constraint;
+     return ptr;
+}
+
+abac_term_t *abac_term_create(int type, char *name, abac_condition_t *cptr)
+{
+     if(debug) {
+         printf("abac_term_create: \n");
+         printf("  type is %d(%s)\n", type, abac_termtype_name(type));
+         printf("  name is (%s)\n", name);
+         if(cptr)
+             printf("  cptr is (%s)\n", abac_condition_typed_string(cptr));
+             else printf("  there is no cptr\n");
+     }
+
+     abac_term_t *ptr=abac_xmalloc(sizeof(abac_term_t));
+     ptr->type=type;
+     /* reformat the term name if it is a time type */
+     if((!cptr) && _abac_termtype_is_time_type(type) && isdigit(name[0])) {
+         char *tmp=abac_term_to_time(name);
+         ptr->name=tmp;
+         } else {
+             ptr->name=abac_xstrdup(name);
+     }
+     ptr->constraint=(cptr==NULL)?NULL:abac_condition_dup(cptr);
+     return ptr;
+}
+
+abac_term_t *abac_term_dup(abac_term_t *ptr)
+{
+     assert(ptr);
+     abac_term_t *nptr=abac_xmalloc(sizeof(abac_term_t));
+     nptr->type=ptr->type;
+     nptr->name=abac_xstrdup(ptr->name);
+     if(ptr->constraint!=NULL)
+        nptr->constraint=abac_condition_dup(ptr->constraint);
+        else nptr->constraint=NULL;
+     return nptr;
+}
+
+void abac_term_free(abac_term_t *ptr)
+{
+    if(ptr->constraint) {
+         abac_condition_free(ptr->constraint);
+    }
+    free(ptr->name);
+    free(ptr);
+}
+
+abac_term_t *abac_term_add_constraint(abac_term_t *ptr, abac_condition_t *cond)
+{
+    if(ptr->constraint) {
+        abac_condition_free(ptr->constraint);
+    }
+    ptr->constraint = abac_condition_dup(cond);
+    return ptr;
+}
+
+/* name or name:cond */
+static char *abac_term_string_with_condition(abac_term_t *ptr)
+{
+    char *tmp=NULL;
+    char *cond=NULL;
+    char *name=abac_term_name(ptr);
+    if(ptr->constraint) {
+       cond=abac_condition_string(ptr->constraint);
+    }
+    if(cond) {
+       asprintf(&tmp,"%s:%s", name, cond);
+       free(cond);
+    } else tmp=abac_xstrdup(name);
+    return tmp;
+}
+
+/* [type:name] or [typed:name:cond] */
+static char *abac_term_typed_string_with_condition(abac_term_t *ptr)
+{
+    char *tmp=NULL;
+    char *cond=NULL;
+    char *name=abac_term_name(ptr);
+    char *type=abac_term_type_name(ptr);
+    if(ptr->constraint) {
+       cond=abac_condition_typed_string(ptr->constraint);
+    }
+    if(cond) {
+       asprintf(&tmp,"[%s:%s:%s]", type, name, cond);
+       free(cond);
+    } else
+           asprintf(&tmp,"[%s:%s]", type, name);
+    if(debug) printf("abac_term_typed_string_with_condition: (%s)\n",tmp);
+    return tmp;
+}
+
+/* len of name or name:cond */
+static int abac_term_len_with_condition(abac_term_t *ptr)
+{
+    char *cond=NULL;
+    char *name=ptr->name;
+    int len=strlen(name);
+    if(ptr->constraint) {
+       cond=abac_condition_string(ptr->constraint);
+       len=len+strlen(cond)+1;
+       free(cond); 
+    }
+    return len;
+}
+
+/* just name */
+char *abac_term_string(abac_term_t *ptr)
+{
+    return abac_xstrdup(ptr->name);
+}
+
+/* just len of name */
+static int abac_term_len(abac_term_t *ptr)
+{
+    /* including the 2 's */
+    if(ptr->type == abac_term_verify_term_type("urn") ||
+              ptr->type == abac_term_verify_term_type("string") ) {
+        return strlen(ptr->name)+2; 
+    }
+    return strlen(ptr->name);
+}
+
+char *abac_term_typed_string(abac_term_t *ptr)
+{
+    return abac_term_typed_string_with_condition(ptr);
+}
+
+/********************************************************************/
+abac_param_list_t *abac_param_list_new(abac_term_t *term)
+{
+    abac_param_list_t *ptr=abac_xmalloc(sizeof(abac_param_list_t));
+    ptr->list=abac_list_new();
+    abac_list_add(ptr->list, abac_term_dup(term));
+    return ptr;
+}
+
+abac_param_list_t *abac_param_list_free(abac_param_list_t *ptr)
+{
+    abac_list_t *list=ptr->list;
+    abac_term_t  *cur;
+    abac_list_foreach(list, cur,
+           abac_term_free(cur);
+    );
+    abac_list_free(list);
+    free(ptr);
+}
+
+abac_param_list_t *abac_param_list_add_term(abac_param_list_t *ptr, abac_term_t *term)
+{
+    abac_list_t *list=ptr->list;
+    abac_list_add(list, abac_term_dup(term));
+    return ptr;
+}
+
+
+/* term1:cond1,term2:cond2 */
+char* abac_param_list_string_with_condition(abac_param_list_t *ptr)
+{
+    if(ptr->list == NULL)
+        return "";
+
+    abac_term_t  *cur;
+    char *tmp=NULL, *final=NULL;
+    abac_list_foreach(ptr->list, cur,
+           char *s=abac_term_string_with_condition(cur);
+           if(final==NULL) {
+               final=abac_xstrdup(s);
+               } else {
+                  tmp=final;
+                  final=NULL;
+                  asprintf(&final,"%s,%s",tmp,s);
+                  free(tmp);
+           }
+           free(s);
+    );
+    return final;
+}
+
+/* [type:term1:cond1],[type:term2:cond2] */
+char* abac_param_list_typed_string_with_condition(abac_param_list_t *ptr)
+{
+    if(ptr->list == NULL)
+        return "";
+
+    abac_term_t  *cur;
+    char *tmp=NULL, *final=NULL;
+    abac_list_foreach(ptr->list, cur,
+           char *s=abac_term_typed_string_with_condition(cur);
+           if(final==NULL) {
+               final=abac_xstrdup(s);
+               } else {
+                  tmp=final;
+                  final=NULL;
+                  asprintf(&final,"%s,%s",tmp,s);
+                  if(debug) printf("typed param so far, %s\n", final);
+                  free(tmp);
+           }
+           free(s);
+    );
+    if(debug) printf("typed param so far, %s\n", final);
+    return final;
+}
+
+/* term1,term2 */
+char* abac_param_list_string(abac_param_list_t *ptr)
+{
+    abac_list_t *list=ptr->list;
+    if(list == NULL)
+        return "";
+    abac_term_t  *cur;
+    char *final=NULL;
+    char *tmp=NULL;
+
+    /* collect up all the string */
+    abac_list_foreach(list, cur,
+           char *s=abac_term_string(cur);
+           if(final==NULL) {
+               final=abac_xstrdup(s);
+               } else {
+                  tmp=final;
+                  final=NULL;
+                  asprintf(&final,"%s,%s",tmp,s);
+                  if(debug) printf("param so far, %s\n", final);
+                  free(tmp);
+           }
+           free(s);
+    );
+    if(debug) printf("param so far, %s\n", final);
+    return final;
+}
+
+/* make a stack of it for the abac.hh */
+abac_term_t **abac_param_list_vectorize(abac_param_list_t *ptr)
+{
+    abac_term_t **terms=NULL;
+    abac_list_t *list=ptr->list;
+    int cnt=0;
+    if(list != NULL)
+        cnt=abac_list_size(list);
+    
+    // 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
+    terms = abac_xmalloc(sizeof(abac_term_t *) * (cnt + 1));
+
+    abac_term_t  *cur;
+    int i = 0;
+    if(i<cnt) {
+        abac_list_foreach(list, cur,
+            terms[i++] = abac_term_dup(cur);
+        );
+    }
+    terms[i] = NULL;
+    return terms;
+}
+
+void abac_terms_free(abac_term_t **terms)
+{
+    /* always null terminating */
+    assert(terms);
+    int i; 
+    for (i = 0; terms[i] != NULL; ++i) {
+        abac_term_free(terms[i]);
+    }
+    free(terms);
+}
