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
84static unsigned
85mask_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
105static unsigned
106swiz_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
126static int
127handle_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
150here only to avoid the compiler complaining about an unput function
151that 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
157static keyword. Declare them here to avoid a compiler warning. */
158int yyget_column  (yyscan_t yyscanner);
159void yyset_column (int  column_no , yyscan_t yyscanner);
160
161%}
162
163num    [0-9]+
164exp    [Ee][-+]?[0-9]+
165frac   "."[0-9]+
166dot    "."[ \t]*
167
168sat    (_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; }
176ADDRESS                   {
177   yylval->integer = at_address;
178   return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS);
179}
180ALIAS                     { return ALIAS; }
181ATTRIB                    { return ATTRIB; }
182END                       { return END; }
183OPTION                    { return OPTION; }
184OUTPUT                    { return OUTPUT; }
185PARAM                     { return PARAM; }
186TEMP                      { yylval->integer = at_temp; return TEMP; }
187
188ABS{sat}           { return_opcode(             1, VECTOR_OP, ABS, 3); }
189ADD{sat}           { return_opcode(             1, BIN_OP, ADD, 3); }
190ARL                { return_opcode(require_ARB_vp, ARL, ARL, 3); }
191
192CMP{sat}           { return_opcode(require_ARB_fp, TRI_OP, CMP, 3); }
193COS{sat}           { return_opcode(require_ARB_fp, SCALAR_OP, COS, 3); }
194
195DP3{sat}           { return_opcode(             1, BIN_OP, DP3, 3); }
196DP4{sat}           { return_opcode(             1, BIN_OP, DP4, 3); }
197DPH{sat}           { return_opcode(             1, BIN_OP, DPH, 3); }
198DST{sat}           { return_opcode(             1, BIN_OP, DST, 3); }
199
200EX2{sat}           { return_opcode(             1, SCALAR_OP, EX2, 3); }
201EXP                { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); }
202
203FLR{sat}           { return_opcode(             1, VECTOR_OP, FLR, 3); }
204FRC{sat}           { return_opcode(             1, VECTOR_OP, FRC, 3); }
205
206KIL                { return_opcode(require_ARB_fp, KIL, KIL, 3); }
207
208LIT{sat}           { return_opcode(             1, VECTOR_OP, LIT, 3); }
209LG2{sat}           { return_opcode(             1, SCALAR_OP, LG2, 3); }
210LOG                { return_opcode(require_ARB_vp, SCALAR_OP, LOG, 3); }
211LRP{sat}           { return_opcode(require_ARB_fp, TRI_OP, LRP, 3); }
212
213MAD{sat}           { return_opcode(             1, TRI_OP, MAD, 3); }
214MAX{sat}           { return_opcode(             1, BIN_OP, MAX, 3); }
215MIN{sat}           { return_opcode(             1, BIN_OP, MIN, 3); }
216MOV{sat}           { return_opcode(             1, VECTOR_OP, MOV, 3); }
217MUL{sat}           { return_opcode(             1, BIN_OP, MUL, 3); }
218
219POW{sat}           { return_opcode(             1, BINSC_OP, POW, 3); }
220
221RCP{sat}           { return_opcode(             1, SCALAR_OP, RCP, 3); }
222RSQ{sat}           { return_opcode(             1, SCALAR_OP, RSQ, 3); }
223
224SCS{sat}           { return_opcode(require_ARB_fp, SCALAR_OP, SCS, 3); }
225SGE{sat}           { return_opcode(             1, BIN_OP, SGE, 3); }
226SIN{sat}           { return_opcode(require_ARB_fp, SCALAR_OP, SIN, 3); }
227SLT{sat}           { return_opcode(             1, BIN_OP, SLT, 3); }
228SUB{sat}           { return_opcode(             1, BIN_OP, SUB, 3); }
229SWZ{sat}           { return_opcode(             1, SWZ, SWZ, 3); }
230
231TEX{sat}           { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, 3); }
232TXB{sat}           { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, 3); }
233TXP{sat}           { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, 3); }
234
235XPD{sat}           { return_opcode(             1, BIN_OP, XPD, 3); }
236
237vertex                    { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); }
238fragment                  { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); }
239program                   { return PROGRAM; }
240state                     { return STATE; }
241result                    { 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
298texture                   { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); }
2991D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); }
3002D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); }
3013D                        { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); }
302CUBE                      { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); }
303RECT                      { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); }
304SHADOW1D                  { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); }
305SHADOW2D                  { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); }
306SHADOWRECT                { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); }
307ARRAY1D                   { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); }
308ARRAY2D                   { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); }
309ARRAYSHADOW1D             { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); }
310ARRAYSHADOW2D             { 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
477void
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
485void
486_mesa_program_lexer_dtor(void *scanner)
487{
488   yylex_destroy(scanner);
489}
490