]> git.tuebingen.mpg.de Git - tfortune.git/blob - tf.h
initial
[tfortune.git] / tf.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6 #include <stdbool.h>
7 #include <limits.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <inttypes.h>
11 #include <fnmatch.h>
12 #include <regex.h>
13 #include <assert.h>
14 #include <lopsub.h>
15
16 #include "err.h"
17
18 /* Opaque, only known to ast.c. Passed to the generated txp_yyparse(). */
19 struct txp_context;
20
21 /*
22  * Since we use a reentrant lexer, all functions generated by flex(1)
23  * receive an additional argument of this type.
24  */
25 typedef void *txp_yyscan_t;
26
27 /* Parsed regex pattern. */
28 struct txp_re_pattern {
29         regex_t preg; /* Pre-compiled regex. */
30         unsigned flags; /* Subset of the cflags described in regex(3). */
31 };
32
33 /*
34  * The possible values of a node in the abstract syntax tree (AST).
35  *
36  * Constant semantic values (string literals, numeric constants and regex
37  * patterns which are part of the tag expression) are determined during
38  * txp_init() while values which depend on the epigram (tags, number of lines,
39  * etc.) are determined during txp_eval_row().
40  *
41  * This union, and the txp_ast_node structure below are used extensively in
42  * txp.y. However, both need to be public because the lexer must be able to
43  * create AST nodes for the constant semantic values.
44  */
45 union txp_semantic_value {
46         bool boolval; /* Comparators, =~ and =|. */
47         char *strval; /* String literals, tags, path. */
48         int64_t intval; /* Constants, bitrate, frequency, etc. */
49         struct txp_re_pattern re_pattern; /*< Right-hand side operand of =~. */
50 };
51
52 /*
53  * A node is either interior or a leaf node. Interior nodes have at least one
54  * child while leaf nodes have a semantic value and no children.
55  *
56  * Examples: (a) STRING_LITERAL has a semantic value (the unescaped string
57  * literal) and no children, (b) NEG (unary minus) has no semantic value but
58  * one child (the numeric expression that is to be negated), (c) LESS_OR_EQUAL
59  * has no semantic value and two children (the two numeric expressions being
60  * compared).
61  */
62 struct txp_ast_node {
63         /* Corresponds to a token type, for example LESS_OR_EQUAL. */
64         int id;
65         union {
66                 /* Pointers to the child nodes (interior nodes only). */
67                 struct txp_ast_node **children;
68                 /* Leaf nodes only. */
69                 union txp_semantic_value sv;
70         };
71         /*
72          * The number of children is implicitly given by the id, but we include
73          * it here to avoid having to maintain a lookup table. The AST is
74          * usually small, so we can afford to waste a byte per node.
75          */
76         uint8_t num_children;
77 };
78
79 enum loglevels {LOGLEVELS, NUM_LOGLEVELS};
80 #define DEBUG_LOG(f,...) txp_log(LL_DEBUG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
81 #define INFO_LOG(f,...) txp_log(LL_INFO, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
82 #define NOTICE_LOG(f,...) txp_log(LL_NOTICE, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
83 #define WARNING_LOG(f,...) txp_log(LL_WARNING, "%s: " f, __FUNCTION__, ##  __VA_ARGS__)
84 #define ERROR_LOG(f,...) txp_log(LL_ERROR, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
85 #define CRIT_LOG(f,...) txp_log(LL_CRIT, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
86 #define EMERG_LOG(f,...) txp_log(LL_EMERG, "%s: " f, __FUNCTION__, ## __VA_ARGS__)
87
88 /* tfortune.c */
89
90 void txp_log(int ll, const char* fmt,...);
91
92 /* Called from both the lexer and the parser. */
93 __attribute__ ((format (printf, 3, 4)))
94 void txp_parse_error(int line, struct txp_context *ctx, const char *fmt, ...);
95
96 /* Helper functions for the lexer. */
97 unsigned parse_quoted_string(const char *src, const char quote_chars[2],
98                 char **result);
99 int txp_parse_regex_pattern(const char *src, struct txp_re_pattern *result);
100
101 /* ast.c */
102 struct txp_ast_node *ast_node_new_unary(int id, struct txp_ast_node *child);
103 struct txp_ast_node *ast_node_new_binary(int id, struct txp_ast_node *left,
104                 struct txp_ast_node *right);
105
106 /*
107  * Allocate a new leaf node for the abstract syntax tree.
108  *
109  * This returns a pointer to a node whose ->num_children field is initialized
110  * to zero. The ->id field is initialized with the given id.  The caller is
111  * expected to initialize the ->sv field.
112  */
113 struct txp_ast_node *txp_new_ast_leaf_node(int id);
114
115 /*
116  * Evaluate an abstract syntax tree, starting at the root node.
117  *
118  * The root node argument should be the pointer that was returned from an
119  * earlier call to txp_init() via the context pointer. The context contains the
120  * information about the epigram.
121  *
122  * Returns true if the AST evaluates to true, a non-empty string, or a non-zero
123  * number, false otherwise.
124  */
125 bool txp_eval_ast(struct txp_ast_node *root, struct txp_context *ctx);
126
127 /*
128  * Deallocate an abstract syntax tree.
129  *
130  * This frees the memory occupied by the nodes of the AST, the child pointers
131  * of the internal nodes and the (constant) semantic values of the leaf nodes
132  * (string literals and pre-compiled regular expressions).
133  */
134 void txp_free_ast(struct txp_ast_node *root);
135
136
137 /* util.c */
138 int atoi64(const char *str, int64_t *value);
139 unsigned xvasprintf(char **result, const char *fmt, va_list ap);
140 unsigned xasprintf(char **result, const char *fmt, ...);
141 void *xmalloc(size_t size);
142 void *xcalloc(size_t size);
143 int xregcomp(regex_t *preg, const char *regex, int cflags);
144
145 /* txp.c */
146
147 /* txp.y. */
148