forked from sysprog21/kcalc-fixed
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexpression.h
163 lines (141 loc) · 3.71 KB
/
expression.h
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
/* MathEX is a mathematical expression evaluator.
* It takes string as input and returns floating-point number as a result.
*/
#ifndef EXPRESSION_H_
#define EXPRESSION_H_
#ifdef __KERNEL__
#include <linux/slab.h>
#else
#include <stddef.h>
#include <stdlib.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define vec(T) \
struct { \
T *buf; \
int len; \
int cap; \
}
#define vec_init() \
{ \
NULL, 0, 0 \
}
#define vec_len(v) ((v)->len)
#define vec_unpack(v) \
(char **) &(v)->buf, &(v)->len, &(v)->cap, sizeof(*(v)->buf)
#define vec_push(v, val) \
vec_expand(vec_unpack(v)) ? -1 : ((v)->buf[(v)->len++] = (val), 0)
#define vec_nth(v, i) (v)->buf[i]
#define vec_peek(v) (v)->buf[(v)->len - 1]
#define vec_pop(v) (v)->buf[--(v)->len]
#ifdef __KERNEL__
#define vec_free(v) (kfree((v)->buf), (v)->buf = NULL, (v)->len = (v)->cap = 0)
#else
#define vec_free(v) (free((v)->buf), (v)->buf = NULL, (v)->len = (v)->cap = 0)
#endif
#define vec_foreach(v, var, iter) \
if ((v)->len > 0) \
for ((iter) = 0; (iter) < (v)->len && (((var) = (v)->buf[(iter)]), 1); \
++(iter))
/* Simple expandable vector implementation */
static inline int vec_expand(char **buf, int *length, int *cap, int memsz)
{
if (*length + 1 > *cap) {
void *ptr;
int n = (*cap == 0) ? 1 : *cap << 1;
#ifdef __KERNEL__
ptr = krealloc(*buf, n * memsz, GFP_KERNEL);
#else
ptr = realloc(*buf, n * memsz);
#endif
if (!ptr)
return -1; /* allocation failed */
*buf = (char *) ptr;
*cap = n;
}
return 0;
}
/*
* Expression data types
*/
struct expr_func;
typedef vec(struct expr) vec_expr_t;
typedef void (*exprfn_cleanup_t)(struct expr_func *f, void *context);
typedef uint64_t (*exprfn_t)(struct expr_func *f,
vec_expr_t args,
void *context);
struct expr {
int type;
union {
struct {
uint64_t value;
} num;
struct {
uint64_t *value;
} var;
struct {
vec_expr_t args;
} op;
struct {
struct expr_func *f;
vec_expr_t args;
void *context;
} func;
} param;
};
struct expr_string {
const char *s;
int n;
};
struct expr_arg {
int oslen;
int eslen;
vec_expr_t args;
};
typedef vec(struct expr_string) vec_str_t;
typedef vec(struct expr_arg) vec_arg_t;
/*
* Functions
*/
struct expr_func {
const char *name;
exprfn_t f;
exprfn_cleanup_t cleanup;
size_t ctxsz;
};
struct expr_func *expr_func(struct expr_func *funcs, const char *s, size_t len);
/*
* Variables
*/
struct expr_var {
uint64_t value;
struct expr_var *next;
char name[];
};
struct expr_var_list {
struct expr_var *head;
};
struct expr_var *expr_var(struct expr_var_list *vars,
const char *s,
size_t len);
uint64_t expr_eval(struct expr *e);
#define EXPR_TOP (1 << 0)
#define EXPR_TOPEN (1 << 1)
#define EXPR_TCLOSE (1 << 2)
#define EXPR_TNUMBER (1 << 3)
#define EXPR_TWORD (1 << 4)
#define EXPR_TDEFAULT (EXPR_TOPEN | EXPR_TNUMBER | EXPR_TWORD)
#define EXPR_UNARY (1 << 5)
#define EXPR_COMMA (1 << 6)
int expr_next_token(const char *s, size_t len, int *flags);
struct expr *expr_create(const char *s,
size_t len,
struct expr_var_list *vars,
struct expr_func *funcs);
void expr_destroy(struct expr *e, struct expr_var_list *vars);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* EXPRESSION_H_ */