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