Tue, 31 Mar 2015 10:18:55 +0200
UCX string module update
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2015 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "davqlparser.h" #include <string.h> #include <stdio.h> #define sfmtarg(s) ((int)(s).length), (s).ptr static const char* _map_querytype(davqltype_t type) { switch(type) { case GET: return "GET"; case SET: return "SET"; default: return "unknown"; } } static const char* _map_exprtype(davqlexprtype_t type) { switch(type) { case LITERAL: return "LITERAL"; case IDENTIFIER: return "IDENTIFIER"; case UNARY: return "UNARY"; case BINARY: return "BINARY"; case LOGICAL: return "LOGICAL"; case FUNCCALL: return "FUNCCALL"; default: return "unknown"; } } static const char* _map_operator(davqloperator_t op) { // don't use string array, because enum values may change switch(op) { case ADD: return "+"; case SUB: return "-"; case MUL: return "*"; case DIV: return "/"; case AND: return "&"; case OR: return "|"; case XOR: return "^"; case NEG: return "~"; case NOT: return "NOT"; case LAND: return "AND"; case LOR: return "OR"; case LXOR: return "XOR"; case EQ: return "="; case NEQ: return "!="; case LT: return "<"; case GT: return ">"; case LE: return "<="; case GE: return ">="; case LIKE: return "LIKE"; case UNLIKE: return "UNLIKE"; default: return "unknown"; } } static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { // Basic information printf("Statement: %*s\nType: %s\nField count: %zu", sfmtarg(stmt->srctext), _map_querytype(stmt->type), ucx_list_size(stmt->fields)); // Has wildcard _Bool wildcard = 0; UCX_FOREACH(elm, stmt->fields) { DavQLExpression* expr = (DavQLExpression*)elm->data; if (expr->type == IDENTIFIER && expr->srctext.length == 1 && *(expr->srctext.ptr) == '*') { wildcard = 1; } } printf(" %s wildcard\nPath: %*s\nHas where clause: %s\n", wildcard?"with":"without", sfmtarg(stmt->path.srctext), stmt->where ? "yes" : "no"); if (stmt->type == SET) { printf("Value list size matches: %s", ucx_list_size(stmt->fields) == ucx_list_size(stmt->setvalues) ? "yes" : "no"); } // WITH attributes if (stmt->depth == SIZE_MAX) { printf("Depth: unbound\n"); } else { printf("Depth: %zu\n", stmt->depth); } } static int dav_debug_ql_expr_selected(DavQLExpression *expr) { if (!expr) { printf("Currently no expression selected.\n"); return 0; } else { return 1; } } static void dav_debug_ql_expr_print(DavQLExpression *expr) { if (dav_debug_ql_expr_selected(expr)) { sstr_t empty = S("(empty)"); printf( "Text: %*s\nType: %s\nOperator: %s\n" "Left hand: %*s\nRight hand: %*s\n", sfmtarg(expr->srctext), _map_exprtype(expr->type), _map_operator(expr->op), sfmtarg(expr->left?expr->left->srctext:empty), sfmtarg(expr->right?expr->right->srctext:empty)); } } #define DQLD_CMD_Q 0 #define DQLD_CMD_PS 1 #define DQLD_CMD_PE 2 #define DQLD_CMD_P 10 #define DQLD_CMD_L 21 #define DQLD_CMD_R 22 #define DQLD_CMD_H 100 static int dav_debug_ql_command() { printf("> "); char buffer[16]; fgets(buffer, 16, stdin); if (!strcmp(buffer, "q\n")) { return DQLD_CMD_Q; } else if (!strcmp(buffer, "ps\n")) { return DQLD_CMD_PS; } else if (!strcmp(buffer, "pe\n")) { return DQLD_CMD_PE; } else if (!strcmp(buffer, "p\n")) { return DQLD_CMD_P; } else if (!strcmp(buffer, "l\n")) { return DQLD_CMD_L; } else if (!strcmp(buffer, "r\n")) { return DQLD_CMD_R; } else if (!strcmp(buffer, "h\n")) { return DQLD_CMD_H; } else { return -1; } } void dav_debug_ql_statement(DavQLStatement *stmt) { if (!stmt) { fprintf(stderr, "Debug DavQLStatement failed: null pointer"); return; } printf("Starting DavQL debugger (type 'h' for help)...\n\n"); dav_debug_ql_stmt_print(stmt); DavQLExpression *examineexpr = NULL; while(1) { int cmd = dav_debug_ql_command(); switch (cmd) { case DQLD_CMD_Q: return; case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break; case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break; case DQLD_CMD_P: examineexpr = &(stmt->path); dav_debug_ql_expr_print(examineexpr); break; case DQLD_CMD_L: if (dav_debug_ql_expr_selected(examineexpr)) { if (examineexpr->left) { examineexpr = examineexpr->left; dav_debug_ql_expr_print(examineexpr); } else { printf("There is no left subtree.\n"); } } break; case DQLD_CMD_R: if (dav_debug_ql_expr_selected(examineexpr)) { if (examineexpr->right) { examineexpr = examineexpr->right; dav_debug_ql_expr_print(examineexpr); } else { printf("There is no right subtree.\n"); } } break; case DQLD_CMD_H: printf( "\nCommands:\n" "p: examine path\n" "ps: print statement information\n" "q: quit\n\n" "\nExpression examination:\n" "pe: print expression information\n" "l: enter left subtree\n" "r: enter right subtree\n"); break; default: printf("unknown command\n"); } } } DavQLStatement* dav_parse_statement(sstr_t srctext) { DavQLStatement *stmt = malloc(sizeof(DavQLStatement)); // default values memset(stmt, 0, sizeof(DavQLStatement)); stmt->srctext = srctext; stmt->type = stmt->path.type = stmt->path.op = -1; stmt->depth = SIZE_MAX; return stmt; }