1 %{
2 /*
3 * Copyright © 2009 Intel Corporation
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25 #ifndef _MSC_VER
26 #include <unistd.h>
27 #endif
28
29 #include "main/glheader.h"
30
31 #include "program/prog_instruction.h"
32 #include "program/prog_statevars.h"
33 #include "program/symbol_table.h"
34 #include "program/program_parser.h"
35 #include "program/program_parse.tab.h"
36 #include "util/strtod.h"
37
38 #define require_ARB_vp (yyextra->mode == ARB_vertex)
39 #define require_ARB_fp (yyextra->mode == ARB_fragment)
40 #define require_shadow (yyextra->option.Shadow)
41 #define require_rect (yyextra->option.TexRect)
42 #define require_texarray (yyextra->option.TexArray)
43
44 #ifndef HAVE_UNISTD_H
45 #define YY_NO_UNISTD_H
46 #endif
47
48 #define return_token_or_IDENTIFIER(condition, token) \
49 do { \
50 if (condition) { \
51 return token; \
52 } else { \
53 return handle_ident(yyextra, yytext, yylval); \
54 } \
55 } while (0)
56
57 #define return_token_or_DOT(condition, token) \
58 do { \
59 if (condition) { \
60 return token; \
61 } else { \
62 yyless(1); \
63 return DOT; \
64 } \
65 } while (0)
66
67
68 #define return_opcode(condition, token, opcode, len) \
69 do { \
70 if (condition && \
71 _mesa_parse_instruction_suffix(yyextra, \
72 yytext + len, \
73 & yylval->temp_inst)) { \
74 yylval->temp_inst.Opcode = OPCODE_ ## opcode; \
75 return token; \
76 } else { \
77 return handle_ident(yyextra, yytext, yylval); \
78 } \
79 } while (0)
80
81 #define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \
82 SWIZZLE_NIL, SWIZZLE_NIL)
83
84 static unsigned
mask_from_char(char c)85 mask_from_char(char c)
86 {
87 switch (c) {
88 case 'x':
89 case 'r':
90 return WRITEMASK_X;
91 case 'y':
92 case 'g':
93 return WRITEMASK_Y;
94 case 'z':
95 case 'b':
96 return WRITEMASK_Z;
97 case 'w':
98 case 'a':
99 return WRITEMASK_W;
100 }
101
102 return 0;
103 }
104
105 static unsigned
swiz_from_char(char c)106 swiz_from_char(char c)
107 {
108 switch (c) {
109 case 'x':
110 case 'r':
111 return SWIZZLE_X;
112 case 'y':
113 case 'g':
114 return SWIZZLE_Y;
115 case 'z':
116 case 'b':
117 return SWIZZLE_Z;
118 case 'w':
119 case 'a':
120 return SWIZZLE_W;
121 }
122
123 return 0;
124 }
125
126 static int
handle_ident(struct asm_parser_state * state,const char * text,YYSTYPE * lval)127 handle_ident(struct asm_parser_state *state, const char *text, YYSTYPE *lval)
128 {
129 lval->string = strdup(text);
130
131 return (_mesa_symbol_table_find_symbol(state->st, text) == NULL)
132 ? IDENTIFIER : USED_IDENTIFIER;
133 }
134
135 #define YY_USER_ACTION \
136 do { \
137 yylloc->first_column = yylloc->last_column; \
138 yylloc->last_column += yyleng; \
139 if ((yylloc->first_line == 1) \
140 && (yylloc->first_column == 1)) { \
141 yylloc->position = 1; \
142 } else { \
143 yylloc->position += yylloc->last_column - yylloc->first_column; \
144 } \
145 } while(0);
146
147 #define YY_NO_INPUT
148
149 /* Yes, this is intentionally doing nothing. We have this line of code
150 here only to avoid the compiler complaining about an unput function
151 that is defined, but never called. */
152 #define YY_USER_INIT while (0) { unput(0); }
153
154 #define YY_EXTRA_TYPE struct asm_parser_state *
155
156 /* Flex defines a couple of functions with no declarations nor the
157 static keyword. Declare them here to avoid a compiler warning. */
158 int yyget_column (yyscan_t yyscanner);
159 void yyset_column (int column_no , yyscan_t yyscanner);
160
161 %}
162
163 num [0-9]+
164 exp [Ee][-+]?[0-9]+
165 frac "."[0-9]+
166 dot "."[ \t]*
167
168 sat (_SAT)?
169
170 %option prefix="_mesa_program_lexer_"
171 %option bison-bridge bison-locations reentrant noyywrap
172 %%
173
174 "!!ARBvp1.0" { return ARBvp_10; }
175 "!!ARBfp1.0" { return ARBfp_10; }
176 ADDRESS {
177 yylval->integer = at_address;
178 return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
179 }
180 ALIAS { return ALIAS; }
181 ATTRIB { return ATTRIB; }
182 END { return END; }
183 OPTION { return OPTION; }
184 OUTPUT { return OUTPUT; }
185 PARAM { return PARAM; }
186 TEMP { yylval->integer = at_temp; return TEMP; }
187
188 ABS{sat} { return_opcode( 1, VECTOR_OP, ABS, 3); }
189 ADD{sat} { return_opcode( 1, BIN_OP, ADD, 3); }
190 ARL { return_opcode(require_ARB_vp, ARL, ARL, 3); }
191
192 CMP{sat} { return_opcode(require_ARB_fp, TRI_OP, CMP, 3); }
193 COS{sat} { return_opcode(require_ARB_fp, SCALAR_OP, COS, 3); }
194
195 DP3{sat} { return_opcode( 1, BIN_OP, DP3, 3); }
196 DP4{sat} { return_opcode( 1, BIN_OP, DP4, 3); }
197 DPH{sat} { return_opcode( 1, BIN_OP, DPH, 3); }
198 DST{sat} { return_opcode( 1, BIN_OP, DST, 3); }
199
200 EX2{sat} { return_opcode( 1, SCALAR_OP, EX2, 3); }
201 EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); }
202
203 FLR{sat} { return_opcode( 1, VECTOR_OP, FLR, 3); }
204 FRC{sat} { return_opcode( 1, VECTOR_OP, FRC, 3); }
205
206 KIL { return_opcode(require_ARB_fp, KIL, KIL, 3); }
207
208 LIT{sat} { return_opcode( 1, VECTOR_OP, LIT, 3); }
209 LG2{sat} { return_opcode( 1, SCALAR_OP, LG2, 3); }
210 LOG { return_opcode(require_ARB_vp, SCALAR_OP, LOG, 3); }
211 LRP{sat} { return_opcode(require_ARB_fp, TRI_OP, LRP, 3); }
212
213 MAD{sat} { return_opcode( 1, TRI_OP, MAD, 3); }
214 MAX{sat} { return_opcode( 1, BIN_OP, MAX, 3); }
215 MIN{sat} { return_opcode( 1, BIN_OP, MIN, 3); }
216 MOV{sat} { return_opcode( 1, VECTOR_OP, MOV, 3); }
217 MUL{sat} { return_opcode( 1, BIN_OP, MUL, 3); }
218
219 POW{sat} { return_opcode( 1, BINSC_OP, POW, 3); }
220
221 RCP{sat} { return_opcode( 1, SCALAR_OP, RCP, 3); }
222 RSQ{sat} { return_opcode( 1, SCALAR_OP, RSQ, 3); }
223
224 SCS{sat} { return_opcode(require_ARB_fp, SCALAR_OP, SCS, 3); }
225 SGE{sat} { return_opcode( 1, BIN_OP, SGE, 3); }
226 SIN{sat} { return_opcode(require_ARB_fp, SCALAR_OP, SIN, 3); }
227 SLT{sat} { return_opcode( 1, BIN_OP, SLT, 3); }
228 SUB{sat} { return_opcode( 1, BIN_OP, SUB, 3); }
229 SWZ{sat} { return_opcode( 1, SWZ, SWZ, 3); }
230
231 TEX{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, 3); }
232 TXB{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, 3); }
233 TXP{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, 3); }
234
235 XPD{sat} { return_opcode( 1, BIN_OP, XPD, 3); }
236
237 vertex { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
238 fragment { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
239 program { return PROGRAM; }
240 state { return STATE; }
241 result { return RESULT; }
242
243 {dot}ambient { return AMBIENT; }
244 {dot}attenuation { return ATTENUATION; }
245 {dot}back { return BACK; }
246 {dot}clip { return_token_or_DOT(require_ARB_vp, CLIP); }
247 {dot}color { return COLOR; }
248 {dot}depth { return_token_or_DOT(require_ARB_fp, DEPTH); }
249 {dot}diffuse { return DIFFUSE; }
250 {dot}direction { return DIRECTION; }
251 {dot}emission { return EMISSION; }
252 {dot}env { return ENV; }
253 {dot}eye { return EYE; }
254 {dot}fogcoord { return FOGCOORD; }
255 {dot}fog { return FOG; }
256 {dot}front { return FRONT; }
257 {dot}half { return HALF; }
258 {dot}inverse { return INVERSE; }
259 {dot}invtrans { return INVTRANS; }
260 {dot}light { return LIGHT; }
261 {dot}lightmodel { return LIGHTMODEL; }
262 {dot}lightprod { return LIGHTPROD; }
263 {dot}local { return LOCAL; }
264 {dot}material { return MATERIAL; }
265 {dot}program { return MAT_PROGRAM; }
266 {dot}matrix { return MATRIX; }
267 {dot}matrixindex { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
268 {dot}modelview { return MODELVIEW; }
269 {dot}mvp { return MVP; }
270 {dot}normal { return_token_or_DOT(require_ARB_vp, NORMAL); }
271 {dot}object { return OBJECT; }
272 {dot}palette { return PALETTE; }
273 {dot}params { return PARAMS; }
274 {dot}plane { return PLANE; }
275 {dot}point { return_token_or_DOT(require_ARB_vp, POINT_TOK); }
276 {dot}pointsize { return_token_or_DOT(require_ARB_vp, POINTSIZE); }
277 {dot}position { return POSITION; }
278 {dot}primary { return PRIMARY; }
279 {dot}projection { return PROJECTION; }
280 {dot}range { return_token_or_DOT(require_ARB_fp, RANGE); }
281 {dot}row { return ROW; }
282 {dot}scenecolor { return SCENECOLOR; }
283 {dot}secondary { return SECONDARY; }
284 {dot}shininess { return SHININESS; }
285 {dot}size { return_token_or_DOT(require_ARB_vp, SIZE_TOK); }
286 {dot}specular { return SPECULAR; }
287 {dot}spot { return SPOT; }
288 {dot}texcoord { return TEXCOORD; }
289 {dot}texenv { return_token_or_DOT(require_ARB_fp, TEXENV); }
290 {dot}texgen { return_token_or_DOT(require_ARB_vp, TEXGEN); }
291 {dot}q { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
292 {dot}s { return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
293 {dot}t { return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
294 {dot}texture { return TEXTURE; }
295 {dot}transpose { return TRANSPOSE; }
296 {dot}attrib { return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
297
298 texture { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
299 1D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
300 2D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
301 3D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
302 CUBE { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
303 RECT { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
304 SHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
305 SHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
306 SHADOWRECT { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
307 ARRAY1D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
308 ARRAY2D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
309 ARRAYSHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
310 ARRAYSHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); }
311
312 [_a-zA-Z$][_a-zA-Z0-9$]* { return handle_ident(yyextra, yytext, yylval); }
313
314 ".." { return DOT_DOT; }
315
316 {num} {
317 yylval->integer = strtol(yytext, NULL, 10);
318 return INTEGER;
319 }
320 {num}?{frac}{exp}? {
321 yylval->real = _mesa_strtof(yytext, NULL);
322 return REAL;
323 }
324 {num}"."/[^.] {
325 yylval->real = _mesa_strtof(yytext, NULL);
326 return REAL;
327 }
328 {num}{exp} {
329 yylval->real = _mesa_strtof(yytext, NULL);
330 return REAL;
331 }
332 {num}"."{exp} {
333 yylval->real = _mesa_strtof(yytext, NULL);
334 return REAL;
335 }
336
337 ".xyzw" {
338 yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
339 yylval->swiz_mask.mask = WRITEMASK_XYZW;
340 return MASK4;
341 }
342
343 ".xy"[zw] {
344 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
345 yylval->swiz_mask.mask = WRITEMASK_XY
346 | mask_from_char(yytext[3]);
347 return MASK3;
348 }
349 ".xzw" {
350 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
351 yylval->swiz_mask.mask = WRITEMASK_XZW;
352 return MASK3;
353 }
354 ".yzw" {
355 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
356 yylval->swiz_mask.mask = WRITEMASK_YZW;
357 return MASK3;
358 }
359
360 ".x"[yzw] {
361 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
362 yylval->swiz_mask.mask = WRITEMASK_X
363 | mask_from_char(yytext[2]);
364 return MASK2;
365 }
366 ".y"[zw] {
367 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
368 yylval->swiz_mask.mask = WRITEMASK_Y
369 | mask_from_char(yytext[2]);
370 return MASK2;
371 }
372 ".zw" {
373 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
374 yylval->swiz_mask.mask = WRITEMASK_ZW;
375 return MASK2;
376 }
377
378 "."[xyzw] {
379 const unsigned s = swiz_from_char(yytext[1]);
380 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
381 yylval->swiz_mask.mask = mask_from_char(yytext[1]);
382 return MASK1;
383 }
384
385 "."[xyzw]{4} {
386 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
387 swiz_from_char(yytext[2]),
388 swiz_from_char(yytext[3]),
389 swiz_from_char(yytext[4]));
390 yylval->swiz_mask.mask = 0;
391 return SWIZZLE;
392 }
393
394 ".rgba" {
395 yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
396 yylval->swiz_mask.mask = WRITEMASK_XYZW;
397 return_token_or_DOT(require_ARB_fp, MASK4);
398 }
399
400 ".rg"[ba] {
401 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
402 yylval->swiz_mask.mask = WRITEMASK_XY
403 | mask_from_char(yytext[3]);
404 return_token_or_DOT(require_ARB_fp, MASK3);
405 }
406 ".rba" {
407 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
408 yylval->swiz_mask.mask = WRITEMASK_XZW;
409 return_token_or_DOT(require_ARB_fp, MASK3);
410 }
411 ".gba" {
412 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
413 yylval->swiz_mask.mask = WRITEMASK_YZW;
414 return_token_or_DOT(require_ARB_fp, MASK3);
415 }
416
417 ".r"[gba] {
418 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
419 yylval->swiz_mask.mask = WRITEMASK_X
420 | mask_from_char(yytext[2]);
421 return_token_or_DOT(require_ARB_fp, MASK2);
422 }
423 ".g"[ba] {
424 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
425 yylval->swiz_mask.mask = WRITEMASK_Y
426 | mask_from_char(yytext[2]);
427 return_token_or_DOT(require_ARB_fp, MASK2);
428 }
429 ".ba" {
430 yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
431 yylval->swiz_mask.mask = WRITEMASK_ZW;
432 return_token_or_DOT(require_ARB_fp, MASK2);
433 }
434
435 "."[gba] {
436 const unsigned s = swiz_from_char(yytext[1]);
437 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
438 yylval->swiz_mask.mask = mask_from_char(yytext[1]);
439 return_token_or_DOT(require_ARB_fp, MASK1);
440 }
441
442
443 ".r" {
444 if (require_ARB_vp) {
445 return TEXGEN_R;
446 } else {
447 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
448 SWIZZLE_X, SWIZZLE_X);
449 yylval->swiz_mask.mask = WRITEMASK_X;
450 return MASK1;
451 }
452 }
453
454 "."[rgba]{4} {
455 yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
456 swiz_from_char(yytext[2]),
457 swiz_from_char(yytext[3]),
458 swiz_from_char(yytext[4]));
459 yylval->swiz_mask.mask = 0;
460 return_token_or_DOT(require_ARB_fp, SWIZZLE);
461 }
462
463 "." { return DOT; }
464
465 \n {
466 yylloc->first_line++;
467 yylloc->first_column = 1;
468 yylloc->last_line++;
469 yylloc->last_column = 1;
470 yylloc->position++;
471 }
472 [ \t\r]+ /* eat whitespace */ ;
473 #.*$ /* eat comments */ ;
474 . { return yytext[0]; }
475 %%
476
477 void
478 _mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
479 const char *string, size_t len)
480 {
481 yylex_init_extra(state, scanner);
482 yy_scan_bytes(string, len, *scanner);
483 }
484
485 void
_mesa_program_lexer_dtor(void * scanner)486 _mesa_program_lexer_dtor(void *scanner)
487 {
488 yylex_destroy(scanner);
489 }
490