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
|
/* SPDX-License-Identifier: GPL-3.0-only */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h>
#include <fnmatch.h>
#include <regex.h>
#include <assert.h>
#include <lopsub.h>
#include <sys/uio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <grp.h>
#include "err.h"
/** Compute the minimum of \a x and \a y. */
#define MIN(x, y) ({ \
typeof(x) _min1 = (x); \
typeof(y) _min2 = (y); \
(void) (&_min1 == &_min2); \
_min1 < _min2 ? _min1 : _min2; })
/** Compute the maximum of \a x and \a y. */
#define MAX(x, y) ({ \
typeof(x) _max1 = (x); \
typeof(y) _max2 = (y); \
(void) (&_max1 == &_max2); \
_max1 < _max2 ? _max2 : _max1; })
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/* util.c */
extern int loglevel_arg_val;
enum loglevels {LOGLEVELS, NUM_LOGLEVELS};
void tf_log(int ll, const char* fmt,...);
#define DEBUG_LOG(f,...) tf_log(LL_DEBUG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
#define INFO_LOG(f,...) tf_log(LL_INFO, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
#define NOTICE_LOG(f,...) tf_log(LL_NOTICE, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
#define WARNING_LOG(f,...) tf_log(LL_WARNING, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
#define ERROR_LOG(f,...) tf_log(LL_ERROR, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
#define CRIT_LOG(f,...) tf_log(LL_CRIT, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
#define EMERG_LOG(f,...) tf_log(LL_EMERG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
int atoi64(const char *str, int64_t *value);
unsigned xvasprintf(char **result, const char *fmt, va_list ap);
unsigned xasprintf(char **result, const char *fmt, ...);
void *xrealloc(void *p, size_t size);
void *xmalloc(size_t size);
void *xcalloc(size_t size);
char *xstrdup(const char *str);
char *get_homedir(void);
int xregcomp(regex_t *preg, const char *regex, int cflags);
void mmap_file(const char *path, struct iovec *iov);
int fd2buf(int fd, struct iovec *result);
struct regfile_iter; /* opaque */
void regfile_iter_new(const char *dirname, struct regfile_iter **result);
bool regfile_iter_map(const struct regfile_iter *iter, struct iovec *result);
const char *regfile_iter_basename(const struct regfile_iter *iter);
const struct stat *regfile_iter_stat(const struct regfile_iter *iter);
void regfile_iter_next(struct regfile_iter *iter);
void regfile_iter_free(struct regfile_iter *iter);
/* tfortune.c */
struct epi_properties; /* opaque */
unsigned epi_len(const struct epi_properties *props);
bool epi_has_tag(const char *tag, const struct epi_properties *props);
char *epi_text(const struct epi_properties *props);
/* version.c */
const char *tf_version(void);
/* tag expression parser (ast.c, txp.lex, txp.y) */
/* Opaque, only known to ast.c. Passed to the generated txp_yyparse(). */
struct txp_context;
int txp_init(const struct iovec *definition, struct txp_context **result,
char **errmsg);
bool txp_eval_ast(const struct txp_context *ctx,
const struct epi_properties *props);
void txp_free(struct txp_context *ctx);
/* non-public API of the tag expression parser */
/*
* Since we use a reentrant lexer, all functions generated by flex(1)
* receive an additional argument of this type.
*/
typedef void *txp_yyscan_t;
/* Parsed regex pattern. */
struct txp_re_pattern {
regex_t preg; /* Pre-compiled regex. */
unsigned flags; /* Subset of the cflags described in regex(3). */
};
/*
* The possible values of a node in the abstract syntax tree (AST).
*
* Constant semantic values (string literals, numeric constants and regex
* patterns which are part of the tag expression) are determined during
* txp_init() while values which depend on the epigram (tags, number of lines,
* etc.) are determined during txp_eval_row().
*
* This union, and the txp_ast_node structure below are used extensively in
* txp.y. However, both need to be public because the lexer must be able to
* create AST nodes for the constant semantic values.
*/
union txp_semantic_value {
bool boolval; /* Comparators, =~ and =|. */
char *strval; /* String literals (e.g., argument of tag()) */
int64_t intval; /* Constants, num_lines, etc. */
struct txp_re_pattern re_pattern; /* Right-hand side operand of =~. */
};
/*
* A node is either interior or a leaf node. Interior nodes have at least one
* child while leaf nodes have a semantic value and no children.
*
* Examples: (a) STRING_LITERAL has a semantic value (the unescaped string
* literal) and no children, (b) NEG (unary minus) has no semantic value but
* one child (the numeric expression that is to be negated), (c) LESS_OR_EQUAL
* has no semantic value and two children (the two numeric expressions being
* compared).
*/
struct txp_ast_node {
/* Corresponds to a token type, for example LESS_OR_EQUAL. */
int id;
union {
/* Pointers to the child nodes (interior nodes only). */
struct txp_ast_node **children;
/* Leaf nodes only. */
union txp_semantic_value sv;
};
/*
* The number of children is implicitly given by the id, but we include
* it here to avoid having to maintain a lookup table. The AST is
* usually small, so we can afford to waste a byte per node.
*/
uint8_t num_children;
};
/* Called from both the lexer and the parser. */
__attribute__ ((format (printf, 3, 4)))
void txp_parse_error(int line, struct txp_context *ctx, const char *fmt, ...);
/* Helper functions for the lexer. */
unsigned parse_quoted_string(const char *src, const char quote_chars[2],
char **result);
int txp_parse_regex_pattern(const char *src, struct txp_re_pattern *result);
struct txp_ast_node *ast_node_new_unary(int id, struct txp_ast_node *child);
struct txp_ast_node *ast_node_new_binary(int id, struct txp_ast_node *left,
struct txp_ast_node *right);
struct txp_ast_node *txp_new_ast_leaf_node(int id);
/* linhash.c */
struct linhash_item {
const char *key;
void *object;
};
typedef int linhash_comparator(const struct linhash_item **a,
const struct linhash_item **b);
struct linhash_table;
struct linhash_iterator;
struct linhash_table *linhash_new(uint32_t order);
int linhash_insert(struct linhash_item *item, struct linhash_table *t,
void ***object);
struct linhash_item *linhash_lookup(const char *key,
const struct linhash_table *t);
void *linhash_remove(const char *key, struct linhash_table *t);
void linhash_free(struct linhash_table *t);
struct linhash_iterator *linhash_iterator_new(struct linhash_table *t,
linhash_comparator *comp, bool reverse);
struct linhash_item *linhash_iterator_item(const struct linhash_iterator *iter);
void linhash_iterator_next(struct linhash_iterator *iter);
void linhash_iterator_free(struct linhash_iterator *iter);
char *linhash_statistics(const struct linhash_table *t);
uint32_t linhash_num_items(const struct linhash_table *t);
|