]> git.pond.sub.org Git - empserver/blobdiff - src/lib/common/nstreval.c
Virtual selectors
[empserver] / src / lib / common / nstreval.c
index c730ff5aaf98bde5cc00e16b4a3b0e80f3e0bc7f..ab49f84196c80f2ab0f65aa689858baef7aafe98 100644 (file)
@@ -36,6 +36,7 @@
 #include <config.h>
 
 #include <limits.h>
+#include <string.h>
 #include "file.h"
 #include "nat.h"
 #include "nsc.h"
 /*
  * Evaluate VAL.
  * If VAL is symbolic, evaluate it into a promoted value type.
- * Use coordinate system of country CNUM.
+ * Use country CNUM's coordinate system and access control.
  * PTR points to a context object of the type that was used to compile
  * the value.
  * Unless WANT is NSC_NOTYPE, coerce the value to promoted value type
  * WANT.  VAL must be coercible.  That's the case if a previous
  * nstr_coerce_val(VAL, WANT, STR) succeeded.
  */
-void
+struct valstr *
 nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want)
 {
     char *memb_ptr;
@@ -60,14 +61,25 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want)
     int idx;
     struct natstr *natp;
 
+    if (CANT_HAPPEN(want != NSC_NOTYPE && !NSC_IS_PROMOTED(want)))
+       want = nstr_promote(want);
+
     switch (val->val_cat) {
-    default:
-       CANT_REACH();
-       /* fall through */
     case NSC_VAL:
        valtype = val->val_type;
        break;
     case NSC_OFF:
+       if (val->val_as.sym.get) {
+           do {
+               ptr = val->val_as.sym.get(val, cnum, ptr);
+           } while (ptr && val->val_as.sym.get);
+           if (!ptr) {
+               valtype = val->val_type;
+               val->val_cat = NSC_VAL;
+               break;
+           }
+       }
+
        valtype = NSC_LONG;
        memb_ptr = ptr;
        memb_ptr += val->val_as.sym.off;
@@ -134,6 +146,10 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want)
            val->val_as.lng = 0;
        }
        val->val_cat = NSC_VAL;
+       break;
+    default:
+       CANT_REACH();
+       valtype = NSC_NOTYPE;
     }
 
     if (valtype == want)
@@ -147,17 +163,13 @@ nstr_exec_val(struct valstr *val, natid cnum, void *ptr, nsc_type want)
        CANT_REACH();           /* FIXME implement */
 
     if (CANT_HAPPEN(valtype != want && want != NSC_NOTYPE)) {
+       /* make up an error value */
        valtype = want;
-       switch (want) {
-       case NSC_LONG: val->val_as.lng = 0; break;
-       case NSC_DOUBLE: val->val_as.dbl = 0.0; break;
-       case NSC_STRING: val->val_as.str.base = NULL; break;
-       default:
-           CANT_REACH();
-       }
+       memset(&val->val_as, 0, sizeof(val->val_as));
     }
 
     val->val_type = valtype;
+    return val;
 }
 
 /*