1 /*
2  * $Id: fltstack.h,v 1.19 2018/10/27 11:16:47 tom Exp $
3  * A simple stack for lex states
4  */
5 
6 #ifndef FLTSTACK_H
7 #define FLTSTACK_H 1
8 /*
9  * Redefine since filters.h uses BEGIN(), which confuses our notion of current
10  * state.
11  */
12 #undef BeginQuote
13 #define BeginQuote(state, attr) \
14 			new_state(state); \
15 			flt_bfr_begin(attr); \
16 			flt_bfr_append(yytext, yyleng)
17 
18 #undef FinishQuote
19 #define FinishQuote(state) \
20 			flt_bfr_append(yytext, yyleng);\
21 			flt_bfr_finish();\
22 			new_state(state)
23 
24 typedef struct {
25     int state;
26 #ifdef FLTSTACK_EXTRA
27     FLTSTACK_EXTRA
28 #endif
29 } STACK;
30 static STACK *stk_state = 0;
31 static int cur_state;
32 
33 static int stk_limit = 0;
34 static int stk_level = -1;
35 
36 #define FLTSTACK_OK   (stk_level >= 0 && stk_level < stk_limit)
37 #define FLTSTACK_THIS stk_state[stk_level]
38 #define FLT_STATE     FLTSTACK_THIS.state
39 
40 static void new_state(int);
41 static void push_state(int);
42 static void begin_state(int);
43 static void end_state(void);
44 
45 #ifndef UNUSED_POP_STATE
46 static void pop_state(void);
47 #endif
48 
49 #else
50 
51 /*
52  * Record the given state at the current stack level, and tell lex about it.
53  */
54 static void
new_state(int code)55 new_state(int code)
56 {
57     FLEX_PRINTF((stderr, "new_state(%d)\n", code));
58     if (FLTSTACK_OK && stk_state != 0)
59 	FLT_STATE = code;
60     BEGIN(code);
61     cur_state = code;		/* antique lex's have no valid YYSTATE */
62 }
63 
64 #ifndef UNUSED_POP_STATE
65 static void
pop_state(void)66 pop_state(void)
67 {
68 #ifdef INITIAL
69     int state = INITIAL;
70 #else
71     int state = 0;	/* cater to broken "new" flex */
72 #endif
73     FLEX_PRINTF((stderr, "pop_state() level %d\n", stk_level));
74     --stk_level;
75     if (FLTSTACK_OK)
76 	state = FLT_STATE;
77     new_state(state);
78 }
79 #endif
80 
81 static void
push_state(int state)82 push_state(int state)
83 {
84     ++stk_level;
85     FLEX_PRINTF((stderr, "push_state(%d) level %d\n", state, stk_level));
86     if ((stk_level >= stk_limit) || (stk_state == 0)) {
87 	size_t have = sizeof(STACK) * (unsigned) stk_limit;
88 	size_t want = sizeof(STACK) * (unsigned) (stk_limit += (20 + stk_level));
89 	stk_state = type_alloc(STACK, (void *) stk_state, want, &have);
90     }
91 #ifdef FLTSTACK_EXTRA_PUSH
92     if (FLTSTACK_OK) {
93 	FLTSTACK_EXTRA_PUSH
94     }
95 #endif
96     new_state(state);
97 }
98 
99 /*
100  * Call this from do_filter(), to set the initial state and store that value
101  * on the stack.
102  */
103 static void
begin_state(int code)104 begin_state(int code)
105 {
106     FLEX_PRINTF((stderr, "begin_state(%d)\n", code));
107     stk_level = -1;
108     push_state(code);
109 }
110 
111 /*
112  * Cleanup
113  */
114 static void
end_state(void)115 end_state(void)
116 {
117 #if NO_LEAKS
118     if (stk_state != 0) {
119 	free(stk_state);
120 	stk_state = 0;
121     }
122 #endif
123 }
124 #endif /* FLTSTACK_H */
125