More GLSL code:
[mesa.git] / src / mesa / shader / slang / slang_export.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_export.c
27 * interface between assembly code and the application
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_utility.h"
33 #include "slang_export.h"
34
35 /*
36 * slang_export_data_quant
37 */
38
39 GLvoid slang_export_data_quant_ctr (slang_export_data_quant *self)
40 {
41 self->name = SLANG_ATOM_NULL;
42 self->size = 0;
43 self->array_len = 0;
44 self->structure = NULL;
45 self->u.basic_type = GL_FLOAT;
46 }
47
48 GLvoid slang_export_data_quant_dtr (slang_export_data_quant *self)
49 {
50 if (self->structure != NULL)
51 {
52 GLuint i;
53
54 for (i = 0; i < self->u.field_count; i++)
55 slang_export_data_quant_dtr (&self->structure[i]);
56 slang_alloc_free (self->structure);
57 }
58 }
59
60 slang_export_data_quant *slang_export_data_quant_add_field (slang_export_data_quant *self)
61 {
62 const GLuint n = self->u.field_count;
63
64 self->structure = (slang_export_data_quant *) slang_alloc_realloc (self->structure,
65 n * sizeof (slang_export_data_quant), (n + 1) * sizeof (slang_export_data_quant));
66 if (self->structure == NULL)
67 return NULL;
68 slang_export_data_quant_ctr (&self->structure[n]);
69 self->u.field_count++;
70 return &self->structure[n];
71 }
72
73 /*
74 * slang_export_data_entry
75 */
76
77 GLvoid slang_export_data_entry_ctr (slang_export_data_entry *self)
78 {
79 slang_export_data_quant_ctr (&self->quant);
80 self->access = slang_exp_uniform;
81 self->address = ~0;
82 }
83
84 GLvoid slang_export_data_entry_dtr (slang_export_data_entry *self)
85 {
86 slang_export_data_quant_dtr (&self->quant);
87 }
88
89 /*
90 * slang_export_data_table
91 */
92
93 GLvoid slang_export_data_table_ctr (slang_export_data_table *self)
94 {
95 self->entries = NULL;
96 self->count = 0;
97 self->atoms = NULL;
98 }
99
100 GLvoid slang_export_data_table_dtr (slang_export_data_table *self)
101 {
102 if (self->entries != NULL)
103 {
104 GLuint i;
105
106 for (i = 0; i < self->count; i++)
107 slang_export_data_entry_dtr (&self->entries[i]);
108 slang_alloc_free (self->entries);
109 }
110 }
111
112 slang_export_data_entry *slang_export_data_table_add (slang_export_data_table *self)
113 {
114 const GLuint n = self->count;
115
116 self->entries = (slang_export_data_entry *) slang_alloc_realloc (self->entries,
117 n * sizeof (slang_export_data_entry), (n + 1) * sizeof (slang_export_data_entry));
118 if (self->entries == NULL)
119 return NULL;
120 slang_export_data_entry_ctr (&self->entries[n]);
121 self->count++;
122 return &self->entries[n];
123 }
124
125 /*
126 * _slang_find_exported_data()
127 */
128
129 #define EXTRACT_ERROR 0
130 #define EXTRACT_BASIC 1
131 #define EXTRACT_ARRAY 2
132 #define EXTRACT_STRUCT 3
133 #define EXTRACT_STRUCT_ARRAY 4
134
135 #define EXTRACT_MAXLEN 255
136
137 static GLuint extract_name (const char *name, char *parsed, GLuint *element, const char **end)
138 {
139 GLuint i;
140
141 if (name[0] >= 'a' && name[0] <= 'z' || name[0] >= 'A' && name[0] <= 'Z' || name[0] == '_')
142 {
143 parsed[0] = name[0];
144
145 for (i = 1; i < EXTRACT_MAXLEN; i++)
146 {
147 if (name[i] >= 'a' && name[i] <= 'z' || name[i] >= 'A' && name[i] <= 'Z' ||
148 name[i] >= '0' && name[i] <= '9' || name[0] == '_')
149 {
150 parsed[i] = name[i];
151 }
152 else
153 {
154 if (name[i] == '\0')
155 {
156 parsed[i] = '\0';
157 return EXTRACT_BASIC;
158 }
159 if (name[i] == '.')
160 {
161 parsed[i] = '\0';
162 *end = &name[i + 1];
163 return EXTRACT_STRUCT;
164 }
165 if (name[i] == '[')
166 {
167 parsed[i] = '\0';
168 i++;
169 if (name[i] >= '0' && name[i] <= '9')
170 {
171 *element = name[i] - '0';
172 for (i++; ; i++)
173 {
174 if (name[i] >= '0' && name[i] <= '9')
175 *element = *element * 10 + (name[i] - '0');
176 else
177 {
178 if (name[i] == ']')
179 {
180 i++;
181 if (name[i] == '.')
182 {
183 *end = &name[i + 1];
184 return EXTRACT_STRUCT_ARRAY;
185 }
186 *end = &name[i];
187 return EXTRACT_ARRAY;
188 }
189 break;
190 }
191 }
192 }
193 }
194 break;
195 }
196 }
197 }
198 return EXTRACT_ERROR;
199 }
200
201 static GLboolean validate_extracted (slang_export_data_quant *q, GLuint element, GLuint extr)
202 {
203 switch (extr)
204 {
205 case EXTRACT_BASIC:
206 return GL_TRUE;
207 case EXTRACT_ARRAY:
208 return element < q->array_len;
209 case EXTRACT_STRUCT:
210 return q->structure != NULL;
211 case EXTRACT_STRUCT_ARRAY:
212 return q->structure != NULL && element < q->array_len;
213 }
214 return GL_FALSE;
215 }
216
217 static GLuint calculate_offset (slang_export_data_quant *q, GLuint element)
218 {
219 if (q->array_len != 0)
220 return element * q->size;
221 return 0;
222 }
223
224 static GLboolean find_exported_data (slang_export_data_quant *q, const char *name,
225 slang_export_data_quant **quant, GLuint *offset, slang_atom_pool *atoms)
226 {
227 char parsed[EXTRACT_MAXLEN];
228 GLuint result, element, i;
229 const char *end;
230 slang_atom atom;
231
232 result = extract_name (name, parsed, &element, &end);
233 if (result == EXTRACT_ERROR)
234 return GL_FALSE;
235
236 atom = slang_atom_pool_atom (atoms, parsed);
237 if (atom == SLANG_ATOM_NULL)
238 return GL_FALSE;
239
240 for (i = 0; i < q->u.field_count; i++)
241 if (q->structure[i].name == atom)
242 {
243 if (!validate_extracted (&q->structure[i], element, result))
244 return GL_FALSE;
245 *offset += calculate_offset (&q->structure[i], element);
246 if (result == EXTRACT_BASIC || result == EXTRACT_ARRAY)
247 {
248 if (*end != '\0')
249 return GL_FALSE;
250 *quant = &q->structure[i];
251 return GL_TRUE;
252 }
253 return find_exported_data (&q->structure[i], end, quant, offset, atoms);
254 }
255 return GL_FALSE;
256 }
257
258 GLboolean _slang_find_exported_data (slang_export_data_table *table, const char *name,
259 slang_export_data_entry **entry, slang_export_data_quant **quant, GLuint *offset)
260 {
261 char parsed[EXTRACT_MAXLEN];
262 GLuint result, element, i;
263 const char *end;
264 slang_atom atom;
265
266 result = extract_name (name, parsed, &element, &end);
267 if (result == EXTRACT_ERROR)
268 return GL_FALSE;
269
270 atom = slang_atom_pool_atom (table->atoms, parsed);
271 if (atom == SLANG_ATOM_NULL)
272 return GL_FALSE;
273
274 for (i = 0; i < table->count; i++)
275 if (table->entries[i].quant.name == atom)
276 {
277 if (!validate_extracted (&table->entries[i].quant, element, result))
278 return GL_FALSE;
279 *entry = &table->entries[i];
280 *offset = calculate_offset (&table->entries[i].quant, element);
281 if (result == EXTRACT_BASIC || result == EXTRACT_ARRAY)
282 {
283 if (*end != '\0')
284 return GL_FALSE;
285 *quant = &table->entries[i].quant;
286 return GL_TRUE;
287 }
288 return find_exported_data (&table->entries[i].quant, end, quant, offset, table->atoms);
289 }
290 return GL_FALSE;
291 }
292