1
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1
|
/*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
2
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
3
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
4
|
* Copyright 2018 Olaf Wintermann. All rights reserved.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
5
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
6
|
* Redistribution and use in source and binary forms, with or without
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
7
|
* modification, are permitted provided that the following conditions are met:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
8
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
9
|
* 1. Redistributions of source code must retain the above copyright
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
10
|
* notice, this list of conditions and the following disclaimer.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
11
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
12
|
* 2. Redistributions in binary form must reproduce the above copyright
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
13
|
* notice, this list of conditions and the following disclaimer in the
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
14
|
* documentation and/or other materials provided with the distribution.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
15
|
*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
16
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
17
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
18
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
19
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
20
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
21
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
22
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
23
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
24
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
25
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
26
|
* POSSIBILITY OF SUCH DAMAGE.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
27
|
*/
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
28
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
29
|
#include "davqlparser.h"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
30
|
#include <cx/utils.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
31
|
#include <cx/linked_list.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
32
|
#include <cx/printf.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
33
|
#include <string.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
34
|
#include <stdio.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
35
|
#include <ctype.h>
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
36
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
37
|
#define sfmtarg(s) ((int)(s).length), (s).ptr
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
38
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
39
|
// ------------------------------------------------------------------------
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
40
|
// D E B U G E R
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
41
|
// ------------------------------------------------------------------------
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
42
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
43
|
static const char* _map_querytype(davqltype_t type) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
44
|
switch(type) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
45
|
case DAVQL_ERROR: return "ERROR";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
46
|
case DAVQL_SELECT: return "SELECT";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
47
|
case DAVQL_SET: return "SET";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
48
|
default: return "unknown";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
49
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
50
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
51
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
52
|
static const char* _map_exprtype(davqlexprtype_t type) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
53
|
switch(type) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
54
|
case DAVQL_UNDEFINED_TYPE: return "undefined";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
55
|
case DAVQL_NUMBER: return "NUMBER";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
56
|
case DAVQL_STRING: return "STRING";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
57
|
case DAVQL_TIMESTAMP: return "TIMESTAMP";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
58
|
case DAVQL_IDENTIFIER: return "IDENTIFIER";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
59
|
case DAVQL_UNARY: return "UNARY";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
60
|
case DAVQL_BINARY: return "BINARY";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
61
|
case DAVQL_LOGICAL: return "LOGICAL";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
62
|
case DAVQL_FUNCCALL: return "FUNCCALL";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
63
|
default: return "unknown";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
64
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
65
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
66
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
67
|
static const char* _map_specialfield(int info) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
68
|
switch(info) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
69
|
case 0: return "";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
70
|
case 1: return "with wildcard";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
71
|
case 2: return "(resource data only)";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
72
|
default: return "with mysterious identifier";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
73
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
74
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
75
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
76
|
static const char* _map_operator(davqloperator_t op) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
77
|
// don't use string array, because enum values may change
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
78
|
switch(op) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
79
|
case DAVQL_NOOP: return "no operator";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
80
|
case DAVQL_CALL: return "function call"; case DAVQL_ARGLIST: return ",";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
81
|
case DAVQL_ADD: return "+"; case DAVQL_SUB: return "-";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
82
|
case DAVQL_MUL: return "*"; case DAVQL_DIV: return "/";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
83
|
case DAVQL_AND: return "&"; case DAVQL_OR: return "|";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
84
|
case DAVQL_XOR: return "^"; case DAVQL_NEG: return "~";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
85
|
case DAVQL_NOT: return "NOT"; case DAVQL_LAND: return "AND";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
86
|
case DAVQL_LOR: return "OR"; case DAVQL_LXOR: return "XOR";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
87
|
case DAVQL_EQ: return "="; case DAVQL_NEQ: return "!=";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
88
|
case DAVQL_LT: return "<"; case DAVQL_GT: return ">";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
89
|
case DAVQL_LE: return "<="; case DAVQL_GE: return ">=";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
90
|
case DAVQL_LIKE: return "LIKE"; case DAVQL_UNLIKE: return "UNLIKE";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
91
|
default: return "unknown";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
92
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
93
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
94
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
95
|
static void dav_debug_ql_fnames_print(DavQLStatement *stmt) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
96
|
if (stmt->fields) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
97
|
printf("Field names: ");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
98
|
CxIterator i = cxListIterator(stmt->fields);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
99
|
cx_foreach(DavQLField *, f, i) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
100
|
printf("%.*s, ", (int)f->name.length, f->name.ptr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
101
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
102
|
printf("\b\b \b\b\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
103
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
104
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
105
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
106
|
static void dav_debug_ql_stmt_print(DavQLStatement *stmt) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
107
|
// Basic information
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
108
|
size_t fieldcount = stmt->fields ? stmt->fields->size : 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
109
|
int specialfield = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
110
|
if (stmt->fields && stmt->fields->size > 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
111
|
DavQLField* firstfield = (DavQLField*)cxListAt(stmt->fields, 0);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
112
|
if (firstfield->expr->type == DAVQL_IDENTIFIER) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
113
|
switch (firstfield->expr->srctext.ptr[0]) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
114
|
case '*': specialfield = 1; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
115
|
case '-': specialfield = 2; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
116
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
117
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
118
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
119
|
if (specialfield) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
120
|
fieldcount--;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
121
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
122
|
printf("Statement: %.*s\nType: %s\nField count: %zu %s\n",
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
123
|
(int)stmt->srctext.length, stmt->srctext.ptr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
124
|
_map_querytype(stmt->type),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
125
|
fieldcount,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
126
|
_map_specialfield(specialfield));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
127
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
128
|
dav_debug_ql_fnames_print(stmt);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
129
|
printf("Path: %.*s\nHas where clause: %s\n",
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
130
|
(int)stmt->path.length, stmt->path.ptr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
131
|
stmt->where ? "yes" : "no");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
132
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
133
|
// WITH attributes
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
134
|
if (stmt->depth == DAV_DEPTH_INFINITY) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
135
|
printf("Depth: infinity\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
136
|
} else if (stmt->depth == DAV_DEPTH_PLACEHOLDER) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
137
|
printf("Depth: placeholder\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
138
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
139
|
printf("Depth: %d\n", stmt->depth);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
140
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
141
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
142
|
// order by clause
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
143
|
printf("Order by: ");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
144
|
if (stmt->orderby) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
145
|
CxIterator i = cxListIterator(stmt->orderby);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
146
|
cx_foreach(DavQLOrderCriterion*, critdata, i) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
147
|
printf("%.*s %s%s", (int)critdata->column->srctext.length, critdata->column->srctext.ptr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
148
|
critdata->descending ? "desc" : "asc",
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
149
|
i.index+1 < stmt->orderby->size ? ", " : "\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
150
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
151
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
152
|
printf("nothing\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
153
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
154
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
155
|
// error messages
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
156
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
157
|
printf("\nError code: %d\nError: %s\n",
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
158
|
stmt->errorcode, stmt->errormessage);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
159
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
160
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
161
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
162
|
static int dav_debug_ql_expr_selected(DavQLExpression *expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
163
|
if (!expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
164
|
printf("Currently no expression selected.\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
165
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
166
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
167
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
168
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
169
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
170
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
171
|
static void dav_debug_ql_expr_print(DavQLExpression *expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
172
|
if (dav_debug_ql_expr_selected(expr)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
173
|
cxstring empty = CX_STR("(empty)");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
174
|
printf(
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
175
|
"Text: %.*s\nType: %s\nOperator: %s\n",
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
176
|
sfmtarg(expr->srctext),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
177
|
_map_exprtype(expr->type),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
178
|
_map_operator(expr->op));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
179
|
if (expr->left || expr->right) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
180
|
printf("Left hand: %.*s\nRight hand: %.*s\n",
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
181
|
sfmtarg(expr->left?expr->left->srctext:empty),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
182
|
sfmtarg(expr->right?expr->right->srctext:empty));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
183
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
184
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
185
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
186
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
187
|
static void dav_debug_ql_field_print(DavQLField *field) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
188
|
if (field) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
189
|
printf("Name: %.*s\n", sfmtarg(field->name));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
190
|
if (field->expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
191
|
dav_debug_ql_expr_print(field->expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
192
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
193
|
printf("No expression.\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
194
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
195
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
196
|
printf("No field selected.\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
197
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
198
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
199
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
200
|
static void dav_debug_ql_tree_print(DavQLExpression *expr, int depth) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
201
|
if (expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
202
|
if (expr->left) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
203
|
printf("%*c%s\n", depth, ' ', _map_operator(expr->op));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
204
|
dav_debug_ql_tree_print(expr->left, depth+1);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
205
|
dav_debug_ql_tree_print(expr->right, depth+1);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
206
|
} else if (expr->type == DAVQL_UNARY) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
207
|
printf("%*c%s %.*s\n", depth, ' ', _map_operator(expr->op),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
208
|
sfmtarg(expr->srctext));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
209
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
210
|
printf("%*c%.*s\n", depth, ' ', sfmtarg(expr->srctext));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
211
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
212
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
213
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
214
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
215
|
#define DQLD_CMD_Q 0
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
216
|
#define DQLD_CMD_PS 1
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
217
|
#define DQLD_CMD_PE 2
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
218
|
#define DQLD_CMD_PF 3
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
219
|
#define DQLD_CMD_PT 4
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
220
|
#define DQLD_CMD_F 10
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
221
|
#define DQLD_CMD_W 11
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
222
|
#define DQLD_CMD_O 12
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
223
|
#define DQLD_CMD_L 21
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
224
|
#define DQLD_CMD_R 22
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
225
|
#define DQLD_CMD_N 23
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
226
|
#define DQLD_CMD_P 24
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
227
|
#define DQLD_CMD_H 100
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
228
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
229
|
static int dav_debug_ql_command() {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
230
|
printf("> ");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
231
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
232
|
char buffer[8];
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
233
|
fgets(buffer, 8, stdin);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
234
|
// discard remaining chars
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
235
|
if (!strchr(buffer, '\n')) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
236
|
int chr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
237
|
while ((chr = fgetc(stdin) != '\n') && chr != EOF);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
238
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
239
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
240
|
if (!strcmp(buffer, "q\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
241
|
return DQLD_CMD_Q;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
242
|
} else if (!strcmp(buffer, "ps\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
243
|
return DQLD_CMD_PS;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
244
|
} else if (!strcmp(buffer, "pe\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
245
|
return DQLD_CMD_PE;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
246
|
} else if (!strcmp(buffer, "pf\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
247
|
return DQLD_CMD_PF;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
248
|
} else if (!strcmp(buffer, "pt\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
249
|
return DQLD_CMD_PT;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
250
|
} else if (!strcmp(buffer, "l\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
251
|
return DQLD_CMD_L;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
252
|
} else if (!strcmp(buffer, "r\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
253
|
return DQLD_CMD_R;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
254
|
} else if (!strcmp(buffer, "h\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
255
|
return DQLD_CMD_H;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
256
|
} else if (!strcmp(buffer, "f\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
257
|
return DQLD_CMD_F;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
258
|
} else if (!strcmp(buffer, "w\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
259
|
return DQLD_CMD_W;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
260
|
} else if (!strcmp(buffer, "o\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
261
|
return DQLD_CMD_O;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
262
|
} else if (!strcmp(buffer, "n\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
263
|
return DQLD_CMD_N;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
264
|
} else if (!strcmp(buffer, "p\n")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
265
|
return DQLD_CMD_P;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
266
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
267
|
return -1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
268
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
269
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
270
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
271
|
void dav_debug_statement(DavQLStatement *stmt) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
272
|
if (!stmt) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
273
|
fprintf(stderr, "Debug DavQLStatement failed: null pointer");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
274
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
275
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
276
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
277
|
printf("Starting DavQL debugger (type 'h' for help)...\n\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
278
|
dav_debug_ql_stmt_print(stmt);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
279
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
280
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
281
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
282
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
283
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
284
|
DavQLExpression *examineexpr = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
285
|
CxList *examineelem = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
286
|
int examineclause = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
287
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
288
|
while(1) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
289
|
int cmd = dav_debug_ql_command();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
290
|
switch (cmd) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
291
|
case DQLD_CMD_Q: return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
292
|
case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
293
|
case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
294
|
case DQLD_CMD_PT: dav_debug_ql_tree_print(examineexpr, 1); break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
295
|
case DQLD_CMD_PF: dav_debug_ql_fnames_print(stmt); break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
296
|
case DQLD_CMD_F:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
297
|
examineclause = DQLD_CMD_F;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
298
|
examineelem = stmt->fields;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
299
|
if (stmt->fields && stmt->fields->size > 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
300
|
DavQLField* field = cxListAt(stmt->fields, 0);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
301
|
examineexpr = field->expr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
302
|
dav_debug_ql_field_print(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
303
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
304
|
examineexpr = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
305
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
306
|
break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
307
|
case DQLD_CMD_W:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
308
|
examineclause = 0; examineelem = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
309
|
examineexpr = stmt->where;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
310
|
dav_debug_ql_expr_print(examineexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
311
|
break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
312
|
case DQLD_CMD_O:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
313
|
examineclause = DQLD_CMD_O;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
314
|
examineelem = stmt->orderby;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
315
|
examineexpr = stmt->orderby && stmt->orderby->size > 0 ?
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
316
|
((DavQLOrderCriterion*)cxListAt(stmt->orderby, 0))->column : NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
317
|
dav_debug_ql_expr_print(examineexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
318
|
break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
319
|
case DQLD_CMD_N:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
320
|
case DQLD_CMD_P:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
321
|
printf("TODO: port code to ucx 3\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
322
|
/*
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
323
|
if (examineelem) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
324
|
CxList *newelem = (cmd == DQLD_CMD_N ?
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
325
|
examineelem->next : examineelem->prev);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
326
|
if (newelem) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
327
|
examineelem = newelem;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
328
|
if (examineclause == DQLD_CMD_O) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
329
|
examineexpr = ((DavQLOrderCriterion*)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
330
|
examineelem->data)->column;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
331
|
dav_debug_ql_expr_print(examineexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
332
|
} else if (examineclause == DQLD_CMD_F) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
333
|
DavQLField* field = (DavQLField*)examineelem->data;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
334
|
examineexpr = field->expr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
335
|
dav_debug_ql_field_print(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
336
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
337
|
printf("Examining unknown clause type.");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
338
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
339
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
340
|
printf("Reached end of list.\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
341
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
342
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
343
|
printf("Currently not examining an expression list.\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
344
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
345
|
*/
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
346
|
break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
347
|
case DQLD_CMD_L:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
348
|
if (dav_debug_ql_expr_selected(examineexpr)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
349
|
if (examineexpr->left) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
350
|
examineexpr = examineexpr->left;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
351
|
dav_debug_ql_expr_print(examineexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
352
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
353
|
printf("There is no left subtree.\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
354
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
355
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
356
|
break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
357
|
case DQLD_CMD_R:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
358
|
if (dav_debug_ql_expr_selected(examineexpr)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
359
|
if (examineexpr->right) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
360
|
examineexpr = examineexpr->right;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
361
|
dav_debug_ql_expr_print(examineexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
362
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
363
|
printf("There is no right subtree.\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
364
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
365
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
366
|
break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
367
|
case DQLD_CMD_H:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
368
|
printf(
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
369
|
"\nCommands:\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
370
|
"ps: print statement information\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
371
|
"o: examine order by clause\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
372
|
"f: examine field list\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
373
|
"pf: print field names\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
374
|
"w: examine where clause\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
375
|
"n: examine next expression "
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
376
|
"(in order by clause or field list)\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
377
|
"p: examine previous expression "
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
378
|
"(in order by clause or field list)\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
379
|
"q: quit\n\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
380
|
"\nExpression examination:\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
381
|
"pe: print expression information\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
382
|
"pt: print full syntax tree of current (sub-)expression\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
383
|
"l: enter left subtree\n"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
384
|
"r: enter right subtree\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
385
|
break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
386
|
default: printf("unknown command\n");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
387
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
388
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
389
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
390
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
391
|
// ------------------------------------------------------------------------
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
392
|
// P A R S E R
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
393
|
// ------------------------------------------------------------------------
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
394
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
395
|
#define _error_context "(%.*s[->]%.*s%.*s)"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
396
|
#define _error_invalid "invalid statement"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
397
|
#define _error_out_of_memory "out of memory"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
398
|
#define _error_unexpected_token "unexpected token " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
399
|
#define _error_invalid_token "invalid token " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
400
|
#define _error_missing_path "expected path " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
401
|
#define _error_missing_from "expecting FROM keyword " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
402
|
#define _error_missing_at "expecting AT keyword " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
403
|
#define _error_missing_by "expecting BY keyword " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
404
|
#define _error_missing_as "expecting alias ('as <identifier>') " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
405
|
#define _error_missing_identifier "expecting identifier " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
406
|
#define _error_missing_par "missing closed parenthesis " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
407
|
#define _error_missing_assign "expecting assignment ('=') " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
408
|
#define _error_missing_where "SET statements must have a WHERE clause or " \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
409
|
"explicitly use ANYWHERE " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
410
|
#define _error_invalid_depth "invalid depth " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
411
|
#define _error_missing_expr "missing expression " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
412
|
#define _error_invalid_expr "invalid expression " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
413
|
#define _error_invalid_unary_op "invalid unary operator " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
414
|
#define _error_invalid_logical_op "invalid logical operator " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
415
|
#define _error_invalid_fmtspec "invalid format specifier " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
416
|
#define _error_invalid_string "string expected " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
417
|
#define _error_invalid_order_criterion "invalid order criterion " _error_context
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
418
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
419
|
#define token_sstr(token) ((token)->value)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
420
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
421
|
static void dav_error_in_context(int errorcode, const char *errormsg,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
422
|
DavQLStatement *stmt, DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
423
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
424
|
// we try to achieve two things: get as many information as possible
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
425
|
// and recover the concrete source string (and not the token strings)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
426
|
cxstring emptystring = CX_STR("");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
427
|
cxstring prev = token->prev ? (token->prev->prev ?
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
428
|
token_sstr(token->prev->prev) : token_sstr(token->prev))
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
429
|
: emptystring;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
430
|
cxstring tokenstr = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
431
|
cxstring next = token->next ? (token->next->next ?
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
432
|
token_sstr(token->next->next) : token_sstr(token->next))
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
433
|
: emptystring;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
434
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
435
|
int lp = prev.length == 0 ? 0 : tokenstr.ptr-prev.ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
436
|
const char *pn = tokenstr.ptr + tokenstr.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
437
|
int ln = next.ptr+next.length - pn;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
438
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
439
|
stmt->errorcode = errorcode;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
440
|
stmt->errormessage = cx_asprintf(errormsg,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
441
|
lp, prev.ptr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
442
|
sfmtarg(tokenstr),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
443
|
ln, pn).ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
444
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
445
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
446
|
#define dqlsec_alloc_failed(ptr, stmt) \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
447
|
if (!(ptr)) do { \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
448
|
(stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY; \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
449
|
return 0; \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
450
|
} while(0)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
451
|
#define dqlsec_malloc(stmt, ptr, type) \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
452
|
dqlsec_alloc_failed(ptr = malloc(sizeof(type)), stmt)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
453
|
#define dqlsec_mallocz(stmt, ptr, type) \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
454
|
dqlsec_alloc_failed(ptr = calloc(1, sizeof(type)), stmt)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
455
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
456
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
457
|
// special symbols are single tokens - the % sign MUST NOT be a special symbol
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
458
|
static const char *special_token_symbols = ",()+-*/&|^~=!<>";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
459
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
460
|
static _Bool iskeyword(DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
461
|
cxstring keywords[] ={CX_STR("select"), CX_STR("set"), CX_STR("from"), CX_STR("at"), CX_STR("as"),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
462
|
CX_STR("where"), CX_STR("anywhere"), CX_STR("like"), CX_STR("unlike"), CX_STR("and"),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
463
|
CX_STR("or"), CX_STR("not"), CX_STR("xor"), CX_STR("with"), CX_STR("infinity"),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
464
|
CX_STR("order"), CX_STR("by"), CX_STR("asc"), CX_STR("desc")
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
465
|
};
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
466
|
for (int i = 0 ; i < sizeof(keywords)/sizeof(cxstring) ; i++) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
467
|
if (!cx_strcasecmp(token->value, keywords[i])) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
468
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
469
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
470
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
471
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
472
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
473
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
474
|
static _Bool islongoperator(DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
475
|
cxstring operators[] = {CX_STR("and"), CX_STR("or"), CX_STR("not"), CX_STR("xor"),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
476
|
CX_STR("like"), CX_STR("unlike")
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
477
|
};
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
478
|
for (int i = 0 ; i < sizeof(operators)/sizeof(cxstring) ; i++) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
479
|
if (!cx_strcasecmp(token->value, operators[i])) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
480
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
481
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
482
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
483
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
484
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
485
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
486
|
static int dav_stmt_add_field(DavQLStatement *stmt, DavQLField *field) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
487
|
if(!stmt->fields) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
488
|
stmt->fields = cxLinkedListCreateSimple(CX_STORE_POINTERS);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
489
|
if(!stmt->fields) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
490
|
stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
491
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
492
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
493
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
494
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
495
|
if(cxListAdd(stmt->fields, field)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
496
|
stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
497
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
498
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
499
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
500
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
501
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
502
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
503
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
504
|
static void tokenlist_free(DavQLToken *tokenlist) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
505
|
DavQLToken *token = tokenlist;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
506
|
while(token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
507
|
DavQLToken *next = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
508
|
free(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
509
|
token = next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
510
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
511
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
512
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
513
|
static int dav_parse_add_token(DavQLToken **begin, DavQLToken **end, DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
514
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
515
|
// determine token class (order of if-statements is very important!)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
516
|
char firstchar = token->value.ptr[0];
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
517
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
518
|
if (isdigit(firstchar)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
519
|
token->tokenclass = DAVQL_TOKEN_NUMBER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
520
|
// check, if all characters are digits
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
521
|
for (size_t i = 1 ; i < token->value.length ; i++) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
522
|
if (!isdigit(token->value.ptr[i])) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
523
|
token->tokenclass = DAVQL_TOKEN_INVALID;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
524
|
break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
525
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
526
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
527
|
} else if (firstchar == '%') {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
528
|
token->tokenclass = DAVQL_TOKEN_FMTSPEC;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
529
|
} else if (token->value.length == 1) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
530
|
switch (firstchar) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
531
|
case '(': token->tokenclass = DAVQL_TOKEN_OPENP; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
532
|
case ')': token->tokenclass = DAVQL_TOKEN_CLOSEP; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
533
|
case ',': token->tokenclass = DAVQL_TOKEN_COMMA; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
534
|
default:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
535
|
token->tokenclass = strchr(special_token_symbols, firstchar) ?
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
536
|
DAVQL_TOKEN_OPERATOR : DAVQL_TOKEN_IDENTIFIER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
537
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
538
|
} else if (islongoperator(token)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
539
|
token->tokenclass = DAVQL_TOKEN_OPERATOR;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
540
|
} else if (firstchar == '\'') {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
541
|
token->tokenclass = DAVQL_TOKEN_STRING;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
542
|
} else if (firstchar == '`') {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
543
|
token->tokenclass = DAVQL_TOKEN_IDENTIFIER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
544
|
} else if (iskeyword(token)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
545
|
token->tokenclass = DAVQL_TOKEN_KEYWORD;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
546
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
547
|
token->tokenclass = DAVQL_TOKEN_IDENTIFIER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
548
|
// TODO: check for illegal characters
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
549
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
550
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
551
|
// remove quotes (extreme cool feature)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
552
|
if (token->tokenclass == DAVQL_TOKEN_STRING ||
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
553
|
(token->tokenclass == DAVQL_TOKEN_IDENTIFIER && firstchar == '`')) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
554
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
555
|
char lastchar = token->value.ptr[token->value.length-1];
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
556
|
if (firstchar == lastchar) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
557
|
token->value.ptr++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
558
|
token->value.length -= 2;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
559
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
560
|
token->tokenclass = DAVQL_TOKEN_INVALID;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
561
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
562
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
563
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
564
|
cx_linked_list_add((void**)begin, (void**)end, offsetof(DavQLToken, prev), offsetof(DavQLToken, next), token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
565
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
566
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
567
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
568
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
569
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
570
|
static DavQLToken* dav_parse_tokenize(cxstring src) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
571
|
#define alloc_token() do {token = calloc(1, sizeof(DavQLToken));\
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
572
|
if(!token) {tokenlist_free(tokens_begin); return NULL;}} while(0)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
573
|
#define add_token() if(dav_parse_add_token(&tokens_begin, &tokens_end, token)) return NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
574
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
575
|
DavQLToken *tokens_begin = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
576
|
DavQLToken *tokens_end = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
577
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
578
|
DavQLToken *token = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
579
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
580
|
char insequence = '\0';
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
581
|
for (size_t i = 0 ; i < src.length ; i++) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
582
|
// quoted strings / identifiers are a single token
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
583
|
if (src.ptr[i] == '\'' || src.ptr[i] == '`') {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
584
|
if (src.ptr[i] == insequence) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
585
|
// lookahead for escaped string quotes
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
586
|
if (src.ptr[i] == '\'' && i+2 < src.length &&
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
587
|
src.ptr[i+1] == src.ptr[i] && src.ptr[i+2] == src.ptr[i]) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
588
|
token->value.length += 3;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
589
|
i += 2;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
590
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
591
|
// add quoted token to list
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
592
|
token->value.length++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
593
|
add_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
594
|
token = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
595
|
insequence = '\0';
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
596
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
597
|
} else if (insequence == '\0') {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
598
|
insequence = src.ptr[i];
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
599
|
// always create new token for quoted strings
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
600
|
if (token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
601
|
add_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
602
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
603
|
alloc_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
604
|
token->value.ptr = src.ptr + i;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
605
|
token->value.length = 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
606
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
607
|
// add other kind of quotes to token
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
608
|
token->value.length++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
609
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
610
|
} else if (insequence) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
611
|
token->value.length++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
612
|
} else if (isspace(src.ptr[i])) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
613
|
// add token before spaces to list (if any)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
614
|
if (token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
615
|
add_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
616
|
token = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
617
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
618
|
} else if (strchr(special_token_symbols, src.ptr[i])) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
619
|
// add token before special symbol to list (if any)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
620
|
if (token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
621
|
add_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
622
|
token = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
623
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
624
|
// add special symbol as single token to list
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
625
|
alloc_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
626
|
token->value.ptr = src.ptr + i;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
627
|
token->value.length = 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
628
|
add_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
629
|
// set tokenizer ready to read more tokens
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
630
|
token = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
631
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
632
|
// if this is a new token, create memory for it
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
633
|
if (!token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
634
|
alloc_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
635
|
token->value.ptr = src.ptr + i;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
636
|
token->value.length = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
637
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
638
|
// extend token length when reading more bytes
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
639
|
token->value.length++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
640
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
641
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
642
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
643
|
if (token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
644
|
add_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
645
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
646
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
647
|
alloc_token();
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
648
|
token->tokenclass = DAVQL_TOKEN_END;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
649
|
token->value = CX_STR("");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
650
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
651
|
cx_linked_list_add((void**)&tokens_begin, (void**)&tokens_end, offsetof(DavQLToken, prev), offsetof(DavQLToken, next), token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
652
|
return tokens_begin;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
653
|
#undef alloc_token
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
654
|
#undef add_token
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
655
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
656
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
657
|
static void dav_free_expression(DavQLExpression *expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
658
|
if (expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
659
|
if (expr->left) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
660
|
dav_free_expression(expr->left);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
661
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
662
|
if (expr->right) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
663
|
dav_free_expression(expr->right);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
664
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
665
|
free(expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
666
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
667
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
668
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
669
|
static void dav_free_field(DavQLField *field) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
670
|
dav_free_expression(field->expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
671
|
free(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
672
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
673
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
674
|
static void dav_free_order_criterion(DavQLOrderCriterion *crit) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
675
|
if (crit->column) { // do it null-safe though column is expected to be set
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
676
|
dav_free_expression(crit->column);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
677
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
678
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
679
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
680
|
#define token_is(token, expectedclass) (token && \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
681
|
(token->tokenclass == expectedclass))
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
682
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
683
|
#define tokenvalue_is(token, expectedvalue) (token && \
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
684
|
!cx_strcasecmp(token->value, cx_str(expectedvalue)))
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
685
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
686
|
typedef int(*exprparser_f)(DavQLStatement*,DavQLToken*,DavQLExpression*);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
687
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
688
|
static int dav_parse_binary_expr(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
689
|
DavQLExpression* expr, exprparser_f parseL, char* opc, int* opv,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
690
|
exprparser_f parseR) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
691
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
692
|
if (!token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
693
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
694
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
695
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
696
|
int total_consumed = 0, consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
697
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
698
|
// save temporarily on stack (copy to heap later on)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
699
|
DavQLExpression left, right;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
700
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
701
|
// RULE: LEFT, [Operator, RIGHT]
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
702
|
memset(&left, 0, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
703
|
consumed = parseL(stmt, token, &left);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
704
|
if (!consumed || stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
705
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
706
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
707
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
708
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
709
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
710
|
char *op;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
711
|
if (token_is(token, DAVQL_TOKEN_OPERATOR) &&
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
712
|
(op = strchr(opc, token_sstr(token).ptr[0]))) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
713
|
expr->op = opv[op-opc];
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
714
|
expr->type = DAVQL_BINARY;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
715
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
716
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
717
|
memset(&right, 0, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
718
|
consumed = parseR(stmt, token, &right);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
719
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
720
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
721
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
722
|
if (!consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
723
|
dav_error_in_context(DAVQL_ERROR_MISSING_EXPR,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
724
|
_error_missing_expr, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
725
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
726
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
727
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
728
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
729
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
730
|
if (expr->op == DAVQL_NOOP) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
731
|
memcpy(expr, &left, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
732
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
733
|
dqlsec_malloc(stmt, expr->left, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
734
|
memcpy(expr->left, &left, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
735
|
dqlsec_malloc(stmt, expr->right, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
736
|
memcpy(expr->right, &right, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
737
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
738
|
expr->srctext.ptr = expr->left->srctext.ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
739
|
expr->srctext.length =
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
740
|
expr->right->srctext.ptr -
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
741
|
expr->left->srctext.ptr + expr->right->srctext.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
742
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
743
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
744
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
745
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
746
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
747
|
static void fmt_args_add(DavQLStatement *stmt, void *data) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
748
|
if(!stmt->args) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
749
|
stmt->args = cxLinkedListCreateSimple(CX_STORE_POINTERS);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
750
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
751
|
cxListAdd(stmt->args, data);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
752
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
753
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
754
|
static void dav_add_fmt_args(DavQLStatement *stmt, cxstring str) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
755
|
int placeholder = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
756
|
for (size_t i=0;i<str.length;i++) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
757
|
char c = str.ptr[i];
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
758
|
if (placeholder) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
759
|
if (c != '%') {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
760
|
fmt_args_add(stmt, (void*)(intptr_t)c);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
761
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
762
|
placeholder = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
763
|
} else if (c == '%') {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
764
|
placeholder = 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
765
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
766
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
767
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
768
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
769
|
static int dav_parse_literal(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
770
|
DavQLExpression* expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
771
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
772
|
expr->srctext = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
773
|
if (token_is(token, DAVQL_TOKEN_NUMBER)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
774
|
expr->type = DAVQL_NUMBER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
775
|
} else if (token_is(token, DAVQL_TOKEN_STRING)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
776
|
expr->type = DAVQL_STRING;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
777
|
// check for format specifiers and add args
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
778
|
dav_add_fmt_args(stmt, expr->srctext);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
779
|
} else if (token_is(token, DAVQL_TOKEN_TIMESTAMP)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
780
|
expr->type = DAVQL_TIMESTAMP;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
781
|
} else if (token_is(token, DAVQL_TOKEN_FMTSPEC)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
782
|
&& expr->srctext.length == 2) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
783
|
switch (expr->srctext.ptr[1]) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
784
|
case 'd': expr->type = DAVQL_NUMBER; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
785
|
case 's': expr->type = DAVQL_STRING; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
786
|
case 't': expr->type = DAVQL_TIMESTAMP; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
787
|
default:
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
788
|
dav_error_in_context(DAVQL_ERROR_INVALID_FMTSPEC,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
789
|
_error_invalid_fmtspec, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
790
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
791
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
792
|
// add fmtspec type to query arg list
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
793
|
fmt_args_add(stmt, (void*)(intptr_t)expr->srctext.ptr[1]);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
794
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
795
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
796
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
797
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
798
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
799
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
800
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
801
|
// forward declaration
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
802
|
static int dav_parse_expression(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
803
|
DavQLExpression* expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
804
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
805
|
static int dav_parse_arglist(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
806
|
DavQLExpression* expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
807
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
808
|
expr->srctext.ptr = token_sstr(token).ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
809
|
expr->srctext.length = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
810
|
expr->left = expr->right = NULL; // in case we fail, we want them to be sane
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
811
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
812
|
int total_consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
813
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
814
|
// RULE: Expression, {",", Expression};
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
815
|
DavQLExpression *arglist = expr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
816
|
DavQLExpression arg;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
817
|
const char *lastchar = expr->srctext.ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
818
|
int consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
819
|
do {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
820
|
memset(&arg, 0, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
821
|
consumed = dav_parse_expression(stmt, token, &arg);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
822
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
823
|
lastchar = arg.srctext.ptr + arg.srctext.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
824
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
825
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
826
|
// look ahead for a comma
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
827
|
if (token_is(token, DAVQL_TOKEN_COMMA)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
828
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
829
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
830
|
/* we have more arguments, so put the current argument to the
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
831
|
* left subtree and create a new node to the right
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
832
|
*/
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
833
|
dqlsec_malloc(stmt, arglist->left, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
834
|
memcpy(arglist->left, &arg, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
835
|
arglist->srctext.ptr = arg.srctext.ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
836
|
arglist->op = DAVQL_ARGLIST;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
837
|
arglist->type = DAVQL_FUNCCALL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
838
|
dqlsec_mallocz(stmt, arglist->right, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
839
|
arglist = arglist->right;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
840
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
841
|
// this was the last argument, so write it to the current node
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
842
|
memcpy(arglist, &arg, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
843
|
consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
844
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
845
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
846
|
} while (consumed && !stmt->errorcode);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
847
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
848
|
// recover source text
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
849
|
arglist = expr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
850
|
while (arglist && arglist->type == DAVQL_FUNCCALL) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
851
|
arglist->srctext.length = lastchar - arglist->srctext.ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
852
|
arglist = arglist->right;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
853
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
854
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
855
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
856
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
857
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
858
|
static int dav_parse_funccall(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
859
|
DavQLExpression* expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
860
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
861
|
// RULE: Identifier, "(", ArgumentList, ")";
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
862
|
if (token_is(token, DAVQL_TOKEN_IDENTIFIER) &&
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
863
|
token_is(token->next, DAVQL_TOKEN_OPENP)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
864
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
865
|
expr->type = DAVQL_FUNCCALL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
866
|
expr->op = DAVQL_CALL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
867
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
868
|
dqlsec_mallocz(stmt, expr->left, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
869
|
expr->left->type = DAVQL_IDENTIFIER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
870
|
expr->left->srctext = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
871
|
expr->right = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
872
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
873
|
token = token->next->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
874
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
875
|
DavQLExpression arg;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
876
|
int argtokens = dav_parse_arglist(stmt, token, &arg);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
877
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
878
|
// if an error occurred while parsing the arglist, return now
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
879
|
return 2;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
880
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
881
|
if (argtokens) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
882
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), argtokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
883
|
dqlsec_malloc(stmt, expr->right, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
884
|
memcpy(expr->right, &arg, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
885
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
886
|
// arg list may be empty
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
887
|
expr->right = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
888
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
889
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
890
|
if (token_is(token, DAVQL_TOKEN_CLOSEP)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
891
|
return 3 + argtokens;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
892
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
893
|
dav_error_in_context(DAVQL_ERROR_MISSING_PAR, _error_missing_par,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
894
|
stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
895
|
return 2; // it MUST be a function call, but it is invalid
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
896
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
897
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
898
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
899
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
900
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
901
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
902
|
static int dav_parse_unary_expr(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
903
|
DavQLExpression* expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
904
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
905
|
DavQLToken *firsttoken = token; // save for srctext recovery
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
906
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
907
|
DavQLExpression* atom = expr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
908
|
int total_consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
909
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
910
|
// optional unary operator
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
911
|
if (token_is(token, DAVQL_TOKEN_OPERATOR)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
912
|
char *op = strchr("+-~", token_sstr(token).ptr[0]);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
913
|
if (op) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
914
|
expr->type = DAVQL_UNARY;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
915
|
switch (*op) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
916
|
case '+': expr->op = DAVQL_ADD; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
917
|
case '-': expr->op = DAVQL_SUB; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
918
|
case '~': expr->op = DAVQL_NEG; break;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
919
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
920
|
dqlsec_mallocz(stmt, expr->left, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
921
|
atom = expr->left;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
922
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
923
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
924
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
925
|
dav_error_in_context(DAVQL_ERROR_INVALID_UNARY_OP,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
926
|
_error_invalid_unary_op, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
927
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
928
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
929
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
930
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
931
|
// RULE: (ParExpression | AtomicExpression)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
932
|
if (token_is(token, DAVQL_TOKEN_OPENP)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
933
|
token = token->next; total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
934
|
// RULE: "(", Expression, ")"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
935
|
int consumed = dav_parse_expression(stmt, token, atom);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
936
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
937
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
938
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
939
|
if (!consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
940
|
dav_error_in_context(DAVQL_ERROR_INVALID_EXPR,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
941
|
_error_invalid_expr, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
942
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
943
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
944
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
945
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
946
|
if (token_is(token, DAVQL_TOKEN_CLOSEP)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
947
|
token = token->next; total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
948
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
949
|
dav_error_in_context(DAVQL_ERROR_MISSING_PAR,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
950
|
_error_missing_par, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
951
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
952
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
953
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
954
|
// RULE: FunctionCall
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
955
|
int consumed = dav_parse_funccall(stmt, token, atom);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
956
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
957
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
958
|
} else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
959
|
// RULE: Identifier
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
960
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
961
|
atom->type = DAVQL_IDENTIFIER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
962
|
atom->srctext = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
963
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
964
|
// RULE: Literal
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
965
|
total_consumed += dav_parse_literal(stmt, token, atom);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
966
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
967
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
968
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
969
|
// recover source text
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
970
|
expr->srctext.ptr = token_sstr(firsttoken).ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
971
|
if (total_consumed > 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
972
|
cxstring lasttoken =
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
973
|
token_sstr((DavQLToken*)cx_linked_list_at(token, 0, offsetof(DavQLToken, next), total_consumed-1));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
974
|
expr->srctext.length =
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
975
|
lasttoken.ptr - expr->srctext.ptr + lasttoken.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
976
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
977
|
// the expression should not be used anyway, but we want to be safe
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
978
|
expr->srctext.length = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
979
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
980
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
981
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
982
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
983
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
984
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
985
|
static int dav_parse_bitexpr(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
986
|
DavQLExpression* expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
987
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
988
|
return dav_parse_binary_expr(stmt, token, expr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
989
|
dav_parse_unary_expr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
990
|
"&|^", (int[]){DAVQL_AND, DAVQL_OR, DAVQL_XOR},
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
991
|
dav_parse_bitexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
992
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
993
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
994
|
static int dav_parse_multexpr(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
995
|
DavQLExpression* expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
996
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
997
|
return dav_parse_binary_expr(stmt, token, expr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
998
|
dav_parse_bitexpr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
999
|
"*/", (int[]){DAVQL_MUL, DAVQL_DIV},
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1000
|
dav_parse_multexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1001
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1002
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1003
|
static int dav_parse_expression(DavQLStatement* stmt, DavQLToken* token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1004
|
DavQLExpression* expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1005
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1006
|
return dav_parse_binary_expr(stmt, token, expr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1007
|
dav_parse_multexpr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1008
|
"+-", (int[]){DAVQL_ADD, DAVQL_SUB},
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1009
|
dav_parse_expression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1010
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1011
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1012
|
static int dav_parse_named_field(DavQLStatement *stmt, DavQLToken *token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1013
|
DavQLField *field) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1014
|
int total_consumed = 0, consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1015
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1016
|
// RULE: Expression, " as ", Identifier;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1017
|
DavQLExpression *expr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1018
|
dqlsec_mallocz(stmt, expr, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1019
|
consumed = dav_parse_expression(stmt, token, expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1020
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1021
|
dav_free_expression(expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1022
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1023
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1024
|
if (expr->type == DAVQL_UNDEFINED_TYPE) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1025
|
dav_free_expression(expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1026
|
dav_error_in_context(DAVQL_ERROR_INVALID_EXPR,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1027
|
_error_invalid_expr, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1028
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1029
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1030
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1031
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1032
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1033
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1034
|
if (token_is(token, DAVQL_TOKEN_KEYWORD) && tokenvalue_is(token, "as")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1035
|
token = token->next; total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1036
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1037
|
dav_free_expression(expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1038
|
dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1039
|
_error_missing_as, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1040
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1041
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1042
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1043
|
if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1044
|
field->name = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1045
|
field->expr = expr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1046
|
return total_consumed + 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1047
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1048
|
dav_free_expression(expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1049
|
dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1050
|
_error_missing_identifier, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1051
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1052
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1053
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1054
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1055
|
static int dav_parse_fieldlist(DavQLStatement *stmt, DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1056
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1057
|
// RULE: "-"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1058
|
if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "-")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1059
|
DavQLField *field;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1060
|
dqlsec_malloc(stmt, field, DavQLField);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1061
|
if(dav_stmt_add_field(stmt, field)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1062
|
free(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1063
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1064
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1065
|
dqlsec_mallocz(stmt, field->expr, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1066
|
field->expr->type = DAVQL_IDENTIFIER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1067
|
field->expr->srctext = field->name = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1068
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1069
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1070
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1071
|
// RULE: "*", {",", NamedExpression}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1072
|
if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1073
|
DavQLField *field;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1074
|
dqlsec_malloc(stmt, field, DavQLField);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1075
|
if(dav_stmt_add_field(stmt, field)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1076
|
free(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1077
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1078
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1079
|
dqlsec_mallocz(stmt, field->expr, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1080
|
field->expr->type = DAVQL_IDENTIFIER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1081
|
field->expr->srctext = field->name = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1082
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1083
|
int total_consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1084
|
int consumed = 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1085
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1086
|
do {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1087
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1088
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1089
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1090
|
if (token_is(token, DAVQL_TOKEN_COMMA)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1091
|
total_consumed++; token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1092
|
DavQLField localfield;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1093
|
consumed = dav_parse_named_field(stmt, token, &localfield);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1094
|
if (!stmt->errorcode && consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1095
|
DavQLField *field;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1096
|
dqlsec_malloc(stmt, field, DavQLField);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1097
|
memcpy(field, &localfield, sizeof(DavQLField));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1098
|
if(dav_stmt_add_field(stmt, field)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1099
|
free(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1100
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1101
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1102
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1103
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1104
|
consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1105
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1106
|
} while (consumed > 0);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1107
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1108
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1109
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1110
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1111
|
// RULE: FieldExpression, {",", FieldExpression}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1112
|
{
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1113
|
int total_consumed = 0, consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1114
|
do {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1115
|
// RULE: NamedField | Identifier
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1116
|
DavQLField localfield;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1117
|
consumed = dav_parse_named_field(stmt, token, &localfield);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1118
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1119
|
DavQLField *field;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1120
|
dqlsec_malloc(stmt, field, DavQLField);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1121
|
memcpy(field, &localfield, sizeof(DavQLField));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1122
|
if(dav_stmt_add_field(stmt, field)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1123
|
free(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1124
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1125
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1126
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1127
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1128
|
} else if (token_is(token, DAVQL_TOKEN_IDENTIFIER)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1129
|
// look ahead, if the field is JUST the identifier
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1130
|
&& (token_is(token->next, DAVQL_TOKEN_COMMA) ||
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1131
|
tokenvalue_is(token->next, "from"))) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1132
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1133
|
DavQLField *field;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1134
|
dqlsec_malloc(stmt, field, DavQLField);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1135
|
dqlsec_mallocz(stmt, field->expr, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1136
|
field->expr->type = DAVQL_IDENTIFIER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1137
|
field->expr->srctext = field->name = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1138
|
if(dav_stmt_add_field(stmt, field)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1139
|
free(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1140
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1141
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1142
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1143
|
consumed = 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1144
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1145
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1146
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1147
|
// we found a valid solution, so erase any errors
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1148
|
stmt->errorcode = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1149
|
if (stmt->errormessage) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1150
|
free(stmt->errormessage);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1151
|
stmt->errormessage = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1152
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1153
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1154
|
// dav_parse_named_field has already thrown a good error
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1155
|
consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1156
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1157
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1158
|
// field has been parsed, now try to get a comma
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1159
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1160
|
consumed = token_is(token, DAVQL_TOKEN_COMMA) ? 1 : 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1161
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1162
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1163
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1164
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1165
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1166
|
} while (consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1167
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1168
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1169
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1170
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1171
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1172
|
// forward declaration
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1173
|
static int dav_parse_logical_expr(DavQLStatement *stmt, DavQLToken *token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1174
|
DavQLExpression *expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1175
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1176
|
static int dav_parse_bool_prim(DavQLStatement *stmt, DavQLToken *token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1177
|
DavQLExpression *expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1178
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1179
|
expr->type = DAVQL_LOGICAL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1180
|
expr->srctext = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1181
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1182
|
int total_consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1183
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1184
|
DavQLExpression bexpr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1185
|
memset(&bexpr, 0, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1186
|
total_consumed = dav_parse_expression(stmt, token, &bexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1187
|
if (!total_consumed || stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1188
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1189
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1190
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), total_consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1191
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1192
|
DavQLToken* optok = token;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1193
|
// RULE: Expression, (" like " | " unlike "), String
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1194
|
if (token_is(optok, DAVQL_TOKEN_OPERATOR) && (tokenvalue_is(optok,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1195
|
"like") || tokenvalue_is(optok, "unlike"))) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1196
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1197
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1198
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1199
|
if (token_is(token, DAVQL_TOKEN_STRING)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1200
|
expr->op = tokenvalue_is(optok, "like") ?
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1201
|
DAVQL_LIKE : DAVQL_UNLIKE;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1202
|
dqlsec_malloc(stmt, expr->left, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1203
|
memcpy(expr->left, &bexpr, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1204
|
dqlsec_mallocz(stmt, expr->right, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1205
|
expr->right->type = DAVQL_STRING;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1206
|
expr->right->srctext = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1207
|
expr->srctext.length = expr->right->srctext.ptr -
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1208
|
expr->srctext.ptr + expr->right->srctext.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1209
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1210
|
// fmt args
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1211
|
dav_add_fmt_args(stmt, expr->right->srctext);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1212
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1213
|
return total_consumed + 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1214
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1215
|
dav_error_in_context(DAVQL_ERROR_INVALID_STRING,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1216
|
_error_invalid_string, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1217
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1218
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1219
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1220
|
// RULE: Expression, Comparison, Expression
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1221
|
else if (token_is(optok, DAVQL_TOKEN_OPERATOR) && (
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1222
|
tokenvalue_is(optok, "=") || tokenvalue_is(optok, "!") ||
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1223
|
tokenvalue_is(optok, "<") || tokenvalue_is(optok, ">"))) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1224
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1225
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1226
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1227
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1228
|
if (tokenvalue_is(optok, "=")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1229
|
expr->op = DAVQL_EQ;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1230
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1231
|
if (tokenvalue_is(token, "=")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1232
|
if (tokenvalue_is(optok, "!")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1233
|
expr->op = DAVQL_NEQ;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1234
|
} else if (tokenvalue_is(optok, "<")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1235
|
expr->op = DAVQL_LE;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1236
|
} else if (tokenvalue_is(optok, ">")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1237
|
expr->op = DAVQL_GE;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1238
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1239
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1240
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1241
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1242
|
if (tokenvalue_is(optok, "<")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1243
|
expr->op = DAVQL_LT;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1244
|
} else if (tokenvalue_is(optok, ">")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1245
|
expr->op = DAVQL_GT;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1246
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1247
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1248
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1249
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1250
|
DavQLExpression rexpr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1251
|
memset(&rexpr, 0, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1252
|
int consumed = dav_parse_expression(stmt, token, &rexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1253
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1254
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1255
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1256
|
if (!consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1257
|
dav_error_in_context(
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1258
|
DAVQL_ERROR_MISSING_EXPR, _error_missing_expr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1259
|
stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1260
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1261
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1262
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1263
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1264
|
dqlsec_malloc(stmt, expr->left, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1265
|
memcpy(expr->left, &bexpr, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1266
|
dqlsec_malloc(stmt, expr->right, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1267
|
memcpy(expr->right, &rexpr, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1268
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1269
|
expr->srctext.length = expr->right->srctext.ptr -
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1270
|
expr->srctext.ptr + expr->right->srctext.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1271
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1272
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1273
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1274
|
// RULE: FunctionCall | Identifier;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1275
|
else if (bexpr.type == DAVQL_FUNCCALL || bexpr.type == DAVQL_IDENTIFIER) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1276
|
memcpy(expr, &bexpr, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1277
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1278
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1279
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1280
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1281
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1282
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1283
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1284
|
static int dav_parse_bool_expr(DavQLStatement *stmt, DavQLToken *token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1285
|
DavQLExpression *expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1286
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1287
|
// RULE: "not ", LogicalExpression
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1288
|
if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "not")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1289
|
expr->type = DAVQL_LOGICAL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1290
|
expr->op = DAVQL_NOT;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1291
|
dqlsec_mallocz(stmt, expr->left, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1292
|
expr->srctext = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1293
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1294
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1295
|
int consumed = dav_parse_bool_expr(stmt, token, expr->left);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1296
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1297
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1298
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1299
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1300
|
cxstring lasttok = token_sstr((DavQLToken*)cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed-1));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1301
|
expr->srctext.length =
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1302
|
lasttok.ptr - expr->srctext.ptr + lasttok.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1303
|
return consumed + 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1304
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1305
|
dav_error_in_context(DAVQL_ERROR_MISSING_EXPR,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1306
|
_error_missing_expr, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1307
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1308
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1309
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1310
|
// RULE: "(", LogicalExpression, ")"
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1311
|
else if (token_is(token, DAVQL_TOKEN_OPENP)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1312
|
int consumed = dav_parse_logical_expr(stmt, token->next, expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1313
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1314
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1315
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1316
|
if (token_is(token, DAVQL_TOKEN_CLOSEP)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1317
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1318
|
return consumed + 2;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1319
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1320
|
dav_error_in_context(DAVQL_ERROR_MISSING_PAR, _error_missing_par,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1321
|
stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1322
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1323
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1324
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1325
|
// don't handle errors here, we can also try a boolean primary
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1326
|
stmt->errorcode = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1327
|
if (stmt->errormessage) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1328
|
free(stmt->errormessage);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1329
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1330
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1331
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1332
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1333
|
// RULE: BooleanPrimary
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1334
|
return dav_parse_bool_prim(stmt, token, expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1335
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1336
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1337
|
static int dav_parse_logical_expr(DavQLStatement *stmt, DavQLToken *token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1338
|
DavQLExpression *expr) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1339
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1340
|
DavQLToken *firsttoken = token;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1341
|
int total_consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1342
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1343
|
// RULE: BooleanLiteral, [LogicalOperator, LogicalExpression];
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1344
|
DavQLExpression left, right;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1345
|
memset(&left, 0, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1346
|
int consumed = dav_parse_bool_expr(stmt, token, &left);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1347
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1348
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1349
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1350
|
if (!consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1351
|
dav_error_in_context(DAVQL_ERROR_MISSING_EXPR,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1352
|
_error_missing_expr, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1353
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1354
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1355
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1356
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1357
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1358
|
if (token_is(token, DAVQL_TOKEN_OPERATOR)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1359
|
expr->type = DAVQL_LOGICAL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1360
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1361
|
davqloperator_t op = DAVQL_NOOP;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1362
|
if (tokenvalue_is(token, "and")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1363
|
op = DAVQL_LAND;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1364
|
} else if (tokenvalue_is(token, "or")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1365
|
op = DAVQL_LOR;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1366
|
} else if (tokenvalue_is(token, "xor")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1367
|
op = DAVQL_LXOR;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1368
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1369
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1370
|
if (op == DAVQL_NOOP) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1371
|
dav_error_in_context(DAVQL_ERROR_INVALID_LOGICAL_OP,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1372
|
_error_invalid_logical_op, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1373
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1374
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1375
|
expr->op = op;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1376
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1377
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1378
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1379
|
memset(&right, 0, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1380
|
consumed = dav_parse_logical_expr(stmt, token, &right);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1381
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1382
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1383
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1384
|
if (!consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1385
|
dav_error_in_context(DAVQL_ERROR_MISSING_EXPR,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1386
|
_error_missing_expr, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1387
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1388
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1389
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1390
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1391
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1392
|
dqlsec_malloc(stmt, expr->left, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1393
|
memcpy(expr->left, &left, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1394
|
dqlsec_malloc(stmt, expr->right, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1395
|
memcpy(expr->right, &right, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1396
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1397
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1398
|
memcpy(expr, &left, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1399
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1400
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1401
|
// set type and recover source text
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1402
|
if (total_consumed > 0) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1403
|
expr->srctext.ptr = token_sstr(firsttoken).ptr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1404
|
cxstring lasttok = token_sstr((DavQLToken*)cx_linked_list_at(firsttoken, 0, offsetof(DavQLToken, next), total_consumed-1));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1405
|
expr->srctext.length = lasttok.ptr-expr->srctext.ptr+lasttok.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1406
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1407
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1408
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1409
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1410
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1411
|
static int dav_parse_where_clause(DavQLStatement *stmt, DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1412
|
dqlsec_mallocz(stmt, stmt->where, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1413
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1414
|
return dav_parse_logical_expr(stmt, token, stmt->where);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1415
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1416
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1417
|
static int dav_parse_with_clause(DavQLStatement *stmt, DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1418
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1419
|
int total_consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1420
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1421
|
// RULE: "depth", "=", (Number | "infinity")
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1422
|
if (tokenvalue_is(token, "depth")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1423
|
token = token->next; total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1424
|
if (tokenvalue_is(token, "=")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1425
|
token = token->next; total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1426
|
if (tokenvalue_is(token, "infinity")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1427
|
stmt->depth = DAV_DEPTH_INFINITY;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1428
|
token = token->next; total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1429
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1430
|
DavQLExpression *depthexpr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1431
|
dqlsec_mallocz(stmt, depthexpr, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1432
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1433
|
int consumed = dav_parse_expression(stmt, token, depthexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1434
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1435
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1436
|
if (depthexpr->type == DAVQL_NUMBER) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1437
|
if (depthexpr->srctext.ptr[0] == '%') {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1438
|
stmt->depth = DAV_DEPTH_PLACEHOLDER;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1439
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1440
|
cxstring depthstr = depthexpr->srctext;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1441
|
char *conv = malloc(depthstr.length+1);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1442
|
if (!conv) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1443
|
dav_free_expression(depthexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1444
|
stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1445
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1446
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1447
|
char *chk;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1448
|
memcpy(conv, depthstr.ptr, depthstr.length);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1449
|
conv[depthstr.length] = '\0';
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1450
|
stmt->depth = strtol(conv, &chk, 10);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1451
|
if (*chk || stmt->depth < -1) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1452
|
dav_error_in_context(DAVQL_ERROR_INVALID_DEPTH,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1453
|
_error_invalid_depth, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1454
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1455
|
free(conv);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1456
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1457
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1458
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1459
|
dav_error_in_context(DAVQL_ERROR_INVALID_DEPTH,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1460
|
_error_invalid_depth, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1461
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1462
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1463
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1464
|
dav_free_expression(depthexpr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1465
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1466
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1467
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1468
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1469
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1470
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1471
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1472
|
static int dav_parse_order_crit(DavQLStatement *stmt, DavQLToken *token,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1473
|
DavQLOrderCriterion *crit) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1474
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1475
|
// RULE: (Identifier | Number), [" asc"|" desc"];
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1476
|
DavQLExpression expr;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1477
|
memset(&expr, 0, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1478
|
int consumed = dav_parse_expression(stmt, token, &expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1479
|
if (stmt->errorcode || !consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1480
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1481
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1482
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1483
|
if (expr.type != DAVQL_IDENTIFIER && expr.type != DAVQL_NUMBER) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1484
|
dav_error_in_context(DAVQL_ERROR_INVALID_ORDER_CRITERION,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1485
|
_error_invalid_order_criterion, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1486
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1487
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1488
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1489
|
dqlsec_malloc(stmt, crit->column, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1490
|
memcpy(crit->column, &expr, sizeof(DavQLExpression));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1491
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1492
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1493
|
if (token_is(token, DAVQL_TOKEN_KEYWORD) && (
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1494
|
tokenvalue_is(token, "asc") || tokenvalue_is(token, "desc"))) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1495
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1496
|
crit->descending = tokenvalue_is(token, "desc");
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1497
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1498
|
return consumed+1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1499
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1500
|
crit->descending = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1501
|
return consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1502
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1503
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1504
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1505
|
static int dav_parse_orderby_clause(DavQLStatement *stmt, DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1506
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1507
|
int total_consumed = 0, consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1508
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1509
|
DavQLOrderCriterion crit;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1510
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1511
|
if(!stmt->orderby) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1512
|
stmt->orderby = cxLinkedListCreateSimple(sizeof(DavQLOrderCriterion));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1513
|
if(!stmt->orderby) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1514
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1515
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1516
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1517
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1518
|
// RULE: OrderByCriterion, {",", OrderByCriterion};
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1519
|
do {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1520
|
consumed = dav_parse_order_crit(stmt, token, &crit);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1521
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1522
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1523
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1524
|
if (!consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1525
|
dav_error_in_context(DAVQL_ERROR_MISSING_EXPR, _error_missing_expr,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1526
|
stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1527
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1528
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1529
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1530
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1531
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1532
|
if(cxListAdd(stmt->orderby, &crit)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1533
|
stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1534
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1535
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1536
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1537
|
if (token_is(token, DAVQL_TOKEN_COMMA)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1538
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1539
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1540
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1541
|
consumed = 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1542
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1543
|
} while (consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1544
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1545
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1546
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1547
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1548
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1549
|
static int dav_parse_assignments(DavQLStatement *stmt, DavQLToken *token) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1550
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1551
|
// RULE: Assignment, {",", Assignment}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1552
|
int total_consumed = 0, consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1553
|
do {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1554
|
// RULE: Identifier, "=", Expression
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1555
|
if (token_is(token, DAVQL_TOKEN_IDENTIFIER)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1556
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1557
|
// Identifier
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1558
|
DavQLField *field;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1559
|
dqlsec_malloc(stmt, field, DavQLField);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1560
|
field->name = token_sstr(token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1561
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1562
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1563
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1564
|
// "="
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1565
|
if (!token_is(token, DAVQL_TOKEN_OPERATOR)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1566
|
|| !tokenvalue_is(token, "=")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1567
|
dav_free_field(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1568
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1569
|
dav_error_in_context(DAVQL_ERROR_MISSING_ASSIGN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1570
|
_error_missing_assign, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1571
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1572
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1573
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1574
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1575
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1576
|
// Expression
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1577
|
dqlsec_mallocz(stmt, field->expr, DavQLExpression);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1578
|
consumed = dav_parse_expression(stmt, token, field->expr);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1579
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1580
|
dav_free_field(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1581
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1582
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1583
|
token = cx_linked_list_at(token, 0, offsetof(DavQLToken, next), consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1584
|
total_consumed += consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1585
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1586
|
// Add assignment to list and check if there's another one
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1587
|
if(dav_stmt_add_field(stmt, field)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1588
|
free(field);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1589
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1590
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1591
|
consumed = token_is(token, DAVQL_TOKEN_COMMA) ? 1 : 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1592
|
if (consumed) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1593
|
token = token->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1594
|
total_consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1595
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1596
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1597
|
dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1598
|
_error_missing_identifier, stmt, token);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1599
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1600
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1601
|
} while (consumed);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1602
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1603
|
return total_consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1604
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1605
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1606
|
static int dav_parse_path(DavQLStatement *stmt, DavQLToken *tokens) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1607
|
if (token_is(tokens, DAVQL_TOKEN_STRING)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1608
|
stmt->path = token_sstr(tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1609
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1610
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1611
|
} else if (token_is(tokens, DAVQL_TOKEN_OPERATOR)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1612
|
&& tokenvalue_is(tokens, "/")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1613
|
stmt->path = token_sstr(tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1614
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1615
|
int consumed = 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1616
|
while (!token_is(tokens, DAVQL_TOKEN_KEYWORD) &&
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1617
|
!token_is(tokens, DAVQL_TOKEN_END)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1618
|
cxstring toksstr = token_sstr(tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1619
|
stmt->path.length = toksstr.ptr-stmt->path.ptr+toksstr.length;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1620
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1621
|
consumed++;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1622
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1623
|
return consumed;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1624
|
} else if (token_is(tokens, DAVQL_TOKEN_FMTSPEC) &&
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1625
|
tokenvalue_is(tokens, "%s")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1626
|
stmt->path = token_sstr(tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1627
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1628
|
fmt_args_add(stmt, (void*)(intptr_t)'s');
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1629
|
return 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1630
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1631
|
dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1632
|
_error_missing_path, stmt, tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1633
|
return 0;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1634
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1635
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1636
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1637
|
/**
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1638
|
* Parser of a select statement.
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1639
|
* @param stmt the statement object that shall contain the syntax tree
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1640
|
* @param tokens the token list
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1641
|
*/
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1642
|
static void dav_parse_select_statement(DavQLStatement *stmt, DavQLToken *tokens) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1643
|
stmt->type = DAVQL_SELECT;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1644
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1645
|
// Consume field list
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1646
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), dav_parse_fieldlist(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1647
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1648
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1649
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1650
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1651
|
// Consume FROM keyword
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1652
|
if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1653
|
&& tokenvalue_is(tokens, "from")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1654
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1655
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1656
|
dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1657
|
_error_missing_from, stmt, tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1658
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1659
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1660
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1661
|
// Consume path
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1662
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), dav_parse_path(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1663
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1664
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1665
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1666
|
//dav_add_fmt_args(stmt, stmt->path); // add possible path args
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1667
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1668
|
// Consume with clause (if any)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1669
|
if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1670
|
&& tokenvalue_is(tokens, "with")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1671
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1672
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1673
|
dav_parse_with_clause(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1674
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1675
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1676
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1677
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1678
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1679
|
// Consume where clause (if any)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1680
|
if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1681
|
&& tokenvalue_is(tokens, "where")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1682
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1683
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1684
|
dav_parse_where_clause(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1685
|
} else if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1686
|
&& tokenvalue_is(tokens, "anywhere")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1687
|
// useless, but the user may want to explicitly express his intent
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1688
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1689
|
stmt->where = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1690
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1691
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1692
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1693
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1694
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1695
|
// Consume order by clause (if any)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1696
|
if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1697
|
&& tokenvalue_is(tokens, "order")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1698
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1699
|
if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1700
|
&& tokenvalue_is(tokens, "by")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1701
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1702
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1703
|
dav_parse_orderby_clause(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1704
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1705
|
dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1706
|
_error_missing_by, stmt, tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1707
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1708
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1709
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1710
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1711
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1712
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1713
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1714
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1715
|
if (tokens) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1716
|
if (token_is(tokens, DAVQL_TOKEN_INVALID)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1717
|
dav_error_in_context(DAVQL_ERROR_INVALID_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1718
|
_error_invalid_token, stmt, tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1719
|
} else if (!token_is(tokens, DAVQL_TOKEN_END)) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1720
|
dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1721
|
_error_unexpected_token, stmt, tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1722
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1723
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1724
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1725
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1726
|
static void dav_parse_set_statement(DavQLStatement *stmt, DavQLToken *tokens) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1727
|
stmt->type = DAVQL_SET;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1728
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1729
|
// Consume assignments
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1730
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), dav_parse_assignments(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1731
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1732
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1733
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1734
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1735
|
// Consume AT keyword
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1736
|
if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1737
|
&& tokenvalue_is(tokens, "at")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1738
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1739
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1740
|
dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1741
|
_error_missing_at, stmt, tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1742
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1743
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1744
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1745
|
// Consume path
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1746
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next), dav_parse_path(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1747
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1748
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1749
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1750
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1751
|
// Consume with clause (if any)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1752
|
if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1753
|
&& tokenvalue_is(tokens, "with")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1754
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1755
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1756
|
dav_parse_with_clause(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1757
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1758
|
if (stmt->errorcode) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1759
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1760
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1761
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1762
|
// Consume mandatory where clause (or anywhere keyword)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1763
|
if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1764
|
&& tokenvalue_is(tokens, "where")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1765
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1766
|
tokens = cx_linked_list_at(tokens, 0, offsetof(DavQLToken, next),
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1767
|
dav_parse_where_clause(stmt, tokens));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1768
|
} else if (token_is(tokens, DAVQL_TOKEN_KEYWORD)
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1769
|
&& tokenvalue_is(tokens, "anywhere")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1770
|
// no-op, but we want the user to be explicit about this
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1771
|
tokens = tokens->next;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1772
|
stmt->where = NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1773
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1774
|
dav_error_in_context(DAVQL_ERROR_MISSING_TOKEN,
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1775
|
_error_missing_where, stmt, tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1776
|
return;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1777
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1778
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1779
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1780
|
DavQLStatement* dav_parse_statement(cxstring srctext) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1781
|
DavQLStatement *stmt = calloc(1, sizeof(DavQLStatement));
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1782
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1783
|
// if we can't even get enough memory for the statement object or an error
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1784
|
// message, we can simply die without returning anything
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1785
|
if (!stmt) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1786
|
return NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1787
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1788
|
char *oommsg = strdup(_error_out_of_memory);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1789
|
if (!oommsg) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1790
|
free(stmt);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1791
|
return NULL;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1792
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1793
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1794
|
// default values
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1795
|
stmt->type = -1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1796
|
stmt->depth = 1;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1797
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1798
|
// save trimmed source text
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1799
|
stmt->srctext = cx_strtrim(srctext);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1800
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1801
|
if (stmt->srctext.length) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1802
|
// tokenization
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1803
|
DavQLToken* tokens = dav_parse_tokenize(stmt->srctext);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1804
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1805
|
if (tokens) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1806
|
// use first token to determine query type
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1807
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1808
|
if (tokenvalue_is(tokens, "select")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1809
|
dav_parse_select_statement(stmt, tokens->next);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1810
|
} else if (tokenvalue_is(tokens, "set")) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1811
|
dav_parse_set_statement(stmt, tokens->next);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1812
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1813
|
stmt->type = DAVQL_ERROR;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1814
|
stmt->errorcode = DAVQL_ERROR_INVALID;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1815
|
stmt->errormessage = strdup(_error_invalid);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1816
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1817
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1818
|
// free token data
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1819
|
tokenlist_free(tokens);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1820
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1821
|
stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1822
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1823
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1824
|
stmt->type = DAVQL_ERROR;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1825
|
stmt->errorcode = DAVQL_ERROR_INVALID;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1826
|
stmt->errormessage = strdup(_error_invalid);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1827
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1828
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1829
|
if (stmt->errorcode == DAVQL_ERROR_OUT_OF_MEMORY) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1830
|
stmt->type = DAVQL_ERROR;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1831
|
stmt->errormessage = oommsg;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1832
|
} else {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1833
|
free(oommsg);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1834
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1835
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1836
|
return stmt;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1837
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1838
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1839
|
void dav_free_statement(DavQLStatement *stmt) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1840
|
if(stmt->fields) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1841
|
stmt->fields->simple_destructor = (cx_destructor_func)dav_free_field;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1842
|
cxListDestroy(stmt->fields);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1843
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1844
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1845
|
if (stmt->where) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1846
|
dav_free_expression(stmt->where);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1847
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1848
|
if (stmt->errormessage) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1849
|
free(stmt->errormessage);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1850
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1851
|
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1852
|
if(stmt->orderby) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1853
|
stmt->orderby->simple_destructor = (cx_destructor_func)dav_free_order_criterion;
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1854
|
cxListDestroy(stmt->orderby);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1855
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1856
|
if(stmt->args) {
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1857
|
cxListDestroy(stmt->args);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1858
|
}
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1859
|
free(stmt);
|
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff
changeset
|
1860
|
}
|