summaryrefslogtreecommitdiffstats
path: root/src/expr.h
blob: cb561c8389941c886cc4f9e706db81f0807e1c6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
// Copyright © Tavian Barnes <tavianator@tavianator.com>
// SPDX-License-Identifier: 0BSD

/**
 * The expression tree representation.
 */

#ifndef BFS_EXPR_H
#define BFS_EXPR_H

#include "color.h"
#include "eval.h"
#include "stat.h"

#include <sys/types.h>
#include <time.h>

/**
 * Argument/token/expression kinds.
 */
enum bfs_kind {
	/** A flag (-H, -L, etc.). */
	BFS_FLAG,

	/** A root path. */
	BFS_PATH,

	/** An option (-follow, -mindepth, etc.). */
	BFS_OPTION,
	/** A test (-name, -size, etc.). */
	BFS_TEST,
	/** An action (-print, -exec, etc.). */
	BFS_ACTION,

	/** An operator (-and, -or, etc.). */
	BFS_OPERATOR,
};

/**
 * Integer comparison modes.
 */
enum bfs_int_cmp {
	/** Exactly N. */
	BFS_INT_EQUAL,
	/** Less than N (-N). */
	BFS_INT_LESS,
	/** Greater than N (+N). */
	BFS_INT_GREATER,
};

/**
 * Permission comparison modes.
 */
enum bfs_mode_cmp {
	/** Mode is an exact match (MODE). */
	BFS_MODE_EQUAL,
	/** Mode has all these bits (-MODE). */
	BFS_MODE_ALL,
	/** Mode has any of these bits (/MODE). */
	BFS_MODE_ANY,
};

/**
 * Possible time units.
 */
enum bfs_time_unit {
	/** Seconds. */
	BFS_SECONDS,
	/** Minutes. */
	BFS_MINUTES,
	/** Days. */
	BFS_DAYS,
};

/**
 * Possible file size units.
 */
enum bfs_size_unit {
	/** 512-byte blocks. */
	BFS_BLOCKS,
	/** Single bytes. */
	BFS_BYTES,
	/** Two-byte words. */
	BFS_WORDS,
	/** Kibibytes. */
	BFS_KB,
	/** Mebibytes. */
	BFS_MB,
	/** Gibibytes. */
	BFS_GB,
	/** Tebibytes. */
	BFS_TB,
	/** Pebibytes. */
	BFS_PB,
};

/**
 * A linked list of expressions.
 */
struct bfs_exprs {
	struct bfs_expr *head;
	struct bfs_expr **tail;
};

/**
 * A command line expression.
 */
struct bfs_expr {
	/** This expression's next sibling, if any. */
	struct bfs_expr *next;

	/** The function that evaluates this expression. */
	bfs_eval_fn *eval_fn;

	/** The number of command line arguments for this expression. */
	size_t argc;
	/** The command line arguments comprising this expression. */
	char **argv;
	/** The kind of expression this is. */
	enum bfs_kind kind;

	/** The number of files this expression keeps open between evaluations. */
	int persistent_fds;
	/** The number of files this expression opens during evaluation. */
	int ephemeral_fds;

	/** Whether this expression has no side effects. */
	bool pure;
	/** Whether this expression always evaluates to true. */
	bool always_true;
	/** Whether this expression always evaluates to false. */
	bool always_false;
	/** Whether this expression uses stat(). */
	bool calls_stat;

	/** Estimated cost. */
	float cost;
	/** Estimated probability of success. */
	float probability;
	/** Number of times this predicate was evaluated. */
	size_t evaluations;
	/** Number of times this predicate succeeded. */
	size_t successes;
	/** Total time spent running this predicate. */
	struct timespec elapsed;

	/** Auxiliary data for the evaluation function. */
	union {
		/** Child expressions. */
		struct bfs_exprs children;

		/** Integer comparisons. */
		struct {
			/** Integer for this comparison. */
			long long num;
			/** The comparison mode. */
			enum bfs_int_cmp int_cmp;

			/** -size data. */
			enum bfs_size_unit size_unit;

			/** The stat field to look at. */
			enum bfs_stat_field stat_field;
			/** The time unit. */
			enum bfs_time_unit time_unit;
			/** The reference time. */
			struct timespec reftime;
		};

		/** String comparisons. */
		struct {
			/** String pattern. */
			const char *pattern;
			/** fnmatch() flags. */
			int fnm_flags;
			/** Whether strcmp() can be used instead of fnmatch(). */
			bool literal;
		};

		/** Printing actions. */
		struct {
			/** The output stream. */
			CFILE *cfile;
			/** Optional file path. */
			const char *path;
			/** Optional -printf format. */
			struct bfs_printf *printf;
		};

		/** -exec data. */
		struct bfs_exec *exec;

		/** -flags data. */
		struct {
			/** The comparison mode. */
			enum bfs_mode_cmp flags_cmp;
			/** Flags that should be set. */
			unsigned long long set_flags;
			/** Flags that should be cleared. */
			unsigned long long clear_flags;
		};

		/** -perm data. */
		struct {
			/** The comparison mode. */
			enum bfs_mode_cmp mode_cmp;
			/** Mode to use for files. */
			mode_t file_mode;
			/** Mode to use for directories (different due to X). */
			mode_t dir_mode;
		};

		/** -regex data. */
		struct bfs_regex *regex;

		/** -samefile data. */
		struct {
			/** Device number of the target file. */
			dev_t dev;
			/** Inode number of the target file. */
			ino_t ino;
		};
	};
};

struct bfs_ctx;

/**
 * Create a new expression.
 */
struct bfs_expr *bfs_expr_new(struct bfs_ctx *ctx, bfs_eval_fn *eval, size_t argc, char **argv, enum bfs_kind kind);

/**
 * @return Whether this type of expression has children.
 */
bool bfs_expr_is_parent(const struct bfs_expr *expr);

/**
 * @return The first child of this expression, or NULL if it has none.
 */
struct bfs_expr *bfs_expr_children(const struct bfs_expr *expr);

/**
 * Add a child to an expression.
 */
void bfs_expr_append(struct bfs_expr *expr, struct bfs_expr *child);

/**
 * Add a list of children to an expression.
 */
void bfs_expr_extend(struct bfs_expr *expr, struct bfs_exprs *children);

/**
 * @return Whether expr is known to always quit.
 */
bool bfs_expr_never_returns(const struct bfs_expr *expr);

/**
 * @return The result of the integer comparison for this expression.
 */
bool bfs_expr_cmp(const struct bfs_expr *expr, long long n);

/**
 * Free any resources owned by an expression.
 */
void bfs_expr_clear(struct bfs_expr *expr);

/**
 * Iterate over the children of an expression.
 */
#define for_expr(child, expr) \
	for (struct bfs_expr *child = bfs_expr_children(expr); child; child = child->next)

#endif // BFS_EXPR_H