Mercurial > hg > toybox
comparison toys/pending/find.c @ 867:1700c6bfc8f5
find: Improve operator processing
author | Felix Janda <felix.janda@posteo.de> |
---|---|
date | Thu, 18 Apr 2013 22:37:09 +0200 |
parents | 917d6e051b82 |
children | c326f55c74bd |
comparison
equal
deleted
inserted
replaced
866:0fa773e2a4fe | 867:1700c6bfc8f5 |
---|---|
56 | 56 |
57 static struct filter_node *filter_root; | 57 static struct filter_node *filter_root; |
58 | 58 |
59 /* filter operation types */ | 59 /* filter operation types */ |
60 #define OP_UNKNOWN 0 | 60 #define OP_UNKNOWN 0 |
61 #define OP_NOT 1 | 61 #define OP_OR 2 |
62 #define OP_OR 2 | 62 #define OP_AND 3 |
63 #define OP_AND 3 | 63 #define OP_NOT 4 |
64 | 64 |
65 #define LPAREN 4 | 65 #define LPAREN 1 |
66 #define RPAREN 5 | 66 #define RPAREN 5 |
67 | |
68 #define MAX_OP 5 | |
67 | 69 |
68 #define CHECK_NAME 7 | 70 #define CHECK_NAME 7 |
69 #define CHECK_MTIME 8 | 71 #define CHECK_MTIME 8 |
70 #define CHECK_TYPE 9 | 72 #define CHECK_TYPE 9 |
71 | 73 |
109 int result; | 111 int result; |
110 char *path; | 112 char *path; |
111 int plen = 0; | 113 int plen = 0; |
112 struct stat st_buf; | 114 struct stat st_buf; |
113 time_t node_time; | 115 time_t node_time; |
114 char terminator; | 116 int op; |
117 static int skip = 0; | |
115 | 118 |
116 /* if no filters, success */ | 119 /* if no filters, success */ |
117 if (!filter) { | 120 if (!filter) { |
118 *fnext = NULL; | 121 *fnext = NULL; |
119 return 1; | 122 return 1; |
120 } | 123 } |
121 | 124 op = filter->op; |
122 if (filter->op==OP_NOT) return !evaluate(filter->next, node, fnext); | 125 |
123 | 126 if (op==OP_NOT) return !evaluate(filter->next, node, fnext); |
124 if (filter->op==OP_OR) | 127 |
125 return evaluate(filter->next, node, fnext) || evaluate(*fnext, node, fnext); | 128 if (op==OP_OR || op==OP_AND) { |
126 | 129 result = evaluate(filter->next, node, fnext); |
127 if (filter->op==OP_AND) | 130 if(!skip) { |
128 return evaluate(filter->next, node, fnext) && evaluate(*fnext, node, fnext); | 131 if (op==OP_OR) { |
132 skip = result; | |
133 result = evaluate(*fnext, node, fnext) || result; | |
134 } else { | |
135 skip = !result; | |
136 result = evaluate(*fnext, node, fnext) && result; | |
137 } | |
138 skip = 0; | |
139 } | |
140 else result = evaluate(*fnext, node, fnext); | |
141 return result; | |
142 } | |
129 | 143 |
130 // we're down to single operations, mark our position | 144 // we're down to single operations, mark our position |
131 *fnext = filter->next; | 145 *fnext = filter->next; |
146 if(skip) return 0; | |
132 | 147 |
133 // TODO: Do a regex comparison | 148 // TODO: Do a regex comparison |
134 if (filter->op==CHECK_NAME) | 149 if (op==CHECK_NAME) |
135 return !strcmp(filter->data.name_regex, node->name); | 150 return !strcmp(filter->data.name_regex, node->name); |
136 | 151 |
137 if (filter->op==CHECK_MTIME) { | 152 if (op==CHECK_MTIME) { |
138 // do mtime check | 153 // do mtime check |
139 path = dirtree_path(node, &plen); | 154 path = dirtree_path(node, &plen); |
140 result = stat(path, &st_buf); | 155 result = stat(path, &st_buf); |
141 free(path); | 156 free(path); |
142 if (result<0) return 0; | 157 if (result<0) return 0; |
161 break; | 176 break; |
162 } | 177 } |
163 return result; | 178 return result; |
164 | 179 |
165 } | 180 } |
166 if (filter->op==CHECK_TYPE) { | 181 if (op==CHECK_TYPE) { |
167 path = dirtree_path(node, &plen); | 182 path = dirtree_path(node, &plen); |
168 result = lstat(path, &st_buf); | 183 result = lstat(path, &st_buf); |
169 free(path); | 184 free(path); |
170 if (result<0) return 0; | 185 if (result<0) return 0; |
171 return (st_buf.st_mode & S_IFMT) == filter->data.type; | 186 return (st_buf.st_mode & S_IFMT) == filter->data.type; |
172 } | 187 } |
173 | 188 |
174 | 189 |
175 if (filter->op==ACTION_PRINT || filter->op==ACTION_PRINT0) { | 190 if (op==ACTION_PRINT || op==ACTION_PRINT0) { |
176 terminator = (filter->op==ACTION_PRINT)*'\n'; | 191 char terminator = (op==ACTION_PRINT)*'\n'; |
177 | 192 |
178 path = dirtree_path(node, &plen); | 193 path = dirtree_path(node, &plen); |
179 printf("%s%c", path, terminator); | 194 printf("%s%c", path, terminator); |
180 free(path); | 195 free(path); |
181 return 1; | 196 return 1; |
182 } | 197 } |
183 | 198 |
184 if (filter->op==ACTION_EXEC) return !do_exec(filter, node); | 199 if (op==ACTION_EXEC) return !do_exec(filter, node); |
185 | 200 |
186 error_msg("Ran out of operations in filter list!"); | 201 error_msg("Ran out of operations in filter list!"); |
187 return 1; | 202 return 1; |
188 } | 203 } |
189 | 204 |
216 static void build_filter_list(void) | 231 static void build_filter_list(void) |
217 { | 232 { |
218 struct filter_node *node_list, *op_stack, *node, *op_node, *next; | 233 struct filter_node *node_list, *op_stack, *node, *op_node, *next; |
219 char *arg, **arg_array; | 234 char *arg, **arg_array; |
220 int i, j; | 235 int i, j; |
236 int prevop = 0; | |
221 | 237 |
222 /* part optargs here and build a filter list in prefix format */ | 238 /* part optargs here and build a filter list in prefix format */ |
223 | 239 |
224 TT.dir = "."; | 240 TT.dir = "."; |
225 node_list = NULL; | 241 node_list = NULL; |
301 } | 317 } |
302 if (node->op == OP_UNKNOWN) { | 318 if (node->op == OP_UNKNOWN) { |
303 if (arg[0] == '-') error_exit("bad option '%s'", arg); | 319 if (arg[0] == '-') error_exit("bad option '%s'", arg); |
304 else TT.dir = arg; | 320 else TT.dir = arg; |
305 } else { | 321 } else { |
322 // add OP_AND where necessary | |
323 if (node_list) { | |
324 int o1 = node_list->op, o2 = node->op; | |
325 if ((o1>MAX_OP && o2>MAX_OP) || | |
326 (o1==RPAREN && o2>=OP_NOT && o2!=RPAREN) || | |
327 (o1>=OP_NOT && o1!=LPAREN && o2==LPAREN)) { | |
328 struct filter_node *n = (struct filter_node *) | |
329 xmalloc(sizeof(struct filter_node)); | |
330 n->op = OP_AND; | |
331 n->next = node_list; | |
332 node_list = n; | |
333 } | |
334 } | |
306 /* push node */ | 335 /* push node */ |
307 node->next = node_list;; | 336 node->next = node_list;; |
308 node_list = node; | 337 node_list = node; |
309 } | 338 } |
310 | 339 |
313 /* now convert from infix to prefix */ | 342 /* now convert from infix to prefix */ |
314 filter_root = NULL; | 343 filter_root = NULL; |
315 op_stack = NULL; | 344 op_stack = NULL; |
316 node = node_list; | 345 node = node_list; |
317 while( node ) { | 346 while( node ) { |
347 int op = node->op; | |
318 next = node->next; | 348 next = node->next; |
319 switch( node->op ) { | 349 if (op==LPAREN || op==RPAREN) { |
320 case OP_AND: | 350 free(node); |
321 case OP_OR: | 351 node = 0; |
322 case OP_NOT: | 352 } |
323 case RPAREN: | 353 if (op<=MAX_OP) { |
324 /* push to opstack */ | 354 if (prevop > op) { |
325 node->next = op_stack; | 355 /* pop opstack to output */ |
326 op_stack = node; | |
327 break; | |
328 case LPAREN: | |
329 free(node); | |
330 /* pop opstack to output (up to rparen) */ | |
331 op_node = op_stack; | 356 op_node = op_stack; |
332 while (op_node && op_node->op != RPAREN) { | 357 while (op_node) { |
333 /* remove from op_stack */ | 358 /* remove from op_stack */ |
334 op_stack = op_node->next; | 359 op_stack = op_node->next; |
335 /* push to output */ | 360 /* push to output */ |
336 op_node->next = filter_root; | 361 op_node->next = filter_root; |
337 filter_root = op_node; | 362 filter_root = op_node; |
338 /* get next node */ | 363 /* get next node */ |
339 op_node = op_stack; | 364 op_node = op_stack; |
340 } | 365 } |
341 /* rparen should be on op_stack */ | 366 } |
342 if (!op_stack) error_exit("need ')'"); | 367 if (node) { |
343 /* remove rparen from op_stack */ | 368 /* push to opstack */ |
344 op_stack = op_stack->next; | 369 node->next = op_stack; |
345 free(op_node); | 370 op_stack = node; |
346 break; | 371 } |
347 default: | 372 prevop = op*(op!=RPAREN); |
373 } | |
374 else { | |
348 /* push to output */ | 375 /* push to output */ |
349 node->next = filter_root; | 376 node->next = filter_root; |
350 filter_root = node; | 377 filter_root = node; |
351 break; | |
352 } | 378 } |
353 node = next; | 379 node = next; |
354 } | 380 } |
355 /* end of input - push opstack to output */ | 381 /* end of input - push opstack to output */ |
356 /* pop opstack to output till empty */ | 382 /* pop opstack to output till empty */ |
357 op_node = op_stack; | 383 op_node = op_stack; |
358 while (op_node) { | 384 while (op_node) { |
359 /*if (op_node->op == RPAREN || op_node->op == LPAREN) { | |
360 error_exit("Error: extra paren found\n"); | |
361 } | |
362 */ | |
363 op_stack = op_node->next; | 385 op_stack = op_node->next; |
364 op_node->next = filter_root; | 386 op_node->next = filter_root; |
365 filter_root = op_node; | 387 filter_root = op_node; |
366 op_node = op_stack; | 388 op_node = op_stack; |
367 } | 389 } |