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
32#define require_ARB_vp (yyextra->mode == ARB_vertex)
33#define require_ARB_fp (yyextra->mode == ARB_fragment)
34#define require_NV_fp  (yyextra->option.NV_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, 0, 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
163sz     [HRX]?
164szf    [HR]?
165cc     C?
166sat    (_SAT)?
167
168%option prefix="_mesa_program_"
169%option bison-bridge bison-locations reentrant noyywrap
170%%
171
172"!!ARBvp1.0"              { return ARBvp_10; }
173"!!ARBfp1.0"              { return ARBfp_10; }
174ADDRESS                   {
175   yylval->integer = at_address;
176   return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
177}
178ALIAS                     { return ALIAS; }
179ATTRIB                    { return ATTRIB; }
180END                       { return END; }
181OPTION                    { return OPTION; }
182OUTPUT                    { return OUTPUT; }
183PARAM                     { return PARAM; }
184TEMP                      { yylval->integer = at_temp; return TEMP; }
185
186ABS{sz}{cc}{sat}   { return_opcode(             1, VECTOR_OP, ABS, 3); }
187ADD{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, ADD, 3); }
188ARL                { return_opcode(require_ARB_vp, ARL, ARL, 3); }
189
190CMP{sat}           { return_opcode(require_ARB_fp, TRI_OP, CMP, 3); }
191COS{szf}{cc}{sat}  { return_opcode(require_ARB_fp, SCALAR_OP, COS, 3); }
192
193DDX{szf}{cc}{sat}  { return_opcode(require_NV_fp,  VECTOR_OP, DDX, 3); }
194DDY{szf}{cc}{sat}  { return_opcode(require_NV_fp,  VECTOR_OP, DDY, 3); }
195DP3{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, DP3, 3); }
196DP4{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, DP4, 3); }
197DPH{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, DPH, 3); }
198DST{szf}{cc}{sat}  { return_opcode(             1, BIN_OP, DST, 3); }
199
200EX2{szf}{cc}{sat}  { return_opcode(             1, SCALAR_OP, EX2, 3); }
201EXP                { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); }
202
203FLR{sz}{cc}{sat}   { return_opcode(             1, VECTOR_OP, FLR, 3); }
204FRC{sz}{cc}{sat}   { return_opcode(             1, VECTOR_OP, FRC, 3); }
205
206KIL                { return_opcode(require_ARB_fp, KIL, KIL, 3); }
207
208LIT{szf}{cc}{sat}  { return_opcode(             1, VECTOR_OP, LIT, 3); }
209LG2{szf}{cc}{sat}  { return_opcode(             1, SCALAR_OP, LG2, 3); }
210LOG                { return_opcode(require_ARB_vp, SCALAR_OP, LOG, 3); }
211LRP{sz}{cc}{sat}   { return_opcode(require_ARB_fp, TRI_OP, LRP, 3); }
212
213MAD{sz}{cc}{sat}   { return_opcode(             1, TRI_OP, MAD, 3); }
214MAX{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, MAX, 3); }
215MIN{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, MIN, 3); }
216MOV{sz}{cc}{sat}   { return_opcode(             1, VECTOR_OP, MOV, 3); }
217MUL{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, MUL, 3); }
218
219PK2H               { return_opcode(require_NV_fp,  VECTOR_OP, PK2H, 4); }
220PK2US              { return_opcode(require_NV_fp,  VECTOR_OP, PK2US, 5); }
221PK4B               { return_opcode(require_NV_fp,  VECTOR_OP, PK4B, 4); }
222PK4UB              { return_opcode(require_NV_fp,  VECTOR_OP, PK4UB, 5); }
223POW{szf}{cc}{sat}  { return_opcode(             1, BINSC_OP, POW, 3); }
224
225RCP{szf}{cc}{sat}  { return_opcode(             1, SCALAR_OP, RCP, 3); }
226RFL{szf}{cc}{sat}  { return_opcode(require_NV_fp,  BIN_OP,    RFL, 3); }
227RSQ{szf}{cc}{sat}  { return_opcode(             1, SCALAR_OP, RSQ, 3); }
228
229SCS{sat}           { return_opcode(require_ARB_fp, SCALAR_OP, SCS, 3); }
230SEQ{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SEQ, 3); }
231SFL{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SFL, 3); }
232SGE{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, SGE, 3); }
233SGT{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SGT, 3); }
234SIN{szf}{cc}{sat}  { return_opcode(require_ARB_fp, SCALAR_OP, SIN, 3); }
235SLE{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SLE, 3); }
236SLT{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, SLT, 3); }
237SNE{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, SNE, 3); }
238STR{sz}{cc}{sat}   { return_opcode(require_NV_fp,  BIN_OP, STR, 3); }
239SUB{sz}{cc}{sat}   { return_opcode(             1, BIN_OP, SUB, 3); }
240SWZ{sat}           { return_opcode(             1, SWZ, SWZ, 3); }
241
242TEX{cc}{sat}       { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, 3); }
243TXB{cc}{sat}       { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, 3); }
244TXD{cc}{sat}       { return_opcode(require_NV_fp,  TXD_OP, TXD, 3); }
245TXP{cc}{sat}       { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, 3); }
246
247UP2H{cc}{sat}      { return_opcode(require_NV_fp,  SCALAR_OP, UP2H, 4); }
248UP2US{cc}{sat}     { return_opcode(require_NV_fp,  SCALAR_OP, UP2US, 5); }
249UP4B{cc}{sat}      { return_opcode(require_NV_fp,  SCALAR_OP, UP4B, 4); }
250UP4UB{cc}{sat}     { return_opcode(require_NV_fp,  SCALAR_OP, UP4UB, 5); }
251
252X2D{szf}{cc}{sat}  { return_opcode(require_NV_fp,  TRI_OP, X2D, 3); }
253XPD{sat}           { return_opcode(             1, BIN_OP, XPD, 3); }
254
255vertex                    { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
256fragment                  { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
257program                   { return PROGRAM; }
258state                     { return STATE; }
259result                    { return RESULT; }
260
261{dot}ambient              { return AMBIENT; }
262{dot}attenuation          { return ATTENUATION; }
263{dot}back                 { return BACK; }
264{dot}clip                 { return_token_or_DOT(require_ARB_vp, CLIP); }
265{dot}color                { return COLOR; }
266{dot}depth                { return_token_or_DOT(require_ARB_fp, DEPTH); }
267{dot}diffuse              { return DIFFUSE; }
268{dot}direction            { return DIRECTION; }
269{dot}emission             { return EMISSION; }
270{dot}env                  { return ENV; }
271{dot}eye                  { return EYE; }
272{dot}fogcoord             { return FOGCOORD; }
273{dot}fog                  { return FOG; }
274{dot}front                { return FRONT; }
275{dot}half                 { return HALF; }
276{dot}inverse              { return INVERSE; }
277{dot}invtrans             { return INVTRANS; }
278{dot}light                { return LIGHT; }
279{dot}lightmodel           { return LIGHTMODEL; }
280{dot}lightprod            { return LIGHTPROD; }
281{dot}local                { return LOCAL; }
282{dot}material             { return MATERIAL; }
283{dot}program              { return MAT_PROGRAM; }
284{dot}matrix               { return MATRIX; }
285{dot}matrixindex          { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); }
286{dot}modelview            { return MODELVIEW; }
287{dot}mvp                  { return MVP; }
288{dot}normal               { return_token_or_DOT(require_ARB_vp, NORMAL); }
289{dot}object               { return OBJECT; }
290{dot}palette              { return PALETTE; }
291{dot}params               { return PARAMS; }
292{dot}plane                { return PLANE; }
293{dot}point                { return_token_or_DOT(require_ARB_vp, POINT_TOK); }
294{dot}pointsize            { return_token_or_DOT(require_ARB_vp, POINTSIZE); }
295{dot}position             { return POSITION; }
296{dot}primary              { return PRIMARY; }
297{dot}projection           { return PROJECTION; }
298{dot}range                { return_token_or_DOT(require_ARB_fp, RANGE); }
299{dot}row                  { return ROW; }
300{dot}scenecolor           { return SCENECOLOR; }
301{dot}secondary            { return SECONDARY; }
302{dot}shininess            { return SHININESS; }
303{dot}size                 { return_token_or_DOT(require_ARB_vp, SIZE_TOK); }
304{dot}specular             { return SPECULAR; }
305{dot}spot                 { return SPOT; }
306{dot}texcoord             { return TEXCOORD; }
307{dot}texenv               { return_token_or_DOT(require_ARB_fp, TEXENV); }
308{dot}texgen               { return_token_or_DOT(require_ARB_vp, TEXGEN); }
309{dot}q                    { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); }
310{dot}s                    { return_token_or_DOT(require_ARB_vp, TEXGEN_S); }
311{dot}t                    { return_token_or_DOT(require_ARB_vp, TEXGEN_T); }
312{dot}texture              { return TEXTURE; }
313{dot}transpose            { return TRANSPOSE; }
314{dot}attrib               { return_token_or_DOT(require_ARB_vp, VTXATTRIB); }
315{dot}weight               { return_token_or_DOT(require_ARB_vp, WEIGHT); }
316
317texture                   { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
3181D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
3192D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
3203D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
321CUBE                      { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
322RECT                      { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
323SHADOW1D                  { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
324SHADOW2D                  { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
325SHADOWRECT                { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
326ARRAY1D                   { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
327ARRAY2D                   { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
328ARRAYSHADOW1D             { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
329ARRAYSHADOW2D             { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); }
330
331[_a-zA-Z$][_a-zA-Z0-9$]*  { return handle_ident(yyextra, yytext, yylval); }
332
333".."                      { return DOT_DOT; }
334
335{num}                     {
336   yylval->integer = strtol(yytext, NULL, 10);
337   return INTEGER;
338}
339{num}?{frac}{exp}?        {
340   yylval->real = _mesa_strtof(yytext, NULL);
341   return REAL;
342}
343{num}"."/[^.]             {
344   yylval->real = _mesa_strtof(yytext, NULL);
345   return REAL;
346}
347{num}{exp}                {
348   yylval->real = _mesa_strtof(yytext, NULL);
349   return REAL;
350}
351{num}"."{exp}             {
352   yylval->real = _mesa_strtof(yytext, NULL);
353   return REAL;
354}
355
356".xyzw"                   {
357   yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
358   yylval->swiz_mask.mask = WRITEMASK_XYZW;
359   return MASK4;
360}
361
362".xy"[zw]                 {
363   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
364   yylval->swiz_mask.mask = WRITEMASK_XY
365      | mask_from_char(yytext[3]);
366   return MASK3;
367}
368".xzw"                    {
369   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
370   yylval->swiz_mask.mask = WRITEMASK_XZW;
371   return MASK3;
372}
373".yzw"                    {
374   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
375   yylval->swiz_mask.mask = WRITEMASK_YZW;
376   return MASK3;
377}
378
379".x"[yzw]                 {
380   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
381   yylval->swiz_mask.mask = WRITEMASK_X
382      | mask_from_char(yytext[2]);
383   return MASK2;
384}
385".y"[zw]                  {
386   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
387   yylval->swiz_mask.mask = WRITEMASK_Y
388      | mask_from_char(yytext[2]);
389   return MASK2;
390}
391".zw"                     {
392   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
393   yylval->swiz_mask.mask = WRITEMASK_ZW;
394   return MASK2;
395}
396
397"."[xyzw]                 {
398   const unsigned s = swiz_from_char(yytext[1]);
399   yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
400   yylval->swiz_mask.mask = mask_from_char(yytext[1]);
401   return MASK1;
402}
403
404"."[xyzw]{4}              {
405   yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
406					    swiz_from_char(yytext[2]),
407					    swiz_from_char(yytext[3]),
408					    swiz_from_char(yytext[4]));
409   yylval->swiz_mask.mask = 0;
410   return SWIZZLE;
411}
412
413".rgba"                   {
414   yylval->swiz_mask.swizzle = SWIZZLE_NOOP;
415   yylval->swiz_mask.mask = WRITEMASK_XYZW;
416   return_token_or_DOT(require_ARB_fp, MASK4);
417}
418
419".rg"[ba]                 {
420   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
421   yylval->swiz_mask.mask = WRITEMASK_XY
422      | mask_from_char(yytext[3]);
423   return_token_or_DOT(require_ARB_fp, MASK3);
424}
425".rba"                    {
426   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
427   yylval->swiz_mask.mask = WRITEMASK_XZW;
428   return_token_or_DOT(require_ARB_fp, MASK3);
429}
430".gba"                    {
431   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
432   yylval->swiz_mask.mask = WRITEMASK_YZW;
433   return_token_or_DOT(require_ARB_fp, MASK3);
434}
435
436".r"[gba]                 {
437   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
438   yylval->swiz_mask.mask = WRITEMASK_X
439      | mask_from_char(yytext[2]);
440   return_token_or_DOT(require_ARB_fp, MASK2);
441}
442".g"[ba]                  {
443   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
444   yylval->swiz_mask.mask = WRITEMASK_Y
445      | mask_from_char(yytext[2]);
446   return_token_or_DOT(require_ARB_fp, MASK2);
447}
448".ba"                     {
449   yylval->swiz_mask.swizzle = SWIZZLE_INVAL;
450   yylval->swiz_mask.mask = WRITEMASK_ZW;
451   return_token_or_DOT(require_ARB_fp, MASK2);
452}
453
454"."[gba]                  {
455   const unsigned s = swiz_from_char(yytext[1]);
456   yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s);
457   yylval->swiz_mask.mask = mask_from_char(yytext[1]);
458   return_token_or_DOT(require_ARB_fp, MASK1);
459}
460
461
462".r"                      {
463   if (require_ARB_vp) {
464      return TEXGEN_R;
465   } else {
466      yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X,
467						SWIZZLE_X, SWIZZLE_X);
468      yylval->swiz_mask.mask = WRITEMASK_X;
469      return MASK1;
470   }
471}
472
473"."[rgba]{4}              {
474   yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]),
475					    swiz_from_char(yytext[2]),
476					    swiz_from_char(yytext[3]),
477					    swiz_from_char(yytext[4]));
478   yylval->swiz_mask.mask = 0;
479   return_token_or_DOT(require_ARB_fp, SWIZZLE);
480}
481
482"."                       { return DOT; }
483
484\n                        {
485   yylloc->first_line++;
486   yylloc->first_column = 1;
487   yylloc->last_line++;
488   yylloc->last_column = 1;
489   yylloc->position++;
490}
491[ \t\r]+                  /* eat whitespace */ ;
492#.*$                      /* eat comments */ ;
493.                         { return yytext[0]; }
494%%
495
496void
497_mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state,
498			 const char *string, size_t len)
499{
500   yylex_init_extra(state, scanner);
501   yy_scan_bytes(string, len, *scanner);
502}
503
504void
505_mesa_program_lexer_dtor(void *scanner)
506{
507   yylex_destroy(scanner);
508}
509