| %{ |
| /* |
| * Copyright © 2009 Intel Corporation |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| * DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #ifndef _MSC_VER |
| #include <unistd.h> |
| #endif |
| |
| #include "util/glheader.h" |
| |
| #include "program/prog_instruction.h" |
| #include "program/prog_statevars.h" |
| #include "program/symbol_table.h" |
| #include "program/program_parser.h" |
| #include "program/program_parse.tab.h" |
| #include "util/strtod.h" |
| |
| #define require_ARB_vp (yyextra->mode == ARB_vertex) |
| #define require_ARB_fp (yyextra->mode == ARB_fragment) |
| #define require_shadow (yyextra->option.Shadow) |
| #define require_rect (yyextra->option.TexRect) |
| #define require_texarray (yyextra->option.TexArray) |
| |
| #ifndef HAVE_UNISTD_H |
| #define YY_NO_UNISTD_H |
| #endif |
| |
| #define return_token_or_IDENTIFIER(condition, token) \ |
| do { \ |
| if (condition) { \ |
| return token; \ |
| } else { \ |
| return handle_ident(yyextra, yytext, yylval); \ |
| } \ |
| } while (0) |
| |
| #define return_token_or_DOT(condition, token) \ |
| do { \ |
| if (condition) { \ |
| return token; \ |
| } else { \ |
| yyless(1); \ |
| return DOT; \ |
| } \ |
| } while (0) |
| |
| |
| #define return_opcode(condition, token, opcode, len) \ |
| do { \ |
| if (condition && \ |
| _mesa_parse_instruction_suffix(yyextra, \ |
| yytext + len, \ |
| & yylval->temp_inst)) { \ |
| yylval->temp_inst.Opcode = OPCODE_ ## opcode; \ |
| return token; \ |
| } else { \ |
| return handle_ident(yyextra, yytext, yylval); \ |
| } \ |
| } while (0) |
| |
| #define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \ |
| SWIZZLE_NIL, SWIZZLE_NIL) |
| |
| static unsigned |
| mask_from_char(char c) |
| { |
| switch (c) { |
| case 'x': |
| case 'r': |
| return WRITEMASK_X; |
| case 'y': |
| case 'g': |
| return WRITEMASK_Y; |
| case 'z': |
| case 'b': |
| return WRITEMASK_Z; |
| case 'w': |
| case 'a': |
| return WRITEMASK_W; |
| } |
| |
| return 0; |
| } |
| |
| static unsigned |
| swiz_from_char(char c) |
| { |
| switch (c) { |
| case 'x': |
| case 'r': |
| return SWIZZLE_X; |
| case 'y': |
| case 'g': |
| return SWIZZLE_Y; |
| case 'z': |
| case 'b': |
| return SWIZZLE_Z; |
| case 'w': |
| case 'a': |
| return SWIZZLE_W; |
| } |
| |
| return 0; |
| } |
| |
| static int |
| handle_ident(struct asm_parser_state *state, const char *text, YYSTYPE *lval) |
| { |
| lval->string = strdup(text); |
| |
| return (_mesa_symbol_table_find_symbol(state->st, text) == NULL) |
| ? IDENTIFIER : USED_IDENTIFIER; |
| } |
| |
| #define YY_USER_ACTION \ |
| do { \ |
| yylloc->first_column = yylloc->last_column; \ |
| yylloc->last_column += yyleng; \ |
| if ((yylloc->first_line == 1) \ |
| && (yylloc->first_column == 1)) { \ |
| yylloc->position = 1; \ |
| } else { \ |
| yylloc->position += yylloc->last_column - yylloc->first_column; \ |
| } \ |
| } while(0); |
| |
| #define YY_NO_INPUT |
| |
| /* Yes, this is intentionally doing nothing. We have this line of code |
| here only to avoid the compiler complaining about an unput function |
| that is defined, but never called. */ |
| #define YY_USER_INIT while (0) { unput(0); } |
| |
| #define YY_EXTRA_TYPE struct asm_parser_state * |
| |
| /* Flex defines a couple of functions with no declarations nor the |
| static keyword. Declare them here to avoid a compiler warning. */ |
| int yyget_column (yyscan_t yyscanner); |
| void yyset_column (int column_no , yyscan_t yyscanner); |
| |
| %} |
| |
| num [0-9]+ |
| exp [Ee][-+]?[0-9]+ |
| frac "."[0-9]+ |
| dot "."[ \t]* |
| |
| sat (_SAT)? |
| |
| %option prefix="_mesa_program_lexer_" |
| %option bison-bridge bison-locations reentrant noyywrap |
| %% |
| |
| "!!ARBvp1.0" { return ARBvp_10; } |
| "!!ARBfp1.0" { return ARBfp_10; } |
| ADDRESS { |
| yylval->integer = at_address; |
| return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS); |
| } |
| ALIAS { return ALIAS; } |
| ATTRIB { return ATTRIB; } |
| END { return END; } |
| OPTION { return OPTION; } |
| OUTPUT { return OUTPUT; } |
| PARAM { return PARAM; } |
| TEMP { yylval->integer = at_temp; return TEMP; } |
| |
| ABS{sat} { return_opcode( 1, VECTOR_OP, ABS, 3); } |
| ADD{sat} { return_opcode( 1, BIN_OP, ADD, 3); } |
| ARL { return_opcode(require_ARB_vp, ARL, ARL, 3); } |
| |
| CMP{sat} { return_opcode(require_ARB_fp, TRI_OP, CMP, 3); } |
| COS{sat} { return_opcode(require_ARB_fp, SCALAR_OP, COS, 3); } |
| |
| DP3{sat} { return_opcode( 1, BIN_OP, DP3, 3); } |
| DP4{sat} { return_opcode( 1, BIN_OP, DP4, 3); } |
| DPH{sat} { return_opcode( 1, BIN_OP, DPH, 3); } |
| DST{sat} { return_opcode( 1, BIN_OP, DST, 3); } |
| |
| EX2{sat} { return_opcode( 1, SCALAR_OP, EX2, 3); } |
| EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, 3); } |
| |
| FLR{sat} { return_opcode( 1, VECTOR_OP, FLR, 3); } |
| FRC{sat} { return_opcode( 1, VECTOR_OP, FRC, 3); } |
| |
| KIL { return_opcode(require_ARB_fp, KIL, KIL, 3); } |
| |
| LIT{sat} { return_opcode( 1, VECTOR_OP, LIT, 3); } |
| LG2{sat} { return_opcode( 1, SCALAR_OP, LG2, 3); } |
| LOG { return_opcode(require_ARB_vp, SCALAR_OP, LOG, 3); } |
| LRP{sat} { return_opcode(require_ARB_fp, TRI_OP, LRP, 3); } |
| |
| MAD{sat} { return_opcode( 1, TRI_OP, MAD, 3); } |
| MAX{sat} { return_opcode( 1, BIN_OP, MAX, 3); } |
| MIN{sat} { return_opcode( 1, BIN_OP, MIN, 3); } |
| MOV{sat} { return_opcode( 1, VECTOR_OP, MOV, 3); } |
| MUL{sat} { return_opcode( 1, BIN_OP, MUL, 3); } |
| |
| POW{sat} { return_opcode( 1, BINSC_OP, POW, 3); } |
| |
| RCP{sat} { return_opcode( 1, SCALAR_OP, RCP, 3); } |
| RSQ{sat} { return_opcode( 1, SCALAR_OP, RSQ, 3); } |
| |
| SCS{sat} { return_opcode(require_ARB_fp, SCALAR_OP, SCS, 3); } |
| SGE{sat} { return_opcode( 1, BIN_OP, SGE, 3); } |
| SIN{sat} { return_opcode(require_ARB_fp, SCALAR_OP, SIN, 3); } |
| SLT{sat} { return_opcode( 1, BIN_OP, SLT, 3); } |
| SUB{sat} { return_opcode( 1, BIN_OP, SUB, 3); } |
| SWZ{sat} { return_opcode( 1, SWZ, SWZ, 3); } |
| |
| TEX{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, 3); } |
| TXB{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, 3); } |
| TXP{sat} { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, 3); } |
| |
| XPD{sat} { return_opcode( 1, BIN_OP, XPD, 3); } |
| |
| vertex { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); } |
| fragment { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); } |
| program { return PROGRAM; } |
| state { return STATE; } |
| result { return RESULT; } |
| |
| {dot}ambient { return AMBIENT; } |
| {dot}attenuation { return ATTENUATION; } |
| {dot}back { return BACK; } |
| {dot}clip { return_token_or_DOT(require_ARB_vp, CLIP); } |
| {dot}color { return COLOR; } |
| {dot}depth { return_token_or_DOT(require_ARB_fp, DEPTH); } |
| {dot}diffuse { return DIFFUSE; } |
| {dot}direction { return DIRECTION; } |
| {dot}emission { return EMISSION; } |
| {dot}env { return ENV; } |
| {dot}eye { return EYE; } |
| {dot}fogcoord { return FOGCOORD; } |
| {dot}fog { return FOG; } |
| {dot}front { return FRONT; } |
| {dot}half { return HALF; } |
| {dot}inverse { return INVERSE; } |
| {dot}invtrans { return INVTRANS; } |
| {dot}light { return LIGHT; } |
| {dot}lightmodel { return LIGHTMODEL; } |
| {dot}lightprod { return LIGHTPROD; } |
| {dot}local { return LOCAL; } |
| {dot}material { return MATERIAL; } |
| {dot}program { return MAT_PROGRAM; } |
| {dot}matrix { return MATRIX; } |
| {dot}matrixindex { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); } |
| {dot}modelview { return MODELVIEW; } |
| {dot}mvp { return MVP; } |
| {dot}normal { return_token_or_DOT(require_ARB_vp, NORMAL); } |
| {dot}object { return OBJECT; } |
| {dot}palette { return PALETTE; } |
| {dot}params { return PARAMS; } |
| {dot}plane { return PLANE; } |
| {dot}point { return_token_or_DOT(require_ARB_vp, POINT_TOK); } |
| {dot}pointsize { return_token_or_DOT(require_ARB_vp, POINTSIZE); } |
| {dot}position { return POSITION; } |
| {dot}primary { return PRIMARY; } |
| {dot}projection { return PROJECTION; } |
| {dot}range { return_token_or_DOT(require_ARB_fp, RANGE); } |
| {dot}row { return ROW; } |
| {dot}scenecolor { return SCENECOLOR; } |
| {dot}secondary { return SECONDARY; } |
| {dot}shininess { return SHININESS; } |
| {dot}size { return_token_or_DOT(require_ARB_vp, SIZE_TOK); } |
| {dot}specular { return SPECULAR; } |
| {dot}spot { return SPOT; } |
| {dot}texcoord { return TEXCOORD; } |
| {dot}texenv { return_token_or_DOT(require_ARB_fp, TEXENV); } |
| {dot}texgen { return_token_or_DOT(require_ARB_vp, TEXGEN); } |
| {dot}q { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); } |
| {dot}s { return_token_or_DOT(require_ARB_vp, TEXGEN_S); } |
| {dot}t { return_token_or_DOT(require_ARB_vp, TEXGEN_T); } |
| {dot}texture { return TEXTURE; } |
| {dot}transpose { return TRANSPOSE; } |
| {dot}attrib { return_token_or_DOT(require_ARB_vp, VTXATTRIB); } |
| |
| texture { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); } |
| 1D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); } |
| 2D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); } |
| 3D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); } |
| CUBE { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); } |
| RECT { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); } |
| SHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); } |
| SHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); } |
| SHADOWRECT { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); } |
| ARRAY1D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); } |
| ARRAY2D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); } |
| ARRAYSHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); } |
| ARRAYSHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); } |
| |
| [_a-zA-Z$][_a-zA-Z0-9$]* { return handle_ident(yyextra, yytext, yylval); } |
| |
| ".." { return DOT_DOT; } |
| |
| {num} { |
| yylval->integer = strtol(yytext, NULL, 10); |
| return INTEGER; |
| } |
| {num}?{frac}{exp}? { |
| yylval->real = _mesa_strtof(yytext, NULL); |
| return REAL; |
| } |
| {num}"."/[^.] { |
| yylval->real = _mesa_strtof(yytext, NULL); |
| return REAL; |
| } |
| {num}{exp} { |
| yylval->real = _mesa_strtof(yytext, NULL); |
| return REAL; |
| } |
| {num}"."{exp} { |
| yylval->real = _mesa_strtof(yytext, NULL); |
| return REAL; |
| } |
| |
| ".xyzw" { |
| yylval->swiz_mask.swizzle = SWIZZLE_NOOP; |
| yylval->swiz_mask.mask = WRITEMASK_XYZW; |
| return MASK4; |
| } |
| |
| ".xy"[zw] { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_XY |
| | mask_from_char(yytext[3]); |
| return MASK3; |
| } |
| ".xzw" { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_XZW; |
| return MASK3; |
| } |
| ".yzw" { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_YZW; |
| return MASK3; |
| } |
| |
| ".x"[yzw] { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_X |
| | mask_from_char(yytext[2]); |
| return MASK2; |
| } |
| ".y"[zw] { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_Y |
| | mask_from_char(yytext[2]); |
| return MASK2; |
| } |
| ".zw" { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_ZW; |
| return MASK2; |
| } |
| |
| "."[xyzw] { |
| const unsigned s = swiz_from_char(yytext[1]); |
| yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s); |
| yylval->swiz_mask.mask = mask_from_char(yytext[1]); |
| return MASK1; |
| } |
| |
| "."[xyzw]{4} { |
| yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]), |
| swiz_from_char(yytext[2]), |
| swiz_from_char(yytext[3]), |
| swiz_from_char(yytext[4])); |
| yylval->swiz_mask.mask = 0; |
| return SWIZZLE; |
| } |
| |
| ".rgba" { |
| yylval->swiz_mask.swizzle = SWIZZLE_NOOP; |
| yylval->swiz_mask.mask = WRITEMASK_XYZW; |
| return_token_or_DOT(require_ARB_fp, MASK4); |
| } |
| |
| ".rg"[ba] { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_XY |
| | mask_from_char(yytext[3]); |
| return_token_or_DOT(require_ARB_fp, MASK3); |
| } |
| ".rba" { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_XZW; |
| return_token_or_DOT(require_ARB_fp, MASK3); |
| } |
| ".gba" { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_YZW; |
| return_token_or_DOT(require_ARB_fp, MASK3); |
| } |
| |
| ".r"[gba] { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_X |
| | mask_from_char(yytext[2]); |
| return_token_or_DOT(require_ARB_fp, MASK2); |
| } |
| ".g"[ba] { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_Y |
| | mask_from_char(yytext[2]); |
| return_token_or_DOT(require_ARB_fp, MASK2); |
| } |
| ".ba" { |
| yylval->swiz_mask.swizzle = SWIZZLE_INVAL; |
| yylval->swiz_mask.mask = WRITEMASK_ZW; |
| return_token_or_DOT(require_ARB_fp, MASK2); |
| } |
| |
| "."[gba] { |
| const unsigned s = swiz_from_char(yytext[1]); |
| yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s); |
| yylval->swiz_mask.mask = mask_from_char(yytext[1]); |
| return_token_or_DOT(require_ARB_fp, MASK1); |
| } |
| |
| |
| ".r" { |
| if (require_ARB_vp) { |
| return TEXGEN_R; |
| } else { |
| yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, |
| SWIZZLE_X, SWIZZLE_X); |
| yylval->swiz_mask.mask = WRITEMASK_X; |
| return MASK1; |
| } |
| } |
| |
| "."[rgba]{4} { |
| yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]), |
| swiz_from_char(yytext[2]), |
| swiz_from_char(yytext[3]), |
| swiz_from_char(yytext[4])); |
| yylval->swiz_mask.mask = 0; |
| return_token_or_DOT(require_ARB_fp, SWIZZLE); |
| } |
| |
| "." { return DOT; } |
| |
| \n { |
| yylloc->first_line++; |
| yylloc->first_column = 1; |
| yylloc->last_line++; |
| yylloc->last_column = 1; |
| yylloc->position++; |
| } |
| [ \t\r]+ /* eat whitespace */ ; |
| #.*$ /* eat comments */ ; |
| . { return yytext[0]; } |
| %% |
| |
| void |
| _mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state, |
| const char *string, size_t len) |
| { |
| yylex_init_extra(state, scanner); |
| yy_scan_bytes(string, len, *scanner); |
| } |
| |
| void |
| _mesa_program_lexer_dtor(void *scanner) |
| { |
| yylex_destroy(scanner); |
| } |