-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsimple.c
158 lines (130 loc) · 3.34 KB
/
simple.c
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
#include "simple.h"
#include "config.h"
#include "libks/arena.h"
#include "options.h"
enum simple_state {
SIMPLE_STATE_NOP = -1,
SIMPLE_STATE_DISABLE = 0,
SIMPLE_STATE_ENABLE = 1,
SIMPLE_STATE_IGNORE = 2,
};
struct simple {
struct {
enum simple_state state;
unsigned int flags;
} passes[SIMPLE_LAST];
int enable;
};
static int is_pass_mutually_exclusive(const struct simple *,
enum simple_pass);
struct simple *
simple_alloc(struct arena_scope *eternal_scope, const struct options *op)
{
struct simple *si;
si = arena_calloc(eternal_scope, 1, sizeof(*si));
si->enable = op->simple;
return si;
}
int
simple_enter(struct simple *si, enum simple_pass pass, unsigned int flags,
struct simple_cookie *cookie)
{
*cookie = (struct simple_cookie){
.si = si,
.pass = pass,
.state = si->passes[pass].state,
};
if (!si->enable && (flags & SIMPLE_FORCE) == 0) {
si->passes[pass].state = SIMPLE_STATE_IGNORE;
return 0;
}
if (is_pass_mutually_exclusive(si, pass)) {
unsigned int i;
for (i = 0; i < SIMPLE_LAST; i++) {
if (i != pass &&
si->passes[i].state != SIMPLE_STATE_DISABLE) {
si->passes[pass].state = SIMPLE_STATE_DISABLE;
return 0;
}
}
}
if ((flags & SIMPLE_IGNORE) ||
si->passes[pass].state != SIMPLE_STATE_DISABLE) {
si->passes[pass].state = SIMPLE_STATE_IGNORE;
return 0;
}
si->passes[pass].state = SIMPLE_STATE_ENABLE;
si->passes[pass].flags = flags;
return 1;
}
void
simple_leave(struct simple_cookie *cookie)
{
struct simple *si = cookie->si;
enum simple_pass pass = cookie->pass;
enum simple_state state = cookie->state;
if (si == NULL)
return;
*cookie = (struct simple_cookie){0};
if (state == SIMPLE_STATE_NOP)
return;
si->passes[pass].state = state;
}
int
is_simple_enabled(const struct simple *si, enum simple_pass pass)
{
return (si->enable || (si->passes[pass].flags & SIMPLE_FORCE)) &&
si->passes[pass].state == SIMPLE_STATE_ENABLE;
}
int
simple_disable(struct simple *si)
{
int restore = si->enable;
si->enable = 0;
return restore;
}
void
simple_enable(struct simple *si, int restore)
{
si->enable = restore;
}
/*
* All passes are mutually exclusive by default. However, some combinations are
* explicitly allowed as they do not interfere with each other.
*/
static int
is_pass_mutually_exclusive(const struct simple *si, enum simple_pass pass)
{
static const struct {
enum simple_pass parent;
enum simple_pass nested;
} exceptions[] = {
{ SIMPLE_DECL, SIMPLE_BRACES },
{ SIMPLE_DECL, SIMPLE_DECL_PROTO },
{ SIMPLE_DECL, SIMPLE_IMPLICIT_INT },
{ SIMPLE_DECL, SIMPLE_STATIC },
/*
* SIMPLE_DECL_FORWARD only operates on root level declarations
* as opposed to SIMPLE_DECL which only operates on nested
* levels. They should therefore not interfere.
*/
{ SIMPLE_DECL, SIMPLE_DECL_FORWARD },
{ SIMPLE_EXPR_PARENS, SIMPLE_EXPR_SIZEOF },
{ SIMPLE_STMT, SIMPLE_STMT_EMPTY_LOOP },
{ SIMPLE_STMT_EMPTY_LOOP, SIMPLE_STMT },
};
unsigned int nexceptions = sizeof(exceptions) / sizeof(exceptions[0]);
unsigned int i;
for (i = 0; i < SIMPLE_LAST; i++) {
unsigned int j;
if (si->passes[i].state != SIMPLE_STATE_ENABLE &&
si->passes[i].state != SIMPLE_STATE_IGNORE)
continue;
for (j = 0; j < nexceptions; j++) {
if (exceptions[j].parent == i &&
exceptions[j].nested == pass)
return 0;
}
}
return 1;
}