239
/* Returns true if the specified predicate is reorderable. */
241
predicate_is_cost_free(const struct predicate *p)
243
if (pred_is(p, pred_name) ||
244
pred_is(p, pred_path) ||
245
pred_is(p, pred_iname) ||
246
pred_is(p, pred_ipath))
248
/* Traditionally (at least 4.1.7 through 4.2.x) GNU find always
249
* optimised these cases.
253
else if (options.optimisation_level > 0)
255
if (pred_is(p, pred_and) ||
256
pred_is(p, pred_negate) ||
257
pred_is(p, pred_comma) ||
261
return NeedsNothing == p->p_cost;
269
/* Prints a predicate */
270
void print_predicate(FILE *fp, const struct predicate *p)
272
fprintf (fp, "%s%s%s",
274
p->arg_text ? " " : "",
275
p->arg_text ? p->arg_text : "");
281
struct predicate *head;
282
struct predicate *tail;
286
predlist_init(struct predlist *p)
288
p->head = p->tail = NULL;
292
predlist_insert(struct predlist *list,
293
struct predicate *curr,
294
struct predicate **pprev)
296
struct predicate **insertpos = &(list->head);
298
*pprev = curr->pred_left;
299
if (options.optimisation_level > 2)
301
/* Insert the new node in the list after any other entries which
302
* are more selective.
305
while ( (*insertpos) && ((*insertpos)->est_success_rate < curr->est_success_rate) )
307
insertpos = &((*insertpos)->pred_left);
310
curr->pred_left = (*insertpos);
312
if (NULL == list->tail)
313
list->tail = list->head;
317
pred_cost_compare(const struct predicate *p1, const struct predicate *p2, boolean wantfailure)
319
if (p1->p_cost == p2->p_cost)
321
if (p1->est_success_rate == p2->est_success_rate)
323
else if (wantfailure)
324
return p1->est_success_rate < p2->est_success_rate ? -1 : 1;
326
return p1->est_success_rate < p2->est_success_rate ? 1 : -1;
330
return p1->p_cost < p2->p_cost ? -1 : 1;
336
predlist_merge_sort(struct predlist *list,
337
struct predicate **last)
339
struct predlist new_list;
340
struct predicate *p, *q;
342
if (NULL == list->head)
343
return; /* nothing to do */
345
if (options.debug_options & DebugTreeOpt)
347
fprintf(stderr, "%s:\n", "predlist before merge sort");
348
print_tree(stderr, list->head, 2);
351
calculate_derived_rates(list->head);
352
predlist_init(&new_list);
355
/* remove head of source list */
357
list->head = list->head->pred_left;
360
/* insert it into the new list */
361
for (p=new_list.head; p; p=p->pred_left)
363
/* If these operations are OR operations, we want to get a
364
* successful test as soon as possible, to take advantage of
365
* the short-circuit evaluation. If they're AND, we want to
366
* get an unsuccessful result early for the same reason.
367
* Therefore we invert the sense of the comparison for the
368
* OR case. We only want to invert the sense of the success
369
* rate comparison, not the operation cost comparison. Hence we
370
* pass a flag into pred_cost_compare().
372
boolean wantfailure = (OR_PREC != p->p_prec);
373
if (pred_cost_compare(p->pred_right, q->pred_right, wantfailure) >= 0)
378
/* insert into existing list */
379
q->pred_left = p->pred_left;
380
if (NULL == q->pred_left)
386
q->pred_left = new_list.head; /* prepend */
388
if (NULL == new_list.tail)
389
new_list.tail = q; /* first item in new list */
392
if (options.debug_options & DebugTreeOpt)
394
fprintf(stderr, "%s:\n", "predlist after merge sort");
395
print_tree(stderr, new_list.head, 2);
398
calculate_derived_rates(new_list.head);
399
merge_pred(new_list.head, new_list.tail, last);
404
merge_lists(struct predlist lists[], int nlists,
405
struct predlist *name_list,
406
struct predlist *regex_list,
407
struct predicate **last)
410
static void (*mergefn)(struct predlist *, struct predicate**);
412
mergefn = predlist_merge_sort;
414
mergefn(name_list, last);
415
mergefn(regex_list, last);
417
for (i=0; i<nlists; i++)
418
mergefn(&lists[i], last);
424
subtree_has_side_effects(const struct predicate *p)
428
return p->side_effects
429
|| subtree_has_side_effects(p->pred_left)
430
|| subtree_has_side_effects(p->pred_right);
440
worst_cost (const struct predicate *p)
444
unsigned int cost_r, cost_l, worst;
445
cost_l = worst_cost(p->pred_left);
446
cost_r = worst_cost(p->pred_right);
447
worst = (cost_l > cost_r) ? cost_l : cost_r;
448
if (worst < p->p_cost)
461
perform_arm_swap(struct predicate *p)
463
struct predicate *tmp = p->pred_left->pred_right;
464
p->pred_left->pred_right = p->pred_right;
468
/* Consider swapping p->pred_left->pred_right with p->pred_right,
469
* if that yields a faster evaluation. Normally the left predicate is
472
* If the operation is an OR, we want the left predicate to be the one that
473
* succeeds most often. If it is an AND, we want it to be the predicate that
476
* We don't consider swapping arms of an operator where their cost is
477
* different or where they have side effects.
479
* A viable test case for this is
480
* ./find -D opt -O3 . \! -type f -o -type d
481
* Here, the ! -type f should be evaluated first,
482
* as we assume that 95% of inodes are vanilla files.
485
consider_arm_swap(struct predicate *p)
487
int left_cost, right_cost;
488
const char *reason = NULL;
489
struct predicate **pl, **pr;
491
if (BI_OP != p->p_type)
492
reason = "Not a binary operation";
496
if (NULL == p->pred_left || NULL == p->pred_right)
497
reason = "Doesn't have two arms";
503
if (NULL == p->pred_left->pred_right)
504
reason = "Left arm has no child on RHS";
507
pl = &p->pred_left->pred_right;
511
if (subtree_has_side_effects(*pl))
512
reason = "Left subtree has side-effects";
516
if (subtree_has_side_effects(*pr))
517
reason = "Right subtree has side-effects";
522
left_cost = worst_cost(*pl);
523
right_cost = worst_cost(*pr);
525
if (left_cost < right_cost)
527
reason = "efficient as-is";
534
if (left_cost == right_cost)
536
/* it's a candidate */
537
float succ_rate_l = (*pl)->est_success_rate;
538
float succ_rate_r = (*pr)->est_success_rate;
540
if (options.debug_options & DebugTreeOpt)
542
fprintf(stderr, "Success rates: l=%f, r=%f\n", succ_rate_l, succ_rate_r);
545
if (pred_is(p, pred_or))
547
want_swap = succ_rate_r < succ_rate_l;
549
reason = "Operation is OR and right success rate >= left";
551
else if (pred_is(p, pred_and))
553
want_swap = succ_rate_r > succ_rate_l;
555
reason = "Operation is AND and right success rate <= left";
560
reason = "Not AND or OR";
570
if (options.debug_options & DebugTreeOpt)
572
fprintf(stderr, "Performing arm swap on:\n");
573
print_tree (stderr, p, 0);
581
if (options.debug_options & DebugTreeOpt)
583
fprintf(stderr, "Not an arm swap candidate (%s):\n", reason);
584
print_tree (stderr, p, 0);
590
do_arm_swaps(struct predicate *p)
598
if (consider_arm_swap(p)
599
|| do_arm_swaps(p->pred_left)
600
|| do_arm_swaps(p->pred_right))
179
615
/* Optimize the ordering of the predicates in the tree. Rearrange
180
616
them to minimize work. Strategies:
181
617
* Evaluate predicates that don't need inode information first;
425
888
that a stat is made as late as possible. Return true if the top node
426
889
in TREE requires a stat, false if not. */
429
mark_stat (struct predicate *tree)
431
/* The tree is executed in-order, so walk this way (apologies to Aerosmith)
432
to find the first predicate for which the stat is needed. */
433
switch (tree->p_type)
437
return tree->need_stat;
440
if (mark_stat (tree->pred_right))
441
tree->need_stat = true;
445
/* ANDs and ORs are linked along ->left ending in NULL. */
446
if (tree->pred_left != NULL)
447
mark_stat (tree->pred_left);
449
if (mark_stat (tree->pred_right))
450
tree->need_stat = true;
455
error (1, 0, _("oops -- invalid expression type in mark_stat!"));
460
/* Find the first node in expression tree TREE that we will
461
need to know the file type, if any. Operates in the same
465
mark_type (struct predicate *tree)
467
/* The tree is executed in-order, so walk this way (apologies to Aerosmith)
468
to find the first predicate for which the type information is needed. */
469
switch (tree->p_type)
473
return tree->need_type;
476
if (mark_type (tree->pred_right))
477
tree->need_type = true;
481
/* ANDs and ORs are linked along ->left ending in NULL. */
482
if (tree->pred_left != NULL)
483
mark_type (tree->pred_left);
485
if (mark_type (tree->pred_right))
486
tree->need_type = true;
491
error (1, 0, _("oops -- invalid expression type in mark_type!"));
892
struct pred_cost_lookup
895
enum EvaluationCost cost;
897
static struct pred_cost_lookup costlookup[] =
899
{ pred_amin , NeedsStatInfo },
900
{ pred_and , NeedsNothing, },
901
{ pred_anewer , NeedsStatInfo, },
902
{ pred_atime , NeedsStatInfo, },
903
{ pred_closeparen, NeedsNothing },
904
{ pred_cmin , NeedsStatInfo, },
905
{ pred_cnewer , NeedsStatInfo, },
906
{ pred_comma , NeedsNothing, },
907
{ pred_ctime , NeedsStatInfo, },
908
{ pred_delete , NeedsSyncDiskHit },
909
{ pred_empty , NeedsStatInfo },
910
{ pred_exec , NeedsEventualExec },
911
{ pred_execdir , NeedsEventualExec },
912
{ pred_executable, NeedsAccessInfo },
913
{ pred_false , NeedsNothing },
914
{ pred_fprint , NeedsNothing },
915
{ pred_fprint0 , NeedsNothing },
916
{ pred_fprintf , NeedsNothing },
917
{ pred_fstype , NeedsStatInfo }, /* true for amortised cost */
918
{ pred_gid , NeedsStatInfo },
919
{ pred_group , NeedsStatInfo },
920
{ pred_ilname , NeedsLinkName },
921
{ pred_iname , NeedsNothing },
922
{ pred_inum , NeedsStatInfo },
923
{ pred_ipath , NeedsNothing },
924
{ pred_links , NeedsStatInfo },
925
{ pred_lname , NeedsLinkName },
926
{ pred_ls , NeedsStatInfo },
927
{ pred_fls , NeedsStatInfo },
928
{ pred_mmin , NeedsStatInfo },
929
{ pred_mtime , NeedsStatInfo },
930
{ pred_name , NeedsNothing },
931
{ pred_negate , NeedsNothing, },
932
{ pred_newer , NeedsStatInfo, },
933
{ pred_newerXY , NeedsStatInfo, },
934
{ pred_nogroup , NeedsStatInfo }, /* true for amortised cost if caching is on */
935
{ pred_nouser , NeedsStatInfo }, /* true for amortised cost if caching is on */
936
{ pred_ok , NeedsUserInteraction },
937
{ pred_okdir , NeedsUserInteraction },
938
{ pred_openparen , NeedsNothing },
939
{ pred_or , NeedsNothing, },
940
{ pred_path , NeedsNothing },
941
{ pred_perm , NeedsStatInfo },
942
{ pred_print , NeedsNothing },
943
{ pred_print0 , NeedsNothing },
944
{ pred_prune , NeedsNothing },
945
{ pred_quit , NeedsNothing },
946
{ pred_readable , NeedsAccessInfo },
947
{ pred_regex , NeedsNothing },
948
{ pred_samefile , NeedsStatInfo },
949
{ pred_size , NeedsStatInfo },
950
{ pred_true , NeedsNothing },
951
{ pred_type , NeedsType },
952
{ pred_uid , NeedsStatInfo },
953
{ pred_used , NeedsStatInfo },
954
{ pred_user , NeedsStatInfo },
955
{ pred_writable , NeedsAccessInfo },
956
{ pred_xtype , NeedsType } /* roughly correct unless most files are symlinks */
958
static int pred_table_sorted = 0;
961
check_sorted(void *base, size_t members, size_t membersize,
962
int (*cmpfn)(const void*, const void*))
964
const char *p = base;
966
for (i=1u; i<members; ++i)
968
int result = cmpfn(p+i*membersize, p+(i-1)*membersize);
971
result = cmpfn(p+(i-1)*membersize, p+i*membersize);
972
assert (result <= 0);
979
cost_table_comparison(const void *p1, const void *p2)
981
/* We have to compare the function pointers with memcmp(),
982
* because ISO C does not allow magnitude comparison of
983
* function pointers (just equality testing).
985
const struct pred_cost_lookup *pc1 = p1;
986
const struct pred_cost_lookup *pc2 = p2;
989
char mem[sizeof (PRED_FUNC)];
994
return memcmp(u1.mem, u2.mem, sizeof(u1.pfn));
997
static enum EvaluationCost
998
get_pred_cost(const struct predicate *p)
1000
enum EvaluationCost data_requirement_cost = NeedsNothing;
1001
enum EvaluationCost inherent_cost = NeedsUnknown;
1005
data_requirement_cost = NeedsStatInfo;
1007
else if (p->need_type)
1009
data_requirement_cost = NeedsType;
1013
data_requirement_cost = NeedsNothing;
1016
if (pred_is(p, pred_exec) || pred_is(p, pred_execdir))
1018
if (p->args.exec_vec.multiple)
1019
inherent_cost = NeedsEventualExec;
1021
inherent_cost = NeedsImmediateExec;
1023
else if (pred_is(p, pred_fprintf))
1025
/* the parser calculated the cost for us. */
1026
inherent_cost = p->p_cost;
1030
struct pred_cost_lookup key;
1033
if (!pred_table_sorted)
1036
sizeof(costlookup)/sizeof(costlookup[0]),
1037
sizeof(costlookup[0]),
1038
cost_table_comparison);
1040
if (!check_sorted(costlookup,
1041
sizeof(costlookup)/sizeof(costlookup[0]),
1042
sizeof(costlookup[0]),
1043
cost_table_comparison))
1045
error(1, 0, "Failed to sort the costlookup array (indirect).");
1047
pred_table_sorted = 1;
1049
key.fn = p->pred_func;
1050
entry = bsearch(&key, costlookup,
1051
sizeof(costlookup)/sizeof(costlookup[0]),
1052
sizeof(costlookup[0]),
1053
cost_table_comparison);
1056
inherent_cost = ((const struct pred_cost_lookup*)entry)->cost;
1060
error(0, 0, "warning: no cost entry for predicate %s", p->p_name);
1061
inherent_cost = NeedsUnknown;
1065
if (inherent_cost > data_requirement_cost)
1066
return inherent_cost;
1068
return data_requirement_cost;
1072
estimate_costs (struct predicate *tree)
1076
estimate_costs(tree->pred_right);
1077
estimate_costs(tree->pred_left);
1079
tree->p_cost = get_pred_cost(tree);
1090
getrate(const struct predicate *p)
1093
return p->est_success_rate;
1100
calculate_derived_rates(struct predicate *p)
1105
calculate_derived_rates(p->pred_right);
1107
calculate_derived_rates(p->pred_left);
1109
assert (p->p_type != CLOSE_PAREN);
1110
assert (p->p_type != OPEN_PAREN);
1115
assert (NULL == p->pred_right);
1116
assert (NULL == p->pred_left);
1117
return p->est_success_rate;
1120
assert (NULL == p->pred_right);
1121
assert (NULL == p->pred_left);
1122
return p->est_success_rate;
1125
/* Unary operators must have exactly one operand */
1126
assert (pred_is(p, pred_negate));
1127
assert (NULL == p->pred_left);
1128
p->est_success_rate = (1.0 - p->pred_right->est_success_rate);
1129
return p->est_success_rate;
1134
/* Binary operators must have two operands */
1135
if (pred_is(p, pred_and))
1137
rate = getrate(p->pred_right) * getrate(p->pred_left);
1139
else if (pred_is(p, pred_comma))
1143
else if (pred_is(p, pred_or))
1145
rate = getrate(p->pred_right) + getrate(p->pred_left);
1149
/* only and, or and comma are BI_OP. */
1153
p->est_success_rate = constrain_rate(rate);
1155
return p->est_success_rate;
1159
p->est_success_rate = 1.0;
1160
return p->est_success_rate;
1166
/* opt_expr() rearranges predicates such that each left subtree is
1167
* rooted at a logical predicate (e.g. and or or). check_normalization()
1168
* asserts that this property still holds.
1171
static void check_normalization(struct predicate *p, boolean at_root)
1175
assert (BI_OP == p->p_type);
1180
assert (BI_OP == p->pred_left->p_type);
1181
check_normalization(p->pred_left, false);
1185
check_normalization(p->pred_right, false);
1190
build_expression_tree(int argc, char *argv[], int end_of_leading_options)
1192
const struct parser_table *parse_entry; /* Pointer to the parsing table entry for this expression. */
1193
char *predicate_name; /* Name of predicate being parsed. */
1194
struct predicate *cur_pred;
1195
const struct parser_table *entry_close, *entry_print, *entry_open;
1200
/* Find where in ARGV the predicates begin by skipping the list of
1203
for (i = end_of_leading_options; i < argc && !looks_like_expression(argv[i], true); i++)
1208
/* Enclose the expression in `( ... )' so a default -print will
1209
apply to the whole expression. */
1210
entry_open = find_parser("(");
1211
entry_close = find_parser(")");
1212
entry_print = find_parser("print");
1213
assert (entry_open != NULL);
1214
assert (entry_close != NULL);
1215
assert (entry_print != NULL);
1217
parse_openparen (entry_open, argv, &argc);
1218
last_pred->p_name = "(";
1219
predicates->artificial = true;
1220
parse_begin_user_args(argv, argc, last_pred, predicates);
1221
pred_sanity_check(last_pred);
1223
/* Build the input order list. */
1226
if (!looks_like_expression(argv[i], false))
1228
error (0, 0, _("paths must precede expression: %s"), argv[i]);
1229
usage(stderr, 1, NULL);
1232
predicate_name = argv[i];
1233
parse_entry = find_parser (predicate_name);
1234
if (parse_entry == NULL)
1236
/* Command line option not recognized */
1237
error (1, 0, _("unknown predicate `%s'"), predicate_name);
1240
/* We have recognised a test of the form -foo. Eat that,
1241
* unless it is a predicate like -newerXY.
1243
if (parse_entry->type != ARG_SPECIAL_PARSE)
1248
if (!(*(parse_entry->parser_func)) (parse_entry, argv, &i))
1252
if ( (ARG_SPECIAL_PARSE == parse_entry->type) && (i == oldi) )
1254
/* The special parse function spat out the
1255
* predicate. It must be invalid, or not tasty.
1257
error (1, 0, _("invalid predicate `%s'"),
1262
error (1, 0, _("invalid argument `%s' to `%s'"),
1263
argv[i], predicate_name);
1268
/* Command line option requires an argument */
1269
error (1, 0, _("missing argument to `%s'"), predicate_name);
1274
last_pred->p_name = predicate_name;
1276
/* If the parser consumed an argument, save it. */
1278
last_pred->arg_text = argv[oldi];
1280
last_pred->arg_text = NULL;
1282
pred_sanity_check(last_pred);
1283
pred_sanity_check(predicates); /* XXX: expensive */
1285
parse_end_user_args(argv, argc, last_pred, predicates);
1286
if (predicates->pred_next == NULL)
1288
/* No predicates that do something other than set a global variable
1289
were given; remove the unneeded initial `(' and add `-print'. */
1290
cur_pred = predicates;
1291
predicates = last_pred = predicates->pred_next;
1293
parse_print (entry_print, argv, &argc);
1294
last_pred->p_name = "-print";
1295
pred_sanity_check(last_pred);
1296
pred_sanity_check(predicates); /* XXX: expensive */
1298
else if (!default_prints (predicates->pred_next))
1300
/* One or more predicates that produce output were given;
1301
remove the unneeded initial `('. */
1302
cur_pred = predicates;
1303
predicates = predicates->pred_next;
1304
pred_sanity_check(predicates); /* XXX: expensive */
1309
/* `( user-supplied-expression ) -print'. */
1310
parse_closeparen (entry_close, argv, &argc);
1311
last_pred->p_name = ")";
1312
last_pred->artificial = true;
1313
pred_sanity_check(last_pred);
1314
parse_print (entry_print, argv, &argc);
1315
last_pred->p_name = "-print";
1316
last_pred->artificial = true;
1317
pred_sanity_check(last_pred);
1318
pred_sanity_check(predicates); /* XXX: expensive */
1321
if (options.debug_options & (DebugExpressionTree|DebugTreeOpt))
1323
fprintf (stderr, "Predicate List:\n");
1324
print_list (stderr, predicates);
1327
/* do a sanity check */
1328
check_option_combinations(predicates);
1329
pred_sanity_check(predicates);
1331
/* Done parsing the predicates. Build the evaluation tree. */
1332
cur_pred = predicates;
1333
eval_tree = get_expr (&cur_pred, NO_PREC, NULL);
1334
calculate_derived_rates(eval_tree);
1336
/* Check if we have any left-over predicates (this fixes
1337
* Debian bug #185202).
1339
if (cur_pred != NULL)
1341
/* cur_pred->p_name is often NULL here */
1342
if (pred_is(cur_pred, pred_closeparen))
1344
/* e.g. "find \( -true \) \)" */
1345
error (1, 0, _("you have too many ')'"));
1349
if (cur_pred->p_name)
1350
error (1, 0, _("unexpected extra predicate '%s'"), cur_pred->p_name);
1352
error (1, 0, _("unexpected extra predicate"));
1356
if (options.debug_options & (DebugExpressionTree|DebugTreeOpt))
1358
fprintf (stderr, "Eval Tree:\n");
1359
print_tree (stderr, eval_tree, 0);
1362
estimate_costs(eval_tree);
1364
/* Rearrange the eval tree in optimal-predicate order. */
1365
opt_expr (&eval_tree);
1367
/* Check that the tree is in normalised order (opt_expr does this) */
1368
check_normalization(eval_tree, true);
1370
do_arm_swaps(eval_tree);
1372
/* Check that the tree is still in normalised order */
1373
check_normalization(eval_tree, true);
1375
if (options.debug_options & (DebugExpressionTree|DebugTreeOpt))
1377
fprintf (stderr, "Optimized Eval Tree:\n");
1378
print_tree (stderr, eval_tree, 0);
1379
fprintf (stderr, "Optimized command line:\n");
1380
print_optlist(stderr, eval_tree);
1381
fprintf(stderr, "\n");
1387
/* Initialise the performance data for a predicate.
1390
init_pred_perf(struct predicate *pred)
1392
struct predicate_performance_info *p = &pred->perf;
1393
p->visits = p->successes = 0;
1397
/* Return a pointer to a new predicate structure, which has been
1398
linked in as the last one in the predicates list.
1400
Set `predicates' to point to the start of the predicates list.
1401
Set `last_pred' to point to the new last predicate in the list.
1403
Set all cells in the new structure to the default values. */
1406
get_new_pred (const struct parser_table *entry)
1408
register struct predicate *new_pred;
1411
/* Options should not be turned into predicates. */
1412
assert (entry->type != ARG_OPTION);
1413
assert (entry->type != ARG_POSITIONAL_OPTION);
1415
if (predicates == NULL)
1417
predicates = (struct predicate *)
1418
xmalloc (sizeof (struct predicate));
1419
last_pred = predicates;
1423
new_pred = xmalloc (sizeof (struct predicate));
1424
last_pred->pred_next = new_pred;
1425
last_pred = new_pred;
1427
last_pred->parser_entry = entry;
1428
last_pred->pred_func = NULL;
1429
last_pred->p_name = NULL;
1430
last_pred->p_type = NO_TYPE;
1431
last_pred->p_prec = NO_PREC;
1432
last_pred->side_effects = false;
1433
last_pred->no_default_print = false;
1434
last_pred->need_stat = true;
1435
last_pred->need_type = true;
1436
last_pred->args.str = NULL;
1437
last_pred->pred_next = NULL;
1438
last_pred->pred_left = NULL;
1439
last_pred->pred_right = NULL;
1440
last_pred->literal_control_chars = options.literal_control_chars;
1441
last_pred->artificial = false;
1442
last_pred->est_success_rate = 1.0;
1443
init_pred_perf(last_pred);
1447
/* Return a pointer to a new predicate, with operator check.
1448
Like get_new_pred, but it checks to make sure that the previous
1449
predicate is an operator. If it isn't, the AND operator is inserted. */
1452
get_new_pred_chk_op (const struct parser_table *entry)
1454
struct predicate *new_pred;
1455
static const struct parser_table *entry_and = NULL;
1457
/* Locate the entry in the parser table for the "and" operator */
1458
if (NULL == entry_and)
1459
entry_and = find_parser("and");
1461
/* Check that it's actually there. If not, that is a bug.*/
1462
assert (entry_and != NULL);
1465
switch (last_pred->p_type)
1468
error (1, 0, _("oops -- invalid default insertion of and!"));
1473
/* We need to interpose the and operator. */
1474
new_pred = get_new_pred (entry_and);
1475
new_pred->pred_func = pred_and;
1476
new_pred->p_name = "-a";
1477
new_pred->p_type = BI_OP;
1478
new_pred->p_prec = AND_PREC;
1479
new_pred->need_stat = false;
1480
new_pred->need_type = false;
1481
new_pred->args.str = NULL;
1482
new_pred->side_effects = false;
1483
new_pred->no_default_print = false;
1490
new_pred = get_new_pred (entry);
1491
new_pred->parser_entry = entry;
1497
enum EvaluationCost cost;
1500
struct cost_assoc cost_table[] =
1502
{ NeedsNothing, "Nothing" },
1503
{ NeedsType, "Type" },
1504
{ NeedsStatInfo, "StatInfo" },
1505
{ NeedsLinkName, "LinkName" },
1506
{ NeedsAccessInfo, "AccessInfo" },
1507
{ NeedsSyncDiskHit, "SyncDiskHit" },
1508
{ NeedsEventualExec, "EventualExec" },
1509
{ NeedsImmediateExec, "ImmediateExec" },
1510
{ NeedsUserInteraction, "UserInteraction" },
1511
{ NeedsUnknown, "Unknown" }
1520
static struct prec_assoc prec_table[] =
1523
{COMMA_PREC, "comma"},
1526
{NEGATE_PREC, "negate"},
1537
static struct op_assoc type_table[] =
1540
{PRIMARY_TYPE, "primary"},
1543
{OPEN_PAREN, "open_paren "},
1544
{CLOSE_PAREN, "close_paren "},
1549
cost_name (enum EvaluationCost cost)
1552
unsigned int n = sizeof(cost_table)/sizeof(cost_table[0]);
1554
for (i = 0; i<n; ++i)
1555
if (cost_table[i].cost == cost)
1556
return cost_table[i].name;
1567
for (i = 0; type_table[i].type != (short) -1; i++)
1568
if (type_table[i].type == type)
1570
return (type_table[i].type_name);
1579
for (i = 0; prec_table[i].prec != (short) -1; i++)
1580
if (prec_table[i].prec == prec)
1582
return (prec_table[i].prec_name);
1586
/* Walk the expression tree NODE to stdout.
1587
INDENT is the number of levels to indent the left margin. */
1590
print_tree (FILE *fp, struct predicate *node, int indent)
1596
for (i = 0; i < indent; i++)
1598
fprintf (fp, "pred=[");
1599
print_predicate(fp, node);
1600
fprintf (fp, "] type=%s prec=%s",
1601
type_name (node->p_type), prec_name (node->p_prec));
1602
fprintf (fp, " cost=%s rate=%#03.2g %sside effects ",
1603
cost_name(node->p_cost),
1604
node->est_success_rate,
1605
(node->side_effects ? "" : "no "));
1607
if (node->need_stat || node->need_type)
1611
fprintf (fp, "Needs ");
1612
if (node->need_stat)
1614
fprintf (fp, "stat");
1617
if (node->need_type)
1619
fprintf (fp, "%stype", comma ? "," : "");
1625
for (i = 0; i < indent; i++)
1627
if (NULL == node->pred_left && NULL == node->pred_right)
1629
fprintf (fp, "no children.\n");
1633
if (node->pred_left)
1635
fprintf (fp, "left:\n");
1636
print_tree (fp, node->pred_left, indent + 1);
1640
fprintf (fp, "no left.\n");
1643
for (i = 0; i < indent; i++)
1645
if (node->pred_right)
1647
fprintf (fp, "right:\n");
1648
print_tree (fp, node->pred_right, indent + 1);
1652
fprintf (fp, "no right.\n");