expression compiler generates byte code

Sat, 30 May 2015 13:49:17 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 30 May 2015 13:49:17 +0200
changeset 124
41939c8f3f9c
parent 123
806c4dccf2ae
child 125
5e2576b08680

expression compiler generates byte code

dav/main.c file | annotate | diff | comparison | revisions
libidav/davqlexec.c file | annotate | diff | comparison | revisions
libidav/davqlexec.h file | annotate | diff | comparison | revisions
libidav/utils.c file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
--- a/dav/main.c	Fri May 29 14:16:45 2015 +0200
+++ b/dav/main.c	Sat May 30 13:49:17 2015 +0200
@@ -55,10 +55,10 @@
 #include <libidav/davqlexec.h>
 void test() {
     DavQLStatement *stmt = dav_parse_statement(S(
-        "get * from / where (better or func(x, y, 1+1)) and -a = 2"));
+        "get * from / where name unlike '%d.%s'"));
     
     DavSession *sn = dav_session_new(ctx, "http://test/");
-    dav_statement_exec(sn, stmt);
+    dav_statement_exec(sn, stmt, 123, "txt");
     dav_debug_statement(stmt);
     dav_free_statement(stmt);
 }
--- a/libidav/davqlexec.c	Fri May 29 14:16:45 2015 +0200
+++ b/libidav/davqlexec.c	Sat May 30 13:49:17 2015 +0200
@@ -31,8 +31,8 @@
 #include <string.h>
 
 #include <ucx/utils.h>
-
 #include "davqlexec.h"
+#include "utils.h"
 
 DavQLResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) {
     va_list ap;
@@ -54,10 +54,10 @@
     
     // get path string
     davqlerror_t error;
-    UcxBuffer *path = dav_path_string(st->path, ap, &error);
+    sstr_t path = dav_format_string(sn->mp->allocator, st->path, ap, &error);
     
     if(st->type == DAVQL_GET) {
-        dav_exec_get(sn, st, path->space, ap);
+        dav_exec_get(sn, st, path.ptr, ap);
     } else {
         // TODO
     }
@@ -65,38 +65,37 @@
     return result;
 }
 
-UcxBuffer* dav_path_string(sstr_t pathfmt, va_list ap, davqlerror_t *error) {
-    UcxBuffer *path = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND);
+sstr_t dav_format_string(UcxAllocator *a, sstr_t fstr, va_list ap, davqlerror_t *error) {
+    UcxBuffer *buf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND);
     
     int placeholder = 0;
-    for(int i=0;i<pathfmt.length;i++) {
-        char c = pathfmt.ptr[i];
+    for(int i=0;i<fstr.length;i++) {
+        char c = fstr.ptr[i];
         if(placeholder) {
             if(c == '%') {
                 // no placeholder, %% transposes to %
-                ucx_buffer_putc(path, c);
+                ucx_buffer_putc(buf, c);
             } else {
                 // detect placeholder type and insert arg
                 int err = 0;
                 switch(c) {
                     case 's': {
                         char *arg = va_arg(ap, char*);
-                        ucx_buffer_puts(path, arg);
+                        ucx_buffer_puts(buf, arg);
                         break;
                     }
                     case 'd': {
                         int arg = va_arg(ap, int);
-                        ucx_bprintf(path, "%d", arg);
+                        ucx_bprintf(buf, "%d", arg);
                         break;
                     }
                     case 'u': {
                         unsigned int arg = va_arg(ap, unsigned int);
-                        ucx_bprintf(path, "%u", arg);
+                        ucx_bprintf(buf, "%u", arg);
                         break;
                     }
                     case 't': {
-                        // time arguments doesn't make any sense in a path
-                        *error = DAVQL_UNSUPPORTED_FORMATCHAR;
+                        // time arguments not supported for strings
                         err = 1;
                         break;
                     }
@@ -106,8 +105,11 @@
                     }
                 }
                 if(err) {
-                    ucx_buffer_free(path);
-                    return NULL;
+                    ucx_buffer_free(buf);
+                    sstr_t n;
+                    n.ptr = NULL;
+                    n.length = 0;
+                    return n;
                 }
             }
             placeholder = 0;
@@ -115,22 +117,24 @@
             if(c == '%') {
                 placeholder = 1;
             } else {
-                ucx_buffer_putc(path, c);
+                ucx_buffer_putc(buf, c);
             }
         }
     }
-    ucx_buffer_putc(path, '\0');
     *error = DAVQL_OK;
-    return path;
+    
+    return sstrdup_a(a, sstrn(buf->space, buf->size));
 }
 
 void dav_exec_get(DavSession *sn, DavQLStatement *st, char* path, va_list ap) {
     // execute a davql get statement
+    UcxMempool *mp = ucx_mempool_new(128);
     
     // TODO: get property list
     
-    UcxBuffer *bcode = dav_compile_lexpr(st->where);
-    printf("bcode: %.*s\n", bcode->size, bcode->space);
+    UcxBuffer *bcode = dav_compile_expr(mp->allocator, st->where, ap);
+    
+    print_bytecode(bcode);
 }
 
 static int count_func_args(DavQLExpression *expr) {
@@ -147,150 +151,207 @@
     return count;
 }
 
-static int add_cmd(UcxBuffer *bcode, DavQLExpression *expr) {
+static int add_cmd(UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) {
     if(!expr) {
         return 0;
     }
+     
+    int numcmd = 1;
+    DavQLCmd cmd;
+    memset(&cmd, sizeof(DavQLCmd), 0);
+    davqlerror_t error;
     
-    int numcmd = 1;
     sstr_t src = expr->srctext;
     switch(expr->type) {
-        case DAVQL_NUMBER: {
-            ucx_bprintf(bcode, "number(%.*s) ", src.length, src.ptr);
+        case DAVQL_NUMBER: {   
+            cmd.type = DAVQL_CMD_INT;
+            if(src.ptr[0] == '%') {
+                cmd.data.integer = va_arg(ap, int);
+            } else if(util_strtoint(src.ptr, &cmd.data.integer)) {
+                ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
+            } else {
+                // error
+                return -1;
+            }
+            
             break;
         }
         case DAVQL_STRING: {
-            // TODO: check format specifier
-            ucx_bprintf(bcode, "string(%.*s) ", src.length, src.ptr);
+            cmd.type = DAVQL_CMD_STRING;
+            cmd.data.string = dav_format_string(a, src, ap, &error);
+            ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
             break;
         }
         case DAVQL_TIMESTAMP: {
-            ucx_bprintf(bcode, "timestamp(%.*s) ", src.length, src.ptr);
+            if(src.ptr[0] == '%') {
+                cmd.data.timestamp = va_arg(ap, time_t);
+                ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
+            } else {
+                // error
+                return -1;
+            }
             break;
         }
         case DAVQL_IDENTIFIER: {
-            // TODO: check identifier type
-            ucx_bprintf(bcode, "identifier(%.*s) ", src.length, src.ptr);
+            sstr_t propertyname = sstrchr(src, ':');
+            cmd.type = DAVQL_CMD_RES_IDENTIFIER;
+            if(propertyname.length > 0) {
+                cmd.type = DAVQL_CMD_PROP_IDENTIFIER;
+                
+                // TODO
+            } else if(!sstrcmp(src, S("name"))) {
+                cmd.data.resprop = DAVQL_RES_NAME;
+            } else if(!sstrcmp(src, S("path"))) {
+                cmd.data.resprop = DAVQL_RES_PATH;
+            } else if(!sstrcmp(src, S("href"))) {
+                cmd.data.resprop = DAVQL_RES_HREF;
+            } else if(!sstrcmp(src, S("contentlength"))) {
+                cmd.data.resprop = DAVQL_RES_CONTENTLENGTH;
+            } else if(!sstrcmp(src, S("contenttype"))) {
+                cmd.data.resprop = DAVQL_RES_CONTENTTYPE;
+            } else if(!sstrcmp(src, S("creationdate"))) {
+                cmd.data.resprop = DAVQL_RES_CREATIONDATE;
+            } else if(!sstrcmp(src, S("lastmodified"))) {
+                cmd.data.resprop = DAVQL_RES_LASTMODIFIED;
+            } else if(!sstrcmp(src, S("iscollection"))) {
+                cmd.data.resprop = DAVQL_RES_ISCOLLECTION;
+            }
+            ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
             break;
         }
         case DAVQL_UNARY: {
-            numcmd += add_cmd(bcode, expr->left);
+            numcmd += add_cmd(a, bcode, expr->left, ap);
             switch(expr->op) {
                 case DAVQL_ADD: {
-                    ucx_bprintf(bcode, "unop_add ");
+                    cmd.type = DAVQL_CMD_OP_UNARY_ADD;
                     break;
                 }
                 case DAVQL_SUB: {
-                    ucx_bprintf(bcode, "unop_sub ");
+                    cmd.type = DAVQL_CMD_OP_UNARY_SUB;
                     break;
                 }
                 case DAVQL_NEG: {
-                    ucx_bprintf(bcode, "unop_neg ");
+                    cmd.type = DAVQL_CMD_OP_UNARY_NEG;
                     break;
                 }
             }
+            ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
             break;
         }
         case DAVQL_BINARY: {
-            numcmd += add_cmd(bcode, expr->left);
-            numcmd += add_cmd(bcode, expr->right);
+            numcmd += add_cmd(a, bcode, expr->left, ap);
+            numcmd += add_cmd(a, bcode, expr->right, ap);
             switch(expr->op) {
                 case DAVQL_ADD: {
-                    ucx_bprintf(bcode, "binop_add ");
+                    cmd.type = DAVQL_CMD_OP_BINARY_ADD;
                     break;
                 }
                 case DAVQL_SUB: {
-                    ucx_bprintf(bcode, "binop_sub ");
+                    cmd.type = DAVQL_CMD_OP_BINARY_SUB;
                     break;
                 }
                 case DAVQL_MUL: {
-                    ucx_bprintf(bcode, "binop_sub ");
+                    cmd.type = DAVQL_CMD_OP_BINARY_MUL;
                     break;
                 }
                 case DAVQL_DIV: {
-                    ucx_bprintf(bcode, "binop_sub ");
+                    cmd.type = DAVQL_CMD_OP_BINARY_DIV;
                     break;
                 }
                 case DAVQL_AND: {
-                    ucx_bprintf(bcode, "binop_sub ");
+                    cmd.type = DAVQL_CMD_OP_BINARY_AND;
                     break;
                 }
                 case DAVQL_OR: {
-                    ucx_bprintf(bcode, "binop_sub ");
+                    cmd.type = DAVQL_CMD_OP_BINARY_OR;
                     break;
                 }
                 case DAVQL_XOR: {
-                    ucx_bprintf(bcode, "binop_sub ");
+                    cmd.type = DAVQL_CMD_OP_BINARY_XOR;
                     break;
                 }
             }
+            ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
             break;
         }
         case DAVQL_LOGICAL: {
             if(expr->left && expr->right && expr->op != DAVQL_LOR) {
-                numcmd += add_cmd(bcode, expr->left);
-                numcmd += add_cmd(bcode, expr->right);
+                numcmd += add_cmd(a, bcode, expr->left, ap);
+                numcmd += add_cmd(a, bcode, expr->right, ap);
             }
             
             switch(expr->op) {
-                case DAVQL_NOOP: {
-                    break;
-                }
                 case DAVQL_NOT: {
-                    numcmd += add_cmd(bcode, expr->left);
-                    ucx_bprintf(bcode, "op_not ");
+                    numcmd += add_cmd(a, bcode, expr->left, ap);
+                    cmd.type = DAVQL_CMD_OP_LOGICAL_NOT;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_LAND: {
-                    ucx_bprintf(bcode, "op_land ");
+                    cmd.type = DAVQL_CMD_OP_LOGICAL_NOT;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_LOR: {
-                    int nleft = add_cmd(bcode, expr->left);
-                    ucx_bprintf(bcode, "op_lor_left(    ) ");
-                    char *bcode_pos = bcode->space + bcode->size - 6;
-                    int nright = add_cmd(bcode, expr->right);
-                    char buf[5];
-                    ssize_t n = snprintf(buf, 4, "%d", nright);
-                    memcpy(bcode_pos, buf, n);
-                    ucx_bprintf(bcode, "op_lor ");
+                    int nleft = add_cmd(a, bcode, expr->left, ap);
+                    
+                    cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L;
+                    DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos);
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
+                    
+                    int nright = add_cmd(a, bcode, expr->right, ap);
+                    or_l->data.integer = nright + 1;
+                    
+                    cmd.type = DAVQL_CMD_OP_LOGICAL_OR;
+                    cmd.data.integer = 0;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
+                    
                     numcmd += nleft + nright;
                     break;
                 }
                 case DAVQL_LXOR: {
-                    ucx_bprintf(bcode, "op_lxor ");
+                    cmd.type = DAVQL_CMD_OP_LOGICAL_XOR;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_EQ: {
-                    ucx_bprintf(bcode, "op_eq ");
+                    cmd.type = DAVQL_CMD_OP_EQ;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_NEQ: {
-                    ucx_bprintf(bcode, "op_neq ");
+                    cmd.type = DAVQL_CMD_OP_NEQ;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_LT: {
-                   ucx_bprintf(bcode, "op_lt ");
+                    cmd.type = DAVQL_CMD_OP_LT;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_GT: {
-                    ucx_bprintf(bcode, "op_gt ");
+                    cmd.type = DAVQL_CMD_OP_GT;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_LE: {
-                    ucx_bprintf(bcode, "op_le ");
+                    cmd.type = DAVQL_CMD_OP_LE;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_GE: {
-                    ucx_bprintf(bcode, "op_ge ");
+                    cmd.type = DAVQL_CMD_OP_GE;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_LIKE: {
-                    ucx_bprintf(bcode, "op_like ");
+                    cmd.type = DAVQL_CMD_OP_LIKE;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_UNLIKE: {
-                    ucx_bprintf(bcode, "op_unlike ");
+                    cmd.type = DAVQL_CMD_OP_UNLIKE;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
             }
@@ -299,7 +360,7 @@
         case DAVQL_FUNCCALL: {
             switch(expr->op) {
                 case DAVQL_CALL: {
-                    int nright = add_cmd(bcode, expr->right);
+                    int nright = add_cmd(a, bcode, expr->right, ap);
                     // TODO: count args
                     DavQLExpression *funcid = expr->left;
                     if(!funcid && funcid->type != DAVQL_IDENTIFIER) {
@@ -307,15 +368,24 @@
                         return -1;
                     }
                     
-                    ucx_bprintf(bcode, "funcname(%.*s) numargs(%d) call ", funcid->srctext.length, funcid->srctext.ptr, count_func_args(expr));
-                    numcmd = 3;
+                    // numargs
+                    cmd.type = DAVQL_CMD_INT;
+                    cmd.data.integer = count_func_args(expr);
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
+                    
+                    // TODO: resolve function name
+                    cmd.type = DAVQL_CMD_CALL;
+                    cmd.data.func = NULL;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
+                    
+                    numcmd = 2;
                     numcmd += nright;
                     break;
                 }
                 case DAVQL_ARGLIST: {
                     numcmd = 0;
-                    numcmd += add_cmd(bcode, expr->left);
-                    numcmd += add_cmd(bcode, expr->right);
+                    numcmd += add_cmd(a, bcode, expr->left, ap);
+                    numcmd += add_cmd(a, bcode, expr->right, ap);
                     break;
                 }
             }
@@ -325,13 +395,145 @@
     return numcmd;
 }
 
-UcxBuffer* dav_compile_lexpr(DavQLExpression *lexpr) {
+UcxBuffer* dav_compile_expr(UcxAllocator *a, DavQLExpression *lexpr, va_list ap) {
     UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND);
     if(!bcode) {
         return NULL;
     }
     
-    int numcmd = add_cmd(bcode, lexpr);
+    if(add_cmd(a, bcode, lexpr, ap) <= 0) {
+        ucx_buffer_free(bcode);
+        return NULL;
+    }
     
     return bcode;
 }
+
+
+void print_bytecode(UcxBuffer *bcode) {
+    bcode->pos = 0;
+    DavQLCmd cmd;
+    while(ucx_buffer_read(&cmd, sizeof(DavQLCmd), 1, bcode) == 1) {
+        switch(cmd.type) {
+            case DAVQL_CMD_INT: {
+                printf("int %ll\n", cmd.data.integer);
+                break;
+            }
+            case DAVQL_CMD_STRING: {
+                printf("string \"%.*s\"\n", cmd.data.string.length, cmd.data.string.ptr);
+                break;
+            }
+            case DAVQL_CMD_TIMESTAMP: {
+                printf("timestamp %d\n", cmd.data.timestamp);
+                break;
+            }
+            case DAVQL_CMD_RES_IDENTIFIER: {
+                char *rid[8] = {"name", "path", "href", "contentlength", "contenttype", "creationdate", "lastmodified", "iscollection"};
+                printf("resprop %s\n", rid[cmd.data.resprop]);
+                break;
+            }
+            case DAVQL_CMD_PROP_IDENTIFIER: {
+                printf("property %s:%s\n", cmd.data.property.ns, cmd.data.property.name);
+                break;
+            }
+            case DAVQL_CMD_OP_UNARY_ADD: {
+                printf("uadd\n");
+                break;
+            }
+            case DAVQL_CMD_OP_UNARY_SUB: {
+                printf("usub\n");
+                break;
+            }
+            case DAVQL_CMD_OP_UNARY_NEG: {
+                printf("uneg\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_ADD: {
+                printf("add\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_SUB: {
+                printf("sub\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_MUL: {
+                printf("mul\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_DIV: {
+                printf("div\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_AND: {
+                printf("and\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_OR: {
+                printf("or\n");
+                break;
+            }
+            case DAVQL_CMD_OP_BINARY_XOR: {
+                printf("xor\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_NOT: {
+                printf("not\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_AND: {
+                printf("land\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_OR_L: {
+                printf("or_l %d\n", cmd.data.integer);
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_OR: {
+                printf("or\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LOGICAL_XOR: {
+                printf("lxor\n");
+                break;
+            }
+            case DAVQL_CMD_OP_EQ: {
+                printf("eq\n");
+                break;
+            }
+            case DAVQL_CMD_OP_NEQ: {
+                printf("neq\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LT: {
+                printf("lt\n");
+                break;
+            }
+            case DAVQL_CMD_OP_GT: {
+                printf("gt\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LE: {
+                printf("le\n");
+                break;
+            }
+            case DAVQL_CMD_OP_GE: {
+                printf("ge\n");
+                break;
+            }
+            case DAVQL_CMD_OP_LIKE: {
+                printf("like\n");
+                break;
+            }
+            case DAVQL_CMD_OP_UNLIKE: {
+                printf("unlike\n");
+                break;
+            }
+            case DAVQL_CMD_CALL: {
+                printf("call %x\n", cmd.data.func);
+                break;
+            }
+        }
+    }
+    printf("\n");
+}
+
--- a/libidav/davqlexec.h	Fri May 29 14:16:45 2015 +0200
+++ b/libidav/davqlexec.h	Sat May 30 13:49:17 2015 +0200
@@ -38,7 +38,10 @@
 extern "C" {
 #endif
 
-typedef struct DavQLResult DavQLResult;
+typedef struct DavQLCmd      DavQLCmd;
+typedef struct DavQLStackObj DavQLStackObj;
+
+typedef void*(*davql_func)(); // TODO: interface?
 
 typedef enum {
     DAVQL_OK = 0,
@@ -46,22 +49,82 @@
     DAVQL_UNKNOWN_FORMATCHAR
 } davqlerror_t;
 
-struct DavQLResult {
-    DavResource *result;
-    int         status;
+typedef enum {
+    DAVQL_CMD_INT = 0,
+    DAVQL_CMD_STRING,
+    DAVQL_CMD_TIMESTAMP,
+    DAVQL_CMD_RES_IDENTIFIER,
+    DAVQL_CMD_PROP_IDENTIFIER,
+    DAVQL_CMD_OP_UNARY_ADD,
+    DAVQL_CMD_OP_UNARY_SUB,
+    DAVQL_CMD_OP_UNARY_NEG,
+    DAVQL_CMD_OP_BINARY_ADD,
+    DAVQL_CMD_OP_BINARY_SUB,
+    DAVQL_CMD_OP_BINARY_MUL,
+    DAVQL_CMD_OP_BINARY_DIV,
+    DAVQL_CMD_OP_BINARY_AND,
+    DAVQL_CMD_OP_BINARY_OR,
+    DAVQL_CMD_OP_BINARY_XOR,
+    DAVQL_CMD_OP_LOGICAL_NOT,
+    DAVQL_CMD_OP_LOGICAL_AND,
+    DAVQL_CMD_OP_LOGICAL_OR_L,
+    DAVQL_CMD_OP_LOGICAL_OR,
+    DAVQL_CMD_OP_LOGICAL_XOR,
+    DAVQL_CMD_OP_EQ,
+    DAVQL_CMD_OP_NEQ,
+    DAVQL_CMD_OP_LT,
+    DAVQL_CMD_OP_GT,
+    DAVQL_CMD_OP_LE,
+    DAVQL_CMD_OP_GE,
+    DAVQL_CMD_OP_LIKE,
+    DAVQL_CMD_OP_UNLIKE,
+    DAVQL_CMD_CALL
+} davqlcmdtype_t;
+
+typedef enum {
+    DAVQL_RES_NAME = 0,
+    DAVQL_RES_PATH,
+    DAVQL_RES_HREF,
+    DAVQL_RES_CONTENTLENGTH,
+    DAVQL_RES_CONTENTTYPE,
+    DAVQL_RES_CREATIONDATE,
+    DAVQL_RES_LASTMODIFIED,
+    DAVQL_RES_ISCOLLECTION
+} davqlresprop_t;
+
+struct DavQLCmd {
+    davqlcmdtype_t type;
+    union DavQLCmdData {
+        int64_t        integer;
+        sstr_t         string;
+        time_t         timestamp;
+        davqlresprop_t resprop;
+        DavPropName    property;
+        davql_func     func;
+    } data;
+};
+
+struct DavQLStackObj {
+    int32_t  type; // 0: int, 1: string
+    uint32_t length;
+    union DavQLStackData {
+        int64_t integer;
+        char    *string;
+    } data;
 };
     
 DavQLResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...);
 DavQLResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap);
 
 UcxBuffer* dav_path_string(sstr_t src, va_list ap, davqlerror_t *error);
+sstr_t dav_format_string(UcxAllocator *a, sstr_t fstr, va_list ap, davqlerror_t *error);
 
 void dav_exec_get(DavSession *sn, DavQLStatement *st, char* path, va_list ap);
 
-UcxBuffer* dav_compile_lexpr(DavQLExpression *lexpr);
+UcxBuffer* dav_compile_expr(UcxAllocator *a, DavQLExpression *lexpr, va_list ap);
 
 
-
+void print_bytecode(UcxBuffer *bcode);
 
 #ifdef	__cplusplus
 }
--- a/libidav/utils.c	Fri May 29 14:16:45 2015 +0200
+++ b/libidav/utils.c	Sat May 30 13:49:17 2015 +0200
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 #include <ucx/string.h>
 #include <ucx/buffer.h>
 #include <ucx/utils.h>
@@ -75,8 +76,9 @@
 
 int util_strtoint(char *str, int64_t *value) {
     char *end;
+    errno = 0;
     int64_t val = strtoll(str, &end, 0);
-    if(strlen(end) == 0) {
+    if(errno == 0) {
         *value = val;
         return 1;
     } else {
--- a/libidav/webdav.h	Fri May 29 14:16:45 2015 +0200
+++ b/libidav/webdav.h	Sat May 30 13:49:17 2015 +0200
@@ -45,7 +45,7 @@
 typedef struct DavProxy      DavProxy;
 typedef struct DavSession    DavSession;
 typedef struct DavResource   DavResource;
-typedef struct DavRequest    DavRequest;
+typedef struct DavQLResult   DavQLResult;
 typedef struct DavNamespace  DavNamespace;
 typedef struct DavProperty   DavProperty;
 typedef struct DavPropName   DavPropName;
@@ -145,6 +145,11 @@
     char *name;
 };
 
+struct DavQLResult {
+    DavResource *result;
+    int         status;
+};
+
 #define DAV_KEY_AES128     0
 #define DAV_KEY_AES256     1
 #define DAV_KEY_PASSWORD   2

mercurial