Tue, 24 Mar 2015 15:49:51 +0100
added parse function prototype + started writing a debugger
/* * 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> static const char* _map_querytype(davqltype_t type) { switch(type) { case GET: return "GET"; case SET: return "SET"; default: return "unknown"; } } #define dav_debug_print_sstr_t(s) fwrite((s).ptr, 1, (s).length, stdout); static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { // Basic information printf("Statement: "); dav_debug_print_sstr_t(stmt->srctext); printf("\nType: %s\nField count: %zu", _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(" with%s wildcard\n", wildcard?"":"out"); // Pathname printf("Path: "); dav_debug_print_sstr_t(stmt->path.srctext); // Has where clause printf("\nHas where clause: %s\n", 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_command() { printf("Command (type 'h' for help): "); char buffer[16]; fgets(buffer, 16, stdin); if (!strcmp(buffer, "q\n")) { return 0; } else if (!strcmp(buffer, "ps\n")) { return 1; } else if (!strcmp(buffer, "h\n")) { return 100; } else { return -1; } } void dav_debug_ql_statement(DavQLStatement *stmt) { if (!stmt) { fprintf(stderr, "Debug DavQLStatement failed: null pointer"); return; } printf("Starting DavQL debugger...\n\n"); dav_debug_ql_stmt_print(stmt); while(1) { int cmd = dav_debug_ql_command(); switch (cmd) { case 0: return; case 1: dav_debug_ql_stmt_print(stmt); break; case 100: printf( "\nCommands:\n" "ps: print statement information\n" "q: quit\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 = -1; stmt->depth = SIZE_MAX; return stmt; }