b937d078209c8264eadf9d71a95f68ed16219f5b
[tfortune.git] / tf.h
1 /* SPDX-License-Identifier: GPL-3.0-only */
2
3 #include "config.h"
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <stdarg.h>
7 #include <stdbool.h>
8 #include <unistd.h>
9 #include <limits.h>
10 #include <string.h>
11 #include <errno.h>
12 #include <inttypes.h>
13 #include <fnmatch.h>
14 #include <regex.h>
15 #include <assert.h>
16 #include <lopsub.h>
17 #include <sys/uio.h>
18 #include <dirent.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <sys/mman.h>
22 #include <pwd.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <grp.h>
26
27 #include "err.h"
28
29 /** Compute the minimum of \a x and \a y. */
30 #define MIN(x, y) ({ \
31         typeof(x) _min1 = (x); \
32         typeof(y) _min2 = (y); \
33         (void) (&_min1 == &_min2); \
34         _min1 < _min2 ? _min1 : _min2; })
35
36 /** Compute the maximum of \a x and \a y. */
37 #define MAX(x, y) ({ \
38         typeof(x) _max1 = (x); \
39         typeof(y) _max2 = (y); \
40         (void) (&_max1 == &_max2); \
41         _max1 < _max2 ? _max2 : _max1; })
42
43 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
44
45 /* util.c */
46
47 extern int loglevel_arg_val;
48 enum loglevels {LOGLEVELS, NUM_LOGLEVELS};
49 void tf_log(int ll, const char* fmt,...);
50 #define DEBUG_LOG(f,...) tf_log(LL_DEBUG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
51 #define INFO_LOG(f,...) tf_log(LL_INFO, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
52 #define NOTICE_LOG(f,...) tf_log(LL_NOTICE, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
53 #define WARNING_LOG(f,...) tf_log(LL_WARNING, "%s: " f, __FUNCTION__, ##  __VA_ARGS__)
54 #define ERROR_LOG(f,...) tf_log(LL_ERROR, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
55 #define CRIT_LOG(f,...) tf_log(LL_CRIT, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
56 #define EMERG_LOG(f,...) tf_log(LL_EMERG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
57
58 int atoi64(const char *str, int64_t *value);
59 unsigned xvasprintf(char **result, const char *fmt, va_list ap);
60 unsigned xasprintf(char **result, const char *fmt, ...);
61 void *xrealloc(void *p, size_t size);
62 void *xmalloc(size_t size);
63 void *xcalloc(size_t size);
64 char *xstrdup(const char *str);
65 char *get_homedir(void);
66 int xregcomp(regex_t *preg, const char *regex, int cflags);
67 void mmap_file(const char *path, struct iovec *iov);
68 int fd2buf(int fd, struct iovec *result);
69
70 struct regfile_iter; /* opaque */
71 void regfile_iter_new(const char *dirname, struct regfile_iter **result);
72 bool regfile_iter_map(const struct regfile_iter *iter, struct iovec *result);
73 const char *regfile_iter_basename(const struct regfile_iter *iter);
74 const struct stat *regfile_iter_stat(const struct regfile_iter *iter);
75 void regfile_iter_next(struct regfile_iter *iter);
76 void regfile_iter_free(struct regfile_iter *iter);
77
78 /* tfortune.c */
79 struct epi_properties; /* opaque */
80 unsigned epi_len(const struct epi_properties *props);
81 bool epi_has_tag(const char *tag, const struct epi_properties *props);
82 char *epi_text(const struct epi_properties *props);
83
84 /* version.c */
85 const char *tf_version(void);
86
87 /* tag expression parser (ast.c, txp.lex, txp.y) */
88
89 /* Opaque, only known to ast.c. Passed to the generated txp_yyparse(). */
90 struct txp_context;
91
92 int txp_init(const struct iovec *definition, struct txp_context **result,
93                  char **errmsg);
94 bool txp_eval_ast(const struct txp_context *ctx,
95                 const struct epi_properties *props);
96 void txp_free(struct txp_context *ctx);
97
98 /* non-public API of the tag expression parser */
99
100 /*
101  * Since we use a reentrant lexer, all functions generated by flex(1)
102  * receive an additional argument of this type.
103  */
104 typedef void *txp_yyscan_t;
105
106 /* Parsed regex pattern. */
107 struct txp_re_pattern {
108         regex_t preg; /* Pre-compiled regex. */
109         unsigned flags; /* Subset of the cflags described in regex(3). */
110 };
111
112 /*
113  * The possible values of a node in the abstract syntax tree (AST).
114  *
115  * Constant semantic values (string literals, numeric constants and regex
116  * patterns which are part of the tag expression) are determined during
117  * txp_init() while values which depend on the epigram (tags, number of lines,
118  * etc.) are determined during txp_eval_row().
119  *
120  * This union, and the txp_ast_node structure below are used extensively in
121  * txp.y. However, both need to be public because the lexer must be able to
122  * create AST nodes for the constant semantic values.
123  */
124 union txp_semantic_value {
125         bool boolval; /* Comparators, =~ and =|. */
126         char *strval; /* String literals (e.g., argument of tag()) */
127         int64_t intval; /* Constants, num_lines, etc. */
128         struct txp_re_pattern re_pattern; /* Right-hand side operand of =~. */
129 };
130
131 /*
132  * A node is either interior or a leaf node. Interior nodes have at least one
133  * child while leaf nodes have a semantic value and no children.
134  *
135  * Examples: (a) STRING_LITERAL has a semantic value (the unescaped string
136  * literal) and no children, (b) NEG (unary minus) has no semantic value but
137  * one child (the numeric expression that is to be negated), (c) LESS_OR_EQUAL
138  * has no semantic value and two children (the two numeric expressions being
139  * compared).
140  */
141 struct txp_ast_node {
142         /* Corresponds to a token type, for example LESS_OR_EQUAL. */
143         int id;
144         union {
145                 /* Pointers to the child nodes (interior nodes only). */
146                 struct txp_ast_node **children;
147                 /* Leaf nodes only. */
148                 union txp_semantic_value sv;
149         };
150         /*
151          * The number of children is implicitly given by the id, but we include
152          * it here to avoid having to maintain a lookup table. The AST is
153          * usually small, so we can afford to waste a byte per node.
154          */
155         uint8_t num_children;
156 };
157
158 /* Called from both the lexer and the parser. */
159 __attribute__ ((format (printf, 3, 4)))
160 void txp_parse_error(int line, struct txp_context *ctx, const char *fmt, ...);
161
162 /* Helper functions for the lexer. */
163 unsigned parse_quoted_string(const char *src, const char quote_chars[2],
164                 char **result);
165 int txp_parse_regex_pattern(const char *src, struct txp_re_pattern *result);
166
167 struct txp_ast_node *ast_node_new_unary(int id, struct txp_ast_node *child);
168 struct txp_ast_node *ast_node_new_binary(int id, struct txp_ast_node *left,
169                 struct txp_ast_node *right);
170
171 struct txp_ast_node *txp_new_ast_leaf_node(int id);
172
173 /* linhash.c */
174
175 struct linhash_item {
176         const char *key;
177         void *object;
178 };
179
180 typedef int linhash_comparator(const struct linhash_item **a,
181                 const struct linhash_item **b);
182
183 struct linhash_table;
184 struct linhash_iterator;
185
186 struct linhash_table *linhash_new(uint32_t order);
187 int linhash_insert(struct linhash_item *item, struct linhash_table *t,
188                 void ***object);
189 struct linhash_item *linhash_lookup(const char *key,
190                 const struct linhash_table *t);
191 void *linhash_remove(const char *key, struct linhash_table *t);
192 void linhash_free(struct linhash_table *t);
193
194 struct linhash_iterator *linhash_iterator_new(struct linhash_table *t,
195                 linhash_comparator *comp, bool reverse);
196 struct linhash_item *linhash_iterator_item(const struct linhash_iterator *iter);
197 void linhash_iterator_next(struct linhash_iterator *iter);
198 void linhash_iterator_free(struct linhash_iterator *iter);
199
200 char *linhash_statistics(const struct linhash_table *t);
201 uint32_t linhash_num_items(const struct linhash_table *t);