]> arthur.barton.de Git - netatalk.git/blob - etc/spotlight/slmod_tracker_0_6_parser.y
Merge branch 'develop' into spotlight
[netatalk.git] / etc / spotlight / slmod_tracker_0_6_parser.y
1 %code top {
2   #include <atalk/standards.h>
3
4   #include <stdbool.h>
5   #include <stdio.h>
6   #include <string.h>
7   #include <time.h>
8
9   #include <gio/gio.h>
10   #include <tracker.h>
11
12   #include <atalk/talloc.h>
13   #include <atalk/logger.h>
14   #include <atalk/errchk.h>
15   #include <atalk/spotlight.h>
16
17   #include "slmod_tracker_0_6_map.h"
18
19   struct yy_buffer_state;
20   typedef struct yy_buffer_state *YY_BUFFER_STATE;
21   extern int yylex (void);
22   extern void yyerror (char const *);
23   extern void *yyterminate(void);
24   extern YY_BUFFER_STATE yy_scan_string( const char *str);
25   extern void yy_delete_buffer ( YY_BUFFER_STATE buffer );
26
27   /* forward declarations */
28   static char *map_expr(const char *attr, char op, const char *val);
29   static time_t isodate2unix(const char *s);
30  
31  /* global vars, eg needed by the lexer */
32   slq_t *ts_slq;
33
34   /* local vars */
35   static ServiceType ts_type;   /* Tracker query object type */
36   static gchar *ts_search;      /* Tracker query search term */
37 }
38
39 %code provides {
40   #define SPRAW_TIME_OFFSET 978307200
41   extern int map_spotlight_to_tracker_0_6_query(slq_t *slq, ServiceType *type, gchar **search);
42   extern slq_t *ts_slq;
43 }
44
45 %union {
46     int ival;
47     char *sval;
48     bool bval;
49     time_t tval;
50 }
51
52 %expect 5
53 %error-verbose
54
55 %type <sval> match function expr line
56 %type <tval> date
57
58 %token <sval> WORD
59 %token <bval> BOOL
60 %token FUNC_INRANGE
61 %token DATE_ISO
62 %token OBRACE CBRACE EQUAL UNEQUAL GT LT COMMA QUOTE
63 %left AND
64 %left OR
65 %%
66
67 input:
68 /* empty */
69 | input line
70 ;
71
72 line:
73 expr                           {
74     ts_search = $1;
75     $$ = $1;
76 }
77 ;
78      
79 expr:
80 BOOL                             {
81     if ($1 == false)
82         YYACCEPT;
83     else
84         YYABORT;
85 }
86 | match OR match                 {
87     if (strcmp($1, $3) != 0)
88         YYABORT;
89     else
90         $$ = $1;
91 }
92 | match                        {$$ = $1;}
93 | function                     {$$ = $1;}
94 | OBRACE expr CBRACE           {$$ = $2;}
95 | expr AND expr                {
96     if ($1 && $3) {
97         if (strcmp($1, $3) != 0)
98             YYABORT;
99         else
100             $$ = $1;
101     } else if ($1)
102         $$ = $1;
103     else if ($3)
104         $$ = $3;
105     else
106         YYABORT;
107 }
108 | expr OR expr                 {YYABORT;}
109 ;
110
111 match:
112 WORD EQUAL QUOTE WORD QUOTE          {$$ = map_expr($1, '=', $4);}
113 | WORD UNEQUAL QUOTE WORD QUOTE      {YYABORT;}
114 | WORD LT QUOTE WORD QUOTE           {YYABORT;}
115 | WORD GT QUOTE WORD QUOTE           {YYABORT;}
116 | WORD EQUAL QUOTE WORD QUOTE WORD   {$$ = map_expr($1, '=', $4);}
117 | WORD UNEQUAL QUOTE WORD QUOTE WORD {YYABORT;}
118 | WORD LT QUOTE WORD QUOTE WORD      {YYABORT;}
119 | WORD GT QUOTE WORD QUOTE WORD      {YYABORT;}
120 ;
121
122 function:
123 FUNC_INRANGE OBRACE WORD COMMA date COMMA date CBRACE {YYABORT;}
124 ;
125
126 date:
127 DATE_ISO OBRACE WORD CBRACE    {$$ = isodate2unix($3);}
128 | WORD                         {$$ = atoi($1) + SPRAW_TIME_OFFSET;}
129 ;
130
131 %%
132
133 static time_t isodate2unix(const char *s)
134 {
135     struct tm tm;
136
137     if (strptime(s, "%Y-%m-%dT%H:%M:%SZ", &tm) == NULL)
138         return (time_t)-1;
139     return mktime(&tm);
140 }
141
142 static void map_type_search(const char *val)
143 {
144     for (struct MDTypeMap *p = MDTypeMap; p->mdtm_value; p++) {
145         if (strcmp(p->mdtm_value, val) == 0) {
146             if (p->mdtm_type == -1)
147                 ts_type = SERVICE_OTHER_FILES;
148             else
149                 ts_type = p->mdtm_type;
150             return;
151         }
152     }
153     ts_type = SERVICE_OTHER_FILES;
154 }
155
156 static char *map_expr(const char *attr, char op, const char *val)
157 {
158     EC_INIT;
159     bstring q, search, replace;
160     char *result = NULL;
161
162     for (struct spotlight_tracker_map *p = spotlight_tracker_map; p->stm_spotlight_attr; p++) {
163         if (strcmp(p->stm_spotlight_attr, attr) == 0) {
164             switch (p->stm_type) {
165             case stmt_name:
166             case stmt_fts:
167                 q = bfromcstr(val);
168                 search = bfromcstr("*");
169                 replace = bfromcstr("");
170                 bfindreplace(q, search, replace, 0);
171                 result = talloc_strdup(ts_slq, bdata(q));
172                 bdestroy(q);
173                 bdestroy(search);
174                 bdestroy(replace);
175                 break;
176
177             case stmt_type:
178                 map_type_search(val);
179                 return NULL;
180
181             default:
182                 yyerror("unknown Spotlight attribute type");
183                 EC_FAIL;
184             }
185             break;
186         }
187     }
188
189
190
191 EC_CLEANUP:
192     return result;
193 }
194
195 void yyerror(const char *str)
196 {
197 #ifdef MAIN
198     printf("yyerror: %s\n", str);
199 #else
200     LOG(log_error, logtype_sl, "yyerror: %s", str);
201 #endif
202 }
203  
204 int yywrap()
205 {
206     return 1;
207
208
209 /**
210  * Map a Spotlight RAW query string to a Tracker 0.6 query
211  *
212  * @param[in]     slq      Spotlight query handle
213  * @param[out]    type     mapped file type
214  * @param[out]    search   mapped search term
215  * @return        0 on success, -1 on error
216  **/
217 int map_spotlight_to_tracker_0_6_query(slq_t *slq_in,
218                                        ServiceType *type,
219                                        gchar **search)
220 {
221     EC_INIT;
222     YY_BUFFER_STATE s = NULL;
223
224     ts_slq = slq_in;
225     s = yy_scan_string(ts_slq->slq_qstring);
226
227     /* Default object type is file */
228     *type = SERVICE_FILES;
229     *search = NULL;
230
231     EC_ZERO( yyparse() );
232     *type = ts_type;
233     *search = ts_search;
234
235 EC_CLEANUP:
236     if (s)
237         yy_delete_buffer(s);
238     EC_EXIT;
239 }
240
241 #ifdef MAIN
242 int main(int argc, char **argv)
243 {
244     int ret;
245     YY_BUFFER_STATE s;
246
247     if (argc != 2) {
248         printf("usage: %s QUERY\n", argv[0]);
249         return 1;
250     }
251
252     ts_slq = talloc_zero(NULL, slq_t);
253     struct vol *vol = talloc_zero(ts_slq, struct vol);
254     vol->v_path = "/Volumes/test";
255     ts_slq->slq_vol = vol;
256
257     s = yy_scan_string(argv[1]);
258
259     ret = yyparse();
260
261     yy_delete_buffer(s);
262
263     if (ret == 0) {
264         printf("Tracker 0.6 query: service: %s, searchterm: %s\n",
265                tracker_type_to_service_name(ts_type), ts_search);
266     }
267
268     return ret;
269
270 #endif