1/*
2 * Copyright 2004-2008, Fran��ois Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "query.h"
7
8//#define TESTME
9
10#ifdef _KERNEL_MODE
11#define printf dprintf
12#undef TESTME
13#endif
14
15#ifdef TESTME
16#include <stdio.h>
17#endif
18#include <stdlib.h>
19#include <string.h>
20// ('foo'<>"bar\"")&&!(()||())
21
22char *query_unescape_string(const char *q, const char **newq, char delim)
23{
24	int backslash = 0;
25	int i;
26	char *p, *p2;
27
28	if (*q == '*')
29		q++;
30
31	p = malloc(10);
32	if (!p)
33		return NULL;
34	for (i = 0; *q; i++) {
35		if ((i % 10) == 9) {
36			p2 = realloc(p, i+10);
37			if (!p2) {
38				free(p);
39				return NULL;//p;
40			}
41			p = p2;
42		}
43		if (backslash) {
44			backslash = 0;
45			p[i] = *q;
46		} else if (*q == '\\') {
47			backslash = 1;
48			i--;
49		} else if (*q == '\0') {
50			break;
51		} else if (*q == delim) {
52			break;
53		} else {
54			p[i] = *q;
55			if (p[i] == '*')
56				p[i] = ' ';
57		}
58		q++;
59	}
60	p[i] = '\0';
61	if (i > 0 && p[i-1] == ' ')
62		p[i-1] = '\0';
63	if (newq)
64		*newq = q;
65	if (i)
66		return p;
67	free(p);
68	return NULL;
69}
70
71char *query_strip_bracketed_Cc(char *str)
72{
73	char *p = str;
74	char c, C;
75	while (*p) {
76		if (*p == '[') {
77			if (p[1] && p[2] && p[3] == ']') {
78				c = p[1];
79				C = p[2];
80				//printf("cC = %c%c\n", c, C);
81				if (C >= 'a' && C <= 'z' && (c == C + 'A' - 'a'))
82					*p = C;
83				else if (c >= 'a' && c <= 'z' && (C == c + 'A' - 'a'))
84					*p = c;
85				if (*p != '[') {
86					strcpy(p+1, p + 4);
87				}
88			}
89		}
90		p++;
91	}
92	return str;
93}
94
95enum pqs_state {
96	QS_UNKNOWN,
97	QS_PAREN,
98	QS_QTR,
99	QS_
100};
101
102/*
103static const char *parse_qs_r(const char *query, query_exp *tree)
104{
105	int parens = 0;
106	return NULL;
107}
108*/
109
110status_t query_parse(const char *query, query_exp **tree)
111{
112	//query_exp *t;
113
114	return B_OK;
115}
116
117#ifdef TESTME
118
119const char *strqop(query_op op)
120{
121	switch (op) {
122#define QOP(_op) case _op: return #_op
123	QOP(B_INVALID_OP);
124	QOP(B_EQ);
125	QOP(B_GT);
126	QOP(B_GE);
127	QOP(B_LT);
128	QOP(B_LE);
129	QOP(B_NE);
130	QOP(B_CONTAINS);
131	QOP(B_BEGINS_WITH);
132	QOP(B_ENDS_WITH);
133	QOP(B_AND);
134	QOP(B_OR);
135	QOP(B_NOT);
136#undef QOP
137	default: return "B_?_OP";
138	}
139}
140
141#define INDC '#'
142
143void dump_query_tree(query_exp *tree, int indent)
144{
145	int i;
146	if (!tree)
147		return;
148	if (tree->op >= B_AND) {
149		for (i=0;i<indent;i++) printf("%c", INDC);
150		printf(": %s {\n", strqop(tree->op));
151		dump_query_tree(tree->lv.exp, indent+1);
152		dump_query_tree(tree->rv.exp, indent+1);
153		for (i=0;i<indent;i++) printf("%c", INDC);
154		printf("}\n");
155	} else {
156		for (i=0;i<indent;i++) printf("%c", INDC);
157		printf(": {%s} %s {%s}\n", tree->lv.str, strqop(tree->op), tree->rv.str);
158	}
159}
160
161int main(int argc, char **argv)
162{
163	status_t err;
164	query_exp *tree;
165	char *p;
166	if (argc < 2)
167		return 1;
168/*
169	err = query_parse(argv[1], &tree);
170	if (err) {
171		printf("parse_query_string: %s\n", strerror(err));
172		return 1;
173	}
174	dump_query_tree(tree, 0);
175*/
176	if (!strncmp(argv[1], "((name==\"*", 10)) {
177		argv[1] += 10;
178	}
179	p = query_unescape_string(argv[1], NULL, '"');
180	printf("'%s'\n", p);
181	query_strip_bracketed_Cc(p);
182	printf("'%s'\n", p);
183	return 0;
184}
185#endif
186