summaryrefslogtreecommitdiffstats
path: root/src/expr.h
blob: 1628cacabc6f283f1a4f5019f349b6849b2d894b (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
// 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 <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
#include <time.h>

/**
 * 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 command line expression.
 */
struct bfs_expr {
	/** 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 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;

	/** 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;

	/** Auxilliary data for the evaluation function. */
	union {
		/** Child expressions. */
		struct {
			/** The left hand side of the expression. */
			struct bfs_expr *lhs;
			/** The right hand side of the expression. */
			struct bfs_expr *rhs;
		};

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

			/** Optional extra data. */
			union {
				/** -size data. */
				enum bfs_size_unit size_unit;

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

		/** 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;
		};
	};
};

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

/**
 * @return Whether the expression has child expressions.
 */
bool bfs_expr_is_parent(const struct bfs_expr *expr);

/**
 * @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 an expression tree.
 */
void bfs_expr_free(struct bfs_expr *expr);

#endif // BFS_EXPR_H