28 |
28 |
29 #include "davqlparser.h" |
29 #include "davqlparser.h" |
30 #include <string.h> |
30 #include <string.h> |
31 #include <stdio.h> |
31 #include <stdio.h> |
32 |
32 |
|
33 #define sfmtarg(s) ((int)(s).length), (s).ptr |
|
34 |
33 static const char* _map_querytype(davqltype_t type) { |
35 static const char* _map_querytype(davqltype_t type) { |
34 switch(type) { |
36 switch(type) { |
35 case GET: return "GET"; |
37 case GET: return "GET"; |
36 case SET: return "SET"; |
38 case SET: return "SET"; |
37 default: return "unknown"; |
39 default: return "unknown"; |
38 } |
40 } |
39 } |
41 } |
40 |
42 |
41 #define dav_debug_print_sstr_t(s) fwrite((s).ptr, 1, (s).length, stdout); |
43 static const char* _map_exprtype(davqlexprtype_t type) { |
|
44 switch(type) { |
|
45 case LITERAL: return "LITERAL"; |
|
46 case IDENTIFIER: return "IDENTIFIER"; |
|
47 case UNARY: return "UNARY"; |
|
48 case BINARY: return "BINARY"; |
|
49 case LOGICAL: return "LOGICAL"; |
|
50 case FUNCCALL: return "FUNCCALL"; |
|
51 default: return "unknown"; |
|
52 } |
|
53 } |
|
54 |
|
55 static const char* _map_operator(davqloperator_t op) { |
|
56 // don't use string array, because enum values may change |
|
57 switch(op) { |
|
58 case ADD: return "+"; case SUB: return "-"; case MUL: return "*"; |
|
59 case DIV: return "/"; case AND: return "&"; case OR: return "|"; |
|
60 case XOR: return "^"; case NEG: return "~"; case NOT: return "NOT"; |
|
61 case LAND: return "AND"; case LOR: return "OR"; case LXOR: return "XOR"; |
|
62 case EQ: return "="; case NEQ: return "!="; case LT: return "<"; |
|
63 case GT: return ">"; case LE: return "<="; case GE: return ">="; |
|
64 case LIKE: return "LIKE"; case UNLIKE: return "UNLIKE"; |
|
65 default: return "unknown"; |
|
66 } |
|
67 } |
42 |
68 |
43 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { |
69 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { |
44 |
70 |
45 // Basic information |
71 // Basic information |
46 printf("Statement: "); |
72 printf("Statement: %*s\nType: %s\nField count: %zu", |
47 dav_debug_print_sstr_t(stmt->srctext); |
73 sfmtarg(stmt->srctext), |
48 printf("\nType: %s\nField count: %zu", |
|
49 _map_querytype(stmt->type), |
74 _map_querytype(stmt->type), |
50 ucx_list_size(stmt->fields)); |
75 ucx_list_size(stmt->fields)); |
51 |
76 |
52 // Has wildcard |
77 // Has wildcard |
53 _Bool wildcard = 0; |
78 _Bool wildcard = 0; |
56 if (expr->type == IDENTIFIER && |
81 if (expr->type == IDENTIFIER && |
57 expr->srctext.length == 1 && *(expr->srctext.ptr) == '*') { |
82 expr->srctext.length == 1 && *(expr->srctext.ptr) == '*') { |
58 wildcard = 1; |
83 wildcard = 1; |
59 } |
84 } |
60 } |
85 } |
61 printf(" with%s wildcard\n", wildcard?"":"out"); |
86 printf(" %s wildcard\nPath: %*s\nHas where clause: %s\n", |
62 |
87 wildcard?"with":"without", |
63 // Pathname |
88 sfmtarg(stmt->path.srctext), |
64 printf("Path: "); |
89 stmt->where ? "yes" : "no"); |
65 dav_debug_print_sstr_t(stmt->path.srctext); |
|
66 |
|
67 // Has where clause |
|
68 printf("\nHas where clause: %s\n", stmt->where ? "yes" : "no"); |
|
69 if (stmt->type == SET) { |
90 if (stmt->type == SET) { |
70 printf("Value list size matches: %s", |
91 printf("Value list size matches: %s", |
71 ucx_list_size(stmt->fields) == ucx_list_size(stmt->setvalues) |
92 ucx_list_size(stmt->fields) == ucx_list_size(stmt->setvalues) |
72 ? "yes" : "no"); |
93 ? "yes" : "no"); |
73 } |
94 } |
78 } else { |
99 } else { |
79 printf("Depth: %zu\n", stmt->depth); |
100 printf("Depth: %zu\n", stmt->depth); |
80 } |
101 } |
81 } |
102 } |
82 |
103 |
|
104 static int dav_debug_ql_expr_selected(DavQLExpression *expr) { |
|
105 if (!expr) { |
|
106 printf("Currently no expression selected.\n"); |
|
107 return 0; |
|
108 } else { |
|
109 return 1; |
|
110 } |
|
111 } |
|
112 |
|
113 static void dav_debug_ql_expr_print(DavQLExpression *expr) { |
|
114 if (dav_debug_ql_expr_selected(expr)) { |
|
115 sstr_t empty = S("(empty)"); |
|
116 printf( |
|
117 "Text: %*s\nType: %s\nOperator: %s\n" |
|
118 "Left hand: %*s\nRight hand: %*s\n", |
|
119 sfmtarg(expr->srctext), |
|
120 _map_exprtype(expr->type), |
|
121 _map_operator(expr->op), |
|
122 sfmtarg(expr->left?expr->left->srctext:empty), |
|
123 sfmtarg(expr->right?expr->right->srctext:empty)); |
|
124 } |
|
125 } |
|
126 |
|
127 #define DQLD_CMD_Q 0 |
|
128 #define DQLD_CMD_PS 1 |
|
129 #define DQLD_CMD_PE 2 |
|
130 #define DQLD_CMD_P 10 |
|
131 #define DQLD_CMD_L 21 |
|
132 #define DQLD_CMD_R 22 |
|
133 #define DQLD_CMD_H 100 |
|
134 |
83 static int dav_debug_ql_command() { |
135 static int dav_debug_ql_command() { |
84 printf("Command (type 'h' for help): "); |
136 printf("> "); |
85 |
137 |
86 char buffer[16]; |
138 char buffer[16]; |
87 fgets(buffer, 16, stdin); |
139 fgets(buffer, 16, stdin); |
88 if (!strcmp(buffer, "q\n")) { |
140 if (!strcmp(buffer, "q\n")) { |
89 return 0; |
141 return DQLD_CMD_Q; |
90 } else if (!strcmp(buffer, "ps\n")) { |
142 } else if (!strcmp(buffer, "ps\n")) { |
91 return 1; |
143 return DQLD_CMD_PS; |
|
144 } else if (!strcmp(buffer, "pe\n")) { |
|
145 return DQLD_CMD_PE; |
|
146 } else if (!strcmp(buffer, "p\n")) { |
|
147 return DQLD_CMD_P; |
|
148 } else if (!strcmp(buffer, "l\n")) { |
|
149 return DQLD_CMD_L; |
|
150 } else if (!strcmp(buffer, "r\n")) { |
|
151 return DQLD_CMD_R; |
92 } else if (!strcmp(buffer, "h\n")) { |
152 } else if (!strcmp(buffer, "h\n")) { |
93 return 100; |
153 return DQLD_CMD_H; |
94 } else { |
154 } else { |
95 return -1; |
155 return -1; |
96 } |
156 } |
97 } |
157 } |
98 |
158 |
100 if (!stmt) { |
160 if (!stmt) { |
101 fprintf(stderr, "Debug DavQLStatement failed: null pointer"); |
161 fprintf(stderr, "Debug DavQLStatement failed: null pointer"); |
102 return; |
162 return; |
103 } |
163 } |
104 |
164 |
105 printf("Starting DavQL debugger...\n\n"); |
165 printf("Starting DavQL debugger (type 'h' for help)...\n\n"); |
106 dav_debug_ql_stmt_print(stmt); |
166 dav_debug_ql_stmt_print(stmt); |
|
167 |
|
168 DavQLExpression *examineexpr = NULL; |
107 |
169 |
108 while(1) { |
170 while(1) { |
109 int cmd = dav_debug_ql_command(); |
171 int cmd = dav_debug_ql_command(); |
110 switch (cmd) { |
172 switch (cmd) { |
111 case 0: return; |
173 case DQLD_CMD_Q: return; |
112 case 1: dav_debug_ql_stmt_print(stmt); break; |
174 case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break; |
113 case 100: |
175 case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break; |
|
176 case DQLD_CMD_P: |
|
177 examineexpr = &(stmt->path); |
|
178 dav_debug_ql_expr_print(examineexpr); |
|
179 break; |
|
180 case DQLD_CMD_L: |
|
181 if (dav_debug_ql_expr_selected(examineexpr)) { |
|
182 if (examineexpr->left) { |
|
183 examineexpr = examineexpr->left; |
|
184 dav_debug_ql_expr_print(examineexpr); |
|
185 } else { |
|
186 printf("There is no left subtree.\n"); |
|
187 } |
|
188 } |
|
189 break; |
|
190 case DQLD_CMD_R: |
|
191 if (dav_debug_ql_expr_selected(examineexpr)) { |
|
192 if (examineexpr->right) { |
|
193 examineexpr = examineexpr->right; |
|
194 dav_debug_ql_expr_print(examineexpr); |
|
195 } else { |
|
196 printf("There is no right subtree.\n"); |
|
197 } |
|
198 } |
|
199 break; |
|
200 case DQLD_CMD_H: |
114 printf( |
201 printf( |
115 "\nCommands:\n" |
202 "\nCommands:\n" |
|
203 "p: examine path\n" |
116 "ps: print statement information\n" |
204 "ps: print statement information\n" |
117 "q: quit\n"); |
205 "q: quit\n\n" |
|
206 "\nExpression examination:\n" |
|
207 "pe: print expression information\n" |
|
208 "l: enter left subtree\n" |
|
209 "r: enter right subtree\n"); |
118 break; |
210 break; |
119 default: printf("unknown command\n"); |
211 default: printf("unknown command\n"); |
120 } |
212 } |
121 } |
213 } |
122 } |
214 } |
125 DavQLStatement *stmt = malloc(sizeof(DavQLStatement)); |
217 DavQLStatement *stmt = malloc(sizeof(DavQLStatement)); |
126 |
218 |
127 // default values |
219 // default values |
128 memset(stmt, 0, sizeof(DavQLStatement)); |
220 memset(stmt, 0, sizeof(DavQLStatement)); |
129 stmt->srctext = srctext; |
221 stmt->srctext = srctext; |
130 stmt->type = -1; |
222 stmt->type = stmt->path.type = stmt->path.op = -1; |
131 stmt->depth = SIZE_MAX; |
223 stmt->depth = SIZE_MAX; |
132 |
224 |
133 |
225 |
134 return stmt; |
226 return stmt; |
135 } |
227 } |