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