Merge branch 'gallium-edgeflags'
[mesa.git] / src / glsl / pp / sl_pp_token_util.h
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #ifndef SL_PP_TOKEN_UTIL_H
29 #define SL_PP_TOKEN_UTIL_H
30
31 #include <assert.h>
32 #include <stdlib.h>
33 #include "sl_pp_token.h"
34
35
36 struct sl_pp_context;
37
38 /*
39 * A token buffer allows one to get and unget a token
40 * from a preprocessor context.
41 */
42 struct sl_pp_token_buffer {
43 struct sl_pp_context *context;
44 unsigned int size;
45 unsigned int capacity;
46 struct sl_pp_token_info *tokens;
47 };
48
49 static int
50 sl_pp_token_buffer_init(struct sl_pp_token_buffer *buffer,
51 struct sl_pp_context *context)
52 {
53 buffer->context = context;
54 buffer->size = 0;
55 buffer->capacity = 64;
56 buffer->tokens = malloc(buffer->capacity * sizeof(struct sl_pp_token_info));
57 if (!buffer->tokens) {
58 return -1;
59 }
60 return 0;
61 }
62
63 static void
64 sl_pp_token_buffer_destroy(struct sl_pp_token_buffer *buffer)
65 {
66 free(buffer->tokens);
67 }
68
69 static int
70 sl_pp_token_buffer_get(struct sl_pp_token_buffer *buffer,
71 struct sl_pp_token_info *out)
72 {
73 /* Pop from stack first if not empty. */
74 if (buffer->size) {
75 *out = buffer->tokens[--buffer->size];
76 return 0;
77 }
78
79 assert(buffer->context);
80 return sl_pp_token_get(buffer->context, out);
81 }
82
83 static void
84 sl_pp_token_buffer_unget(struct sl_pp_token_buffer *buffer,
85 const struct sl_pp_token_info *in)
86 {
87 /* Resize if needed. */
88 if (buffer->size == buffer->capacity) {
89 buffer->capacity += 64;
90 buffer->tokens = realloc(buffer->tokens,
91 buffer->capacity * sizeof(struct sl_pp_token_info));
92 assert(buffer->tokens);
93 }
94
95 /* Push token on stack. */
96 buffer->tokens[buffer->size++] = *in;
97 }
98
99 static int
100 sl_pp_token_buffer_skip_white(struct sl_pp_token_buffer *buffer,
101 struct sl_pp_token_info *out)
102 {
103 if (sl_pp_token_buffer_get(buffer, out)) {
104 return -1;
105 }
106
107 while (out->token == SL_PP_WHITESPACE) {
108 if (sl_pp_token_buffer_get(buffer, out)) {
109 return -1;
110 }
111 }
112
113 return 0;
114 }
115
116
117 /*
118 * A token peek allows one to get a number of tokens from a buffer
119 * and then either commit the operation or abort it,
120 * effectively ungetting the peeked tokens.
121 */
122 struct sl_pp_token_peek {
123 struct sl_pp_token_buffer *buffer;
124 unsigned int size;
125 unsigned int capacity;
126 struct sl_pp_token_info *tokens;
127 };
128
129 static int
130 sl_pp_token_peek_init(struct sl_pp_token_peek *peek,
131 struct sl_pp_token_buffer *buffer)
132 {
133 peek->buffer = buffer;
134 peek->size = 0;
135 peek->capacity = 64;
136 peek->tokens = malloc(peek->capacity * sizeof(struct sl_pp_token_info));
137 if (!peek->tokens) {
138 return -1;
139 }
140 return 0;
141 }
142
143 static void
144 sl_pp_token_peek_destroy(struct sl_pp_token_peek *peek)
145 {
146 /* Abort. */
147 while (peek->size) {
148 sl_pp_token_buffer_unget(peek->buffer, &peek->tokens[--peek->size]);
149 }
150 free(peek->tokens);
151 }
152
153 static int
154 sl_pp_token_peek_get(struct sl_pp_token_peek *peek,
155 struct sl_pp_token_info *out)
156 {
157 /* Get token from buffer. */
158 if (sl_pp_token_buffer_get(peek->buffer, out)) {
159 return -1;
160 }
161
162 /* Save it. */
163 if (peek->size == peek->capacity) {
164 peek->capacity += 64;
165 peek->tokens = realloc(peek->tokens,
166 peek->capacity * sizeof(struct sl_pp_token_info));
167 assert(peek->tokens);
168 }
169 peek->tokens[peek->size++] = *out;
170 return 0;
171 }
172
173 static void
174 sl_pp_token_peek_commit(struct sl_pp_token_peek *peek)
175 {
176 peek->size = 0;
177 }
178
179 static int
180 sl_pp_token_peek_to_buffer(const struct sl_pp_token_peek *peek,
181 struct sl_pp_token_buffer *buffer)
182 {
183 unsigned int i;
184
185 if (sl_pp_token_buffer_init(buffer, NULL)) {
186 return -1;
187 }
188 for (i = peek->size; i > 0; i--) {
189 sl_pp_token_buffer_unget(buffer, &peek->tokens[i - 1]);
190 }
191 return 0;
192 }
193
194 static int
195 sl_pp_token_peek_skip_white(struct sl_pp_token_peek *peek,
196 struct sl_pp_token_info *out)
197 {
198 if (sl_pp_token_peek_get(peek, out)) {
199 return -1;
200 }
201
202 while (out->token == SL_PP_WHITESPACE) {
203 if (sl_pp_token_peek_get(peek, out)) {
204 return -1;
205 }
206 }
207
208 return 0;
209 }
210
211 #endif /* SL_PP_TOKEN_UTIL_H */