commit daba4328d4644b1aeb018957ef5326181e8971b0
parent c1d023dce1b322732ee541d0306fddd0d408534a
Author: William Casarin <jb55@jb55.com>
Date:   Sat, 28 Oct 2017 14:32:53 -0700
some helper macros
Diffstat:
| M | op.h |  |  | 4 | ++-- | 
| M | parser.y |  |  | 2 | +- | 
| M | script.c |  |  | 94 | ++++++++++++++++++++++++++++++++++++++++++++----------------------------------- | 
| M | stack.h |  |  | 39 | +++++++++++++++++++++++++-------------- | 
4 files changed, 80 insertions(+), 59 deletions(-)
diff --git a/op.h b/op.h
@@ -338,12 +338,12 @@ stack_push_val(struct stack *stack, struct val val) {
   val_print(val);
   printf("\n");
 #endif
-  stack_push_small(stack, &val, sizeof(struct val));
+  stack_push_small(struct val, stack, &val);
 }
 
 static inline void
 stack_push_op(struct stack *stack, enum opcode opcode) {
-  stack_push_small(stack, &opcode, sizeof(enum opcode));
+  stack_push_small(enum opcode, stack, &opcode);
 }
 
 static inline struct val
diff --git a/parser.y b/parser.y
@@ -30,7 +30,7 @@ script:
 ;
 
 line: T_NEWLINE
-    | T_OP { stack_push_small(&reader_stack, &$1, 4); }
+    | T_OP { stack_push_small(enum opcode, &reader_stack, &$1); }
     | T_EXAMPLE { ; }
 
 
diff --git a/script.c b/script.c
@@ -4,9 +4,11 @@
 #include "stack.h"
 #include <stdio.h>
 
-int script_add_error(const char *serror) {
+#define SCRIPTERR(serr) script_add_error(c, opcode, serr)
+
+int script_add_error(int c, enum opcode cur_op, const char *serror) {
   // TODO: set_error
-  fprintf(stderr, "error: %s\n", serror);
+  fprintf(stderr, "error: %s @ op %d (%s)\n", serror, c, op_name(cur_op));
   return 0;
 }
 
@@ -57,19 +59,25 @@ script_eval(struct stack *script, struct stack *stack) {
   void **p = script->bottom;
   struct val val;
   struct stack _altstack;
+  struct stack _ifstack;
   struct stack *altstack = &_altstack;
+  struct stack *ifstack = &_ifstack;
   int flags = 0;
+  int c = 0;
   u8 tmpbuf[32];
   stack_init(altstack);
+  stack_init(ifstack);
 
   while (p < script->top) {
+    c++;
     enum opcode opcode = *(enum opcode*)p;
+    int if_exec = !stack_size(ifstack);
     p++;
     // TODO: pushdata ops
     assert(!(opcode >= OP_PUSHDATA1 && opcode <= OP_PUSHDATA4));
 
     if (opcode > OP_16 && ++op_count > MAX_OPS_PER_SCRIPT)
-      script_add_error("MAX_OPS_PER_SCRIPT");
+      SCRIPTERR("MAX_OPS_PER_SCRIPT");
 
     if (opcode == OP_CAT ||
         opcode == OP_SUBSTR ||
@@ -87,7 +95,7 @@ script_eval(struct stack *script, struct stack *stack) {
         opcode == OP_LSHIFT ||
         opcode == OP_RSHIFT) {
 
-      script_add_error("SCRIPT_ERR_DISABLED_OPCODE"); // Disabled opcodes.
+      SCRIPTERR("SCRIPT_ERR_DISABLED_OPCODE"); // Disabled opcodes.
     }
 
 
@@ -125,42 +133,42 @@ script_eval(struct stack *script, struct stack *stack) {
       }
       break;
 
-    /* case OP_IF: */
-    /* case OP_NOTIF: */
-    /* { */
-    /*     // <expression> if [statements] [else [statements]] endif */
-    /*     int fval = 0; */
-    /*     if (fExec) */
-    /*     { */
-    /*         if (stack.size() < 1) */
-    /*             return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); */
-    /*         valtype& vch = stacktop(-1); */
-    /*         if (sigversion == SIGVERSION_WITNESS_V0 && (flags & SCRIPT_VERIFY_MINIMALIF)) { */
-    /*             if (vch.size() > 1) */
-    /*                 return set_error(serror, SCRIPT_ERR_MINIMALIF); */
-    /*             if (vch.size() == 1 && vch[0] != 1) */
-    /*                 return set_error(serror, SCRIPT_ERR_MINIMALIF); */
-    /*         } */
-    /*         fValue = CastToBool(vch); */
-    /*         if (opcode == OP_NOTIF) */
-    /*             fValue = !fValue; */
-    /*         popstack(stack); */
-    /*     } */
-    /*     vfExec.push_back(fValue); */
-    /* } */
-    /* break; */
+    case OP_IF:
+    case OP_NOTIF:
+    {
+        // <expression> if [statements] [else [statements]] endif
+        int ifval = 0;
+        if (if_exec)
+        {
+            if (stack_size(stack) < 1)
+              return SCRIPTERR("SCRIPT_ERR_UNBALANCED_CONDITIONAL");
+            struct val val = stack_top_val(stack, -1);
+            /* if (sigversion == SIGVERSION_WITNESS_V0 && (flags & SCRIPT_VERIFY_MINIMALIF)) { */
+            /*     if (vch.size() > 1) */
+            /*         return SCRIPTERR(SCRIPT_ERR_MINIMALIF); */
+            /*     if (vch.size() == 1 && vch[0] != 1) */
+            /*         return SCRIPTERR(SCRIPT_ERR_MINIMALIF); */
+            /* } */
+            ifval = cast_to_bool(val);
+            if (opcode == OP_NOTIF)
+                ifval = !ifval;
+            stack_pop(stack);
+        }
+        stack_push_small(int, ifstack, &ifval);
+    }
+    break;
 
 
     case OP_INVALIDOPCODE:
     {
-      return script_add_error("SCRIPT_ERR_INVALID_OPCODE");
+      return SCRIPTERR("SCRIPT_ERR_INVALID_OPCODE");
     }
     break;
 
     case OP_FROMALTSTACK:
     {
         if (stack_size(altstack) < 1)
-            return script_add_error("SCRIPT_ERR_INVALID_ALTSTACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_ALTSTACK_OPERATION");
         stack_push(stack, stack_top(altstack, -1));
         stack_pop(altstack);
     }
@@ -170,7 +178,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x1 x2 -- )
         if (stack_size(stack) < 2)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         stack_pop(stack);
         stack_pop(stack);
     }
@@ -180,7 +188,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x1 x2 -- x1 x2 x1 x2)
         if (stack_size(stack) < 2)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         struct val v1 = stack_top_val(stack, -2);
         struct val v2 = stack_top_val(stack, -1);
         stack_push_val(stack, v1);
@@ -192,7 +200,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3)
         if (stack_size(stack) < 3)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         struct val v1 = stack_top_val(stack, -3);
         struct val v2 = stack_top_val(stack, -2);
         struct val v3 = stack_top_val(stack, -1);
@@ -206,7 +214,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2)
         if (stack_size(stack) < 4)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         struct val v1 = stack_top_val(stack, -4);
         struct val v2 = stack_top_val(stack, -3);
         stack_push_val(stack, v1);
@@ -218,7 +226,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2)
         if (stack_size(stack) < 6)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         struct val t6 = stack_top_val(stack, -6);
         struct val t5 = stack_top_val(stack, -5);
         *(stack->top - 6) = *(stack->top - 4);
@@ -234,7 +242,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x1 x2 x3 x4 -- x3 x4 x1 x2)
         if (stack_size(stack) < 4)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
 
         struct val t4 = stack_top_val(stack, -4);
         struct val t3 = stack_top_val(stack, -3);
@@ -250,7 +258,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x - 0 | x x)
         if (stack_size(stack) < 1)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         struct val val = stack_top_val(stack, -1);
         if (cast_to_bool(val))
             stack_push_val(stack, val);
@@ -269,7 +277,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
       // (x -- )
       if (stack_size(stack) < 1)
-          return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+        return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
       stack_pop(stack);
     }
     break;
@@ -278,7 +286,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x -- x x)
         if (stack_size(stack) < 1)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         struct val val = stack_top_val(stack, (-1));
         stack_push_val(stack, val);
     }
@@ -288,7 +296,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x1 x2 -- x2)
         if (stack_size(stack) < 2)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         // TODO: sanity check - stack_size() == stack_end(stack)
         stack_set_val(stack, -2, stack_top_val(stack, -1));
         stack_pop(stack);
@@ -299,7 +307,7 @@ script_eval(struct stack *script, struct stack *stack) {
     {
         // (x1 x2 -- x1 x2 x1)
         if (stack_size(stack) < 2)
-            return script_add_error("SCRIPT_ERR_INVALID_STACK_OPERATION");
+          return SCRIPTERR("SCRIPT_ERR_INVALID_STACK_OPERATION");
         struct val val = stack_top_val(stack, (-2));
         stack_push_val(stack, val);
     }
@@ -307,12 +315,14 @@ script_eval(struct stack *script, struct stack *stack) {
 
     default: {
       sprintf((char*)tmpbuf, "unhandled opcode %s", op_name(opcode));
-      return script_add_error((char*)tmpbuf);
+      return SCRIPTERR((char*)tmpbuf);
     }
 
     }
   }
 
+  stack_free(altstack);
+  stack_free(ifstack);
   return 1;
 }
 
diff --git a/stack.h b/stack.h
@@ -41,20 +41,31 @@ stack_size(struct stack *stack) {
   return stack->top - stack->bottom;
 }
 
-static inline void
-stack_push_small(struct stack *stack, void *p, size_t size) {
-#if 0
-  u8 *b = (u8*)p;
-  printf("pushing small", "");
-  for (size_t i = 0; i < size; ++i) {
-    printf(" %02x", b[i]);
-  }
-  printf("\n");
-#endif
-  assert(size <= sizeof(void*));
-  void *tmp = 0;
-  memcpy(&tmp, p, size);
-  stack_push(stack, tmp);
+#define stack_push_small(T, stack, val) { \
+  assert(sizeof(T) <= sizeof(void*)); \
+  void *tmp = 0; \
+  memcpy(&tmp, val, sizeof(T));                    \
+  stack_push(stack, tmp); \
 }
 
+#define stack_top_small(T, stack, ind) {       \
+    memcpy(val, stack_top(stack, ind));  \
+  }
+
+/* static inline void */
+/* _stack_push_smallt(struct stack *stack, void *p, size_t size) { */
+/* #if 0 */
+/*   u8 *b = (u8*)p; */
+/*   printf("pushing small", ""); */
+/*   for (size_t i = 0; i < size; ++i) { */
+/*     printf(" %02x", b[i]); */
+/*   } */
+/*   printf("\n"); */
+/* #endif */
+/*   assert(size <= sizeof(void*)); */
+/*   void *tmp = 0; */
+/*   memcpy(&tmp, p, size); */
+/*   stack_push(stack, tmp); */
+/* } */
+
 #endif /* BTCS_STACK_H */