]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/spotlight_rawquery_parser.y
daf5bc2ff7381fcb24792a5f73c3f61b8a23d924
[netatalk.git] / etc / afpd / spotlight_rawquery_parser.y
1 %{
2   #include <stdbool.h>
3   #include <stdio.h>
4   #include <string.h>
5   #include <gio/gio.h>
6   #include <atalk/talloc.h>
7   #include <atalk/logger.h>
8   #include <atalk/errchk.h>
9   #include "spotlight_SPARQL_map.h"
10   #include "spotlight.h"
11
12   struct yy_buffer_state;
13   typedef struct yy_buffer_state *YY_BUFFER_STATE;
14   extern int yylex (void);
15   extern void yyerror (char const *);
16   extern void *yyterminate(void);
17   extern YY_BUFFER_STATE yy_scan_string( const char *str);
18   extern void yy_delete_buffer ( YY_BUFFER_STATE buffer );
19
20   /* forward declarations */
21   static const char *map_expr(const char *attr, char op, const char *val);
22   static const char *map_daterange(const char *dateattr, const char *date1, const char *date2);
23
24   /* global vars, eg needed by the lexer */
25   slq_t *ssp_slq;
26
27   /* local vars */
28   static gchar *ssp_result;
29
30 %}
31
32 %code provides {
33   extern int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result);
34   extern slq_t *ssp_slq;
35 }
36
37 %union {
38     int ival;
39     const char *sval;
40     bool bval;
41 }
42
43 %expect 1
44 %error-verbose
45
46 %type <sval> match expr line function
47 %token <sval> DATE
48 %token <sval> WORD
49 %token <bval> BOOL
50 %token FUNC_INRANGE
51 %token DATE_SPEC
52 %token OBRACE CBRACE EQUAL UNEQUAL GT LT COMMA QUOTE
53 %left AND
54 %left OR
55 %%
56
57 input:
58 /* empty */
59 | input line
60 ;
61      
62 line:
63 expr                           {
64     ssp_result = talloc_asprintf(ssp_slq,
65                                  "SELECT DISTINCT ?url WHERE "
66                                  "{ ?x nie:url ?url FILTER(fn:starts-with(?url, 'file://%s/')) . %s}",
67                                  ssp_slq->slq_vol->v_path, $1);
68     $$ = ssp_result;
69 }
70 ;
71
72 expr:
73 BOOL                             {
74     if ($1 == false)
75         YYACCEPT;
76     else
77         YYABORT;
78 }
79 | match OR match                 {
80     if (strcmp($1, $3) != 0)
81         $$ = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", $1, $3);
82     else
83         $$ = talloc_asprintf(ssp_slq, "%s", $1);
84 }
85 | match                        {$$ = $1;}
86 | function                     {$$ = $1;}
87 | OBRACE expr CBRACE           {$$ = talloc_asprintf(ssp_slq, "%s", $2);}
88 | expr AND expr                {$$ = talloc_asprintf(ssp_slq, "%s . %s", $1, $3);}
89 | expr OR expr                 {
90     if (strcmp($1, $3) != 0)
91         $$ = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", $1, $3);
92     else
93         $$ = talloc_asprintf(ssp_slq, "%s", $1);
94 }
95 ;
96
97 match:
98 WORD EQUAL QUOTE WORD QUOTE     {$$ = map_expr($1, '=', $4);}
99 | WORD UNEQUAL QUOTE WORD QUOTE {$$ = map_expr($1, '!', $4);}
100 | WORD LT QUOTE WORD QUOTE      {$$ = map_expr($1, '<', $4);}
101 | WORD GT QUOTE WORD QUOTE      {$$ = map_expr($1, '>', $4);}
102 ;
103
104 function:
105 FUNC_INRANGE OBRACE WORD COMMA DATE_SPEC OBRACE DATE CBRACE COMMA DATE_SPEC OBRACE DATE CBRACE CBRACE {$$ = map_daterange($3, $7, $12);}
106 ;
107
108 %%
109
110 const char *map_daterange(const char *dateattr, const char *date1, const char *date2)
111 {
112     char *result = NULL;
113     struct spotlight_sparql_map *p;
114
115     for (p = spotlight_sparql_map; p->ssm_spotlight_attr; p++) {
116         if (strcmp(dateattr, p->ssm_spotlight_attr) == 0) {
117             result = talloc_asprintf(ssp_slq,
118                                      "?x %s ?d FILTER (?d > '%s' && ?d < '%s')",
119                                      p->ssm_sparql_attr,
120                                      date1,
121                                      date2);
122         }
123     }
124
125
126     return result;
127 }
128
129 const char *map_expr(const char *attr, char op, const char *val)
130 {
131     char *result = NULL;
132     struct spotlight_sparql_map *p;
133
134     for (p = spotlight_sparql_map; p->ssm_spotlight_attr; p++) {
135 #if 0
136         if (strcmp(p->ssm_spotlight_attr, attr) == 0) {
137             result = talloc_asprintf(ssp_slq, p->ssm_sparql_query_fmtstr, val);
138             break;
139         }
140 #endif
141     }
142
143     return result;
144 }
145
146 void yyerror(const char *str)
147 {
148 #ifdef MAIN
149     printf("yyerror: %s\n", str);
150 #else
151     LOG(log_error, logtype_sl, "yyerror: %s", str);
152 #endif
153 }
154  
155 int yywrap()
156 {
157     return 1;
158
159
160 /**
161  * Map a Spotlight RAW query string to a SPARQL query string
162  *
163  * @param[in]     slq            Spotlight query handle
164  * @param[out]    sparql_result  Mapped SPARQL query, string is allocated in
165  *                               talloc context of slq
166  * @return        0 on success, -1 on error
167  **/
168 int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result)
169 {
170     EC_INIT;
171     YY_BUFFER_STATE s = NULL;
172
173     ssp_slq = slq;
174     s = yy_scan_string(slq->slq_qstring);
175
176     EC_ZERO( yyparse() );
177
178 EC_CLEANUP:
179     if (s)
180         yy_delete_buffer(s);
181     if (ret == 0)
182         *sparql_result = NULL;
183     else
184         *sparql_result = ssp_result;
185     EC_EXIT;
186 }
187
188 #ifdef MAIN
189 int main(int argc, char **argv)
190 {
191     int ret;
192     YY_BUFFER_STATE s;
193
194     if (argc != 2) {
195         printf("usage: %s QUERY\n", argv[0]);
196         return 1;
197     }
198
199     ssp_slq = talloc_zero(NULL, slq_t);
200     struct vol *vol = talloc_zero(ssp_slq, struct vol);
201     vol->v_path = "/Volumes/test";
202     ssp_slq->slq_vol = vol;
203
204     s = yy_scan_string(argv[1]);
205
206     ret = yyparse();
207
208     yy_delete_buffer(s);
209
210     if (ret == 0)
211         printf("SPARQL: %s\n", ssp_result ? ssp_result : "(empty)");
212
213     return 0;
214
215 #endif