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