Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  6.5
  4.  *
  5.  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. /**
  26.  * \file nvfragparse.c
  27.  * NVIDIA fragment program parser.
  28.  * \author Brian Paul
  29.  */
  30.  
  31. /*
  32.  * Regarding GL_NV_fragment_program:
  33.  *
  34.  * Portions of this software may use or implement intellectual
  35.  * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
  36.  * any and all warranties with respect to such intellectual property,
  37.  * including any use thereof or modifications thereto.
  38.  */
  39.  
  40. #include "main/glheader.h"
  41. #include "main/context.h"
  42. #include "main/imports.h"
  43. #include "main/macros.h"
  44. #include "program.h"
  45. #include "prog_parameter.h"
  46. #include "prog_print.h"
  47. #include "prog_instruction.h"
  48. #include "nvfragparse.h"
  49.  
  50.  
  51. #define INPUT_1V     1
  52. #define INPUT_2V     2
  53. #define INPUT_3V     3
  54. #define INPUT_1S     4
  55. #define INPUT_2S     5
  56. #define INPUT_CC     6
  57. #define INPUT_1V_T   7  /* one source vector, plus textureId */
  58. #define INPUT_3V_T   8  /* one source vector, plus textureId */
  59. #define INPUT_NONE   9
  60. #define INPUT_1V_S  10  /* a string and a vector register */
  61. #define OUTPUT_V    20
  62. #define OUTPUT_S    21
  63. #define OUTPUT_NONE 22
  64.  
  65. /* IRIX defines some of these */
  66. #undef _R
  67. #undef _H
  68. #undef _X
  69. #undef _C
  70. #undef _S
  71.  
  72. /* Optional suffixes */
  73. #define _R  FLOAT32  /* float */
  74. #define _H  FLOAT16  /* half-float */
  75. #define _X  FIXED12  /* fixed */
  76. #define _C  0x08     /* set cond codes */
  77. #define _S  0x10     /* saturate, clamp result to [0,1] */
  78.  
  79. struct instruction_pattern {
  80.    const char *name;
  81.    enum prog_opcode opcode;
  82.    GLuint inputs;
  83.    GLuint outputs;
  84.    GLuint suffixes;
  85. };
  86.  
  87. static const struct instruction_pattern Instructions[] = {
  88.    { "ADD", OPCODE_ADD, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  89.    { "COS", OPCODE_COS, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
  90.    { "DDX", OPCODE_DDX, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },
  91.    { "DDY", OPCODE_DDY, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },
  92.    { "DP3", OPCODE_DP3, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },
  93.    { "DP4", OPCODE_DP4, INPUT_2V, OUTPUT_S, _R | _H | _X | _C | _S },
  94.    { "DST", OPCODE_DP4, INPUT_2V, OUTPUT_V, _R | _H |      _C | _S },
  95.    { "EX2", OPCODE_DP4, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
  96.    { "FLR", OPCODE_FLR, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
  97.    { "FRC", OPCODE_FRC, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
  98.    { "KIL", OPCODE_KIL_NV, INPUT_CC, OUTPUT_NONE, 0                },
  99.    { "LG2", OPCODE_LG2, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
  100.    { "LIT", OPCODE_LIT, INPUT_1V, OUTPUT_V, _R | _H |      _C | _S },
  101.    { "LRP", OPCODE_LRP, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
  102.    { "MAD", OPCODE_MAD, INPUT_3V, OUTPUT_V, _R | _H | _X | _C | _S },
  103.    { "MAX", OPCODE_MAX, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  104.    { "MIN", OPCODE_MIN, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  105.    { "MOV", OPCODE_MOV, INPUT_1V, OUTPUT_V, _R | _H | _X | _C | _S },
  106.    { "MUL", OPCODE_MUL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  107.    { "PK2H",  OPCODE_PK2H,  INPUT_1V, OUTPUT_S, 0                  },
  108.    { "PK2US", OPCODE_PK2US, INPUT_1V, OUTPUT_S, 0                  },
  109.    { "PK4B",  OPCODE_PK4B,  INPUT_1V, OUTPUT_S, 0                  },
  110.    { "PK4UB", OPCODE_PK4UB, INPUT_1V, OUTPUT_S, 0                  },
  111.    { "POW", OPCODE_POW, INPUT_2S, OUTPUT_S, _R | _H |      _C | _S },
  112.    { "RCP", OPCODE_RCP, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
  113.    { "RFL", OPCODE_RFL, INPUT_2V, OUTPUT_V, _R | _H |      _C | _S },
  114.    { "RSQ", OPCODE_RSQ, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
  115.    { "SEQ", OPCODE_SEQ, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  116.    { "SFL", OPCODE_SFL, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  117.    { "SGE", OPCODE_SGE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  118.    { "SGT", OPCODE_SGT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  119.    { "SIN", OPCODE_SIN, INPUT_1S, OUTPUT_S, _R | _H |      _C | _S },
  120.    { "SLE", OPCODE_SLE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  121.    { "SLT", OPCODE_SLT, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  122.    { "SNE", OPCODE_SNE, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  123.    { "STR", OPCODE_STR, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  124.    { "SUB", OPCODE_SUB, INPUT_2V, OUTPUT_V, _R | _H | _X | _C | _S },
  125.    { "TEX", OPCODE_TEX, INPUT_1V_T, OUTPUT_V,              _C | _S },
  126.    { "TXD", OPCODE_TXD, INPUT_3V_T, OUTPUT_V,              _C | _S },
  127.    { "TXP", OPCODE_TXP_NV, INPUT_1V_T, OUTPUT_V,           _C | _S },
  128.    { "UP2H",  OPCODE_UP2H,  INPUT_1S, OUTPUT_V,            _C | _S },
  129.    { "UP2US", OPCODE_UP2US, INPUT_1S, OUTPUT_V,            _C | _S },
  130.    { "UP4B",  OPCODE_UP4B,  INPUT_1S, OUTPUT_V,            _C | _S },
  131.    { "UP4UB", OPCODE_UP4UB, INPUT_1S, OUTPUT_V,            _C | _S },
  132.    { "X2D", OPCODE_X2D, INPUT_3V, OUTPUT_V, _R | _H |      _C | _S },
  133.    { "PRINT", OPCODE_PRINT, INPUT_1V_S, OUTPUT_NONE, 0               },
  134.    { NULL, (enum prog_opcode) -1, 0, 0, 0 }
  135. };
  136.  
  137.  
  138. /*
  139.  * Information needed or computed during parsing.
  140.  * Remember, we can't modify the target program object until we've
  141.  * _successfully_ parsed the program text.
  142.  */
  143. struct parse_state {
  144.    struct gl_context *ctx;
  145.    const GLubyte *start;              /* start of program string */
  146.    const GLubyte *pos;                /* current position */
  147.    const GLubyte *curLine;
  148.    struct gl_fragment_program *program;  /* current program */
  149.  
  150.    struct gl_program_parameter_list *parameters;
  151.  
  152.    GLuint numInst;                    /* number of instructions parsed */
  153.    GLuint inputsRead;                 /* bitmask of input registers used */
  154.    GLuint outputsWritten;             /* bitmask of 1 << FRAG_OUTPUT_* bits */
  155.    GLuint texturesUsed[MAX_TEXTURE_IMAGE_UNITS];
  156. };
  157.  
  158.  
  159.  
  160. /*
  161.  * Called whenever we find an error during parsing.
  162.  */
  163. static void
  164. record_error(struct parse_state *parseState, const char *msg, int lineNo)
  165. {
  166. #ifdef DEBUG
  167.    GLint line, column;
  168.    const GLubyte *lineStr;
  169.    lineStr = _mesa_find_line_column(parseState->start,
  170.                                     parseState->pos, &line, &column);
  171.    _mesa_debug(parseState->ctx,
  172.                "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
  173.                lineNo, line, column, (char *) lineStr, msg);
  174.    free((void *) lineStr);
  175. #else
  176.    (void) lineNo;
  177. #endif
  178.  
  179.    /* Check that no error was already recorded.  Only record the first one. */
  180.    if (parseState->ctx->Program.ErrorString[0] == 0) {
  181.       _mesa_set_program_error(parseState->ctx,
  182.                               parseState->pos - parseState->start,
  183.                               msg);
  184.    }
  185. }
  186.  
  187.  
  188. #define RETURN_ERROR                                                    \
  189. do {                                                                    \
  190.    record_error(parseState, "Unexpected end of input.", __LINE__);      \
  191.    return GL_FALSE;                                                     \
  192. } while(0)
  193.  
  194. #define RETURN_ERROR1(msg)                                              \
  195. do {                                                                    \
  196.    record_error(parseState, msg, __LINE__);                             \
  197.    return GL_FALSE;                                                     \
  198. } while(0)
  199.  
  200. #define RETURN_ERROR2(msg1, msg2)                                       \
  201. do {                                                                    \
  202.    char err[1000];                                                      \
  203.    sprintf(err, "%s %s", msg1, msg2);                           \
  204.    record_error(parseState, err, __LINE__);                             \
  205.    return GL_FALSE;                                                     \
  206. } while(0)
  207.  
  208.  
  209.  
  210.  
  211. /*
  212.  * Search a list of instruction structures for a match.
  213.  */
  214. static struct instruction_pattern
  215. MatchInstruction(const GLubyte *token)
  216. {
  217.    const struct instruction_pattern *inst;
  218.    struct instruction_pattern result;
  219.  
  220.    result.name = NULL;
  221.    result.opcode = MAX_OPCODE; /* i.e. invalid instruction */
  222.    result.inputs = 0;
  223.    result.outputs = 0;
  224.    result.suffixes = 0;
  225.  
  226.    for (inst = Instructions; inst->name; inst++) {
  227.       if (strncmp((const char *) token, inst->name, 3) == 0) {
  228.          /* matched! */
  229.          int i = 3;
  230.          result = *inst;
  231.          result.suffixes = 0;
  232.          /* look at suffix */
  233.          if (token[i] == 'R') {
  234.             result.suffixes |= _R;
  235.             i++;
  236.          }
  237.          else if (token[i] == 'H') {
  238.             result.suffixes |= _H;
  239.             i++;
  240.          }
  241.          else if (token[i] == 'X') {
  242.             result.suffixes |= _X;
  243.             i++;
  244.          }
  245.          if (token[i] == 'C') {
  246.             result.suffixes |= _C;
  247.             i++;
  248.          }
  249.          if (token[i] == '_' && token[i+1] == 'S' &&
  250.              token[i+2] == 'A' && token[i+3] == 'T') {
  251.             result.suffixes |= _S;
  252.          }
  253.          return result;
  254.       }
  255.    }
  256.  
  257.    return result;
  258. }
  259.  
  260.  
  261.  
  262.  
  263. /**********************************************************************/
  264.  
  265.  
  266. static GLboolean IsLetter(GLubyte b)
  267. {
  268.    return (b >= 'a' && b <= 'z') ||
  269.           (b >= 'A' && b <= 'Z') ||
  270.           (b == '_') ||
  271.           (b == '$');
  272. }
  273.  
  274.  
  275. static GLboolean IsDigit(GLubyte b)
  276. {
  277.    return b >= '0' && b <= '9';
  278. }
  279.  
  280.  
  281. static GLboolean IsWhitespace(GLubyte b)
  282. {
  283.    return b == ' ' || b == '\t' || b == '\n' || b == '\r';
  284. }
  285.  
  286.  
  287. /**
  288.  * Starting at 'str' find the next token.  A token can be an integer,
  289.  * an identifier or punctuation symbol.
  290.  * \return <= 0 we found an error, else, return number of characters parsed.
  291.  */
  292. static GLint
  293. GetToken(struct parse_state *parseState, GLubyte *token)
  294. {
  295.    const GLubyte *str = parseState->pos;
  296.    GLint i = 0, j = 0;
  297.  
  298.    token[0] = 0;
  299.  
  300.    /* skip whitespace and comments */
  301.    while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {
  302.       if (str[i] == '#') {
  303.          /* skip comment */
  304.          while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
  305.             i++;
  306.          }
  307.          if (str[i] == '\n' || str[i] == '\r')
  308.             parseState->curLine = str + i + 1;
  309.       }
  310.       else {
  311.          /* skip whitespace */
  312.          if (str[i] == '\n' || str[i] == '\r')
  313.             parseState->curLine = str + i + 1;
  314.          i++;
  315.       }
  316.    }
  317.  
  318.    if (str[i] == 0)
  319.       return -i;
  320.  
  321.    /* try matching an integer */
  322.    while (str[i] && IsDigit(str[i])) {
  323.       token[j++] = str[i++];
  324.    }
  325.    if (j > 0 || !str[i]) {
  326.       token[j] = 0;
  327.       return i;
  328.    }
  329.  
  330.    /* try matching an identifier */
  331.    if (IsLetter(str[i])) {
  332.       while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {
  333.          token[j++] = str[i++];
  334.       }
  335.       token[j] = 0;
  336.       return i;
  337.    }
  338.  
  339.    /* punctuation character */
  340.    if (str[i]) {
  341.       token[0] = str[i++];
  342.       token[1] = 0;
  343.       return i;
  344.    }
  345.  
  346.    /* end of input */
  347.    token[0] = 0;
  348.    return i;
  349. }
  350.  
  351.  
  352. /**
  353.  * Get next token from input stream and increment stream pointer past token.
  354.  */
  355. static GLboolean
  356. Parse_Token(struct parse_state *parseState, GLubyte *token)
  357. {
  358.    GLint i;
  359.    i = GetToken(parseState, token);
  360.    if (i <= 0) {
  361.       parseState->pos += (-i);
  362.       return GL_FALSE;
  363.    }
  364.    parseState->pos += i;
  365.    return GL_TRUE;
  366. }
  367.  
  368.  
  369. /**
  370.  * Get next token from input stream but don't increment stream pointer.
  371.  */
  372. static GLboolean
  373. Peek_Token(struct parse_state *parseState, GLubyte *token)
  374. {
  375.    GLint i, len;
  376.    i = GetToken(parseState, token);
  377.    if (i <= 0) {
  378.       parseState->pos += (-i);
  379.       return GL_FALSE;
  380.    }
  381.    len = (GLint) strlen((const char *) token);
  382.    parseState->pos += (i - len);
  383.    return GL_TRUE;
  384. }
  385.  
  386.  
  387. /**********************************************************************/
  388.  
  389. static const char *InputRegisters[MAX_NV_FRAGMENT_PROGRAM_INPUTS + 1] = {
  390.    "WPOS", "COL0", "COL1", "FOGC",
  391.    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
  392. };
  393.  
  394.  
  395.  
  396. /**********************************************************************/
  397.  
  398. /**
  399.  * Try to match 'pattern' as the next token after any whitespace/comments.
  400.  */
  401. static GLboolean
  402. Parse_String(struct parse_state *parseState, const char *pattern)
  403. {
  404.    const GLubyte *m;
  405.    GLint i;
  406.  
  407.    /* skip whitespace and comments */
  408.    while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') {
  409.       if (*parseState->pos == '#') {
  410.          while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {
  411.             parseState->pos += 1;
  412.          }
  413.          if (*parseState->pos == '\n' || *parseState->pos == '\r')
  414.             parseState->curLine = parseState->pos + 1;
  415.       }
  416.       else {
  417.          /* skip whitespace */
  418.          if (*parseState->pos == '\n' || *parseState->pos == '\r')
  419.             parseState->curLine = parseState->pos + 1;
  420.          parseState->pos += 1;
  421.       }
  422.    }
  423.  
  424.    /* Try to match the pattern */
  425.    m = parseState->pos;
  426.    for (i = 0; pattern[i]; i++) {
  427.       if (*m != (GLubyte) pattern[i])
  428.          return GL_FALSE;
  429.       m += 1;
  430.    }
  431.    parseState->pos = m;
  432.  
  433.    return GL_TRUE; /* success */
  434. }
  435.  
  436.  
  437. static GLboolean
  438. Parse_Identifier(struct parse_state *parseState, GLubyte *ident)
  439. {
  440.    if (!Parse_Token(parseState, ident))
  441.       RETURN_ERROR;
  442.    if (IsLetter(ident[0]))
  443.       return GL_TRUE;
  444.    else
  445.       RETURN_ERROR1("Expected an identfier");
  446. }
  447.  
  448.  
  449. /**
  450.  * Parse a floating point constant, or a defined symbol name.
  451.  * [+/-]N[.N[eN]]
  452.  * Output:  number[0 .. 3] will get the value.
  453.  */
  454. static GLboolean
  455. Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
  456. {
  457.    char *end = NULL;
  458.  
  459.    *number = (GLfloat) _mesa_strtof((const char *) parseState->pos, &end);
  460.  
  461.    if (end && end > (char *) parseState->pos) {
  462.       /* got a number */
  463.       parseState->pos = (GLubyte *) end;
  464.       number[1] = *number;
  465.       number[2] = *number;
  466.       number[3] = *number;
  467.       return GL_TRUE;
  468.    }
  469.    else {
  470.       /* should be an identifier */
  471.       GLubyte ident[100];
  472.       const GLfloat *constant;
  473.       if (!Parse_Identifier(parseState, ident))
  474.          RETURN_ERROR1("Expected an identifier");
  475.       constant = _mesa_lookup_parameter_value(parseState->parameters,
  476.                                               -1, (const char *) ident);
  477.       /* XXX Check that it's a constant and not a parameter */
  478.       if (!constant) {
  479.          RETURN_ERROR1("Undefined symbol");
  480.       }
  481.       else {
  482.          COPY_4V(number, constant);
  483.          return GL_TRUE;
  484.       }
  485.    }
  486. }
  487.  
  488.  
  489.  
  490. /**
  491.  * Parse a vector constant, one of:
  492.  *   { float }
  493.  *   { float, float }
  494.  *   { float, float, float }
  495.  *   { float, float, float, float }
  496.  */
  497. static GLboolean
  498. Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec)
  499. {
  500.    /* "{" was already consumed */
  501.  
  502.    ASSIGN_4V(vec, 0.0, 0.0, 0.0, 1.0);
  503.  
  504.    if (!Parse_ScalarConstant(parseState, vec+0))  /* X */
  505.       return GL_FALSE;
  506.  
  507.    if (Parse_String(parseState, "}")) {
  508.       return GL_TRUE;
  509.    }
  510.  
  511.    if (!Parse_String(parseState, ","))
  512.       RETURN_ERROR1("Expected comma in vector constant");
  513.  
  514.    if (!Parse_ScalarConstant(parseState, vec+1))  /* Y */
  515.       return GL_FALSE;
  516.  
  517.    if (Parse_String(parseState, "}")) {
  518.       return GL_TRUE;
  519.    }
  520.  
  521.    if (!Parse_String(parseState, ","))
  522.       RETURN_ERROR1("Expected comma in vector constant");
  523.  
  524.    if (!Parse_ScalarConstant(parseState, vec+2))  /* Z */
  525.       return GL_FALSE;
  526.  
  527.    if (Parse_String(parseState, "}")) {
  528.       return GL_TRUE;
  529.    }
  530.  
  531.    if (!Parse_String(parseState, ","))
  532.       RETURN_ERROR1("Expected comma in vector constant");
  533.  
  534.    if (!Parse_ScalarConstant(parseState, vec+3))  /* W */
  535.       return GL_FALSE;
  536.  
  537.    if (!Parse_String(parseState, "}"))
  538.       RETURN_ERROR1("Expected closing brace in vector constant");
  539.  
  540.    return GL_TRUE;
  541. }
  542.  
  543.  
  544. /**
  545.  * Parse <number>, <varname> or {a, b, c, d}.
  546.  * Return number of values in the vector or scalar, or zero if parse error.
  547.  */
  548. static GLuint
  549. Parse_VectorOrScalarConstant(struct parse_state *parseState, GLfloat *vec)
  550. {
  551.    if (Parse_String(parseState, "{")) {
  552.       return Parse_VectorConstant(parseState, vec);
  553.    }
  554.    else {
  555.       GLboolean b = Parse_ScalarConstant(parseState, vec);
  556.       if (b) {
  557.          vec[1] = vec[2] = vec[3] = vec[0];
  558.       }
  559.       return b;
  560.    }
  561. }
  562.  
  563.  
  564. /**
  565.  * Parse a texture image source:
  566.  *    [TEX0 | TEX1 | .. | TEX15] , [1D | 2D | 3D | CUBE | RECT]
  567.  */
  568. static GLboolean
  569. Parse_TextureImageId(struct parse_state *parseState,
  570.                      GLubyte *texUnit, GLubyte *texTargetBit)
  571. {
  572.    GLubyte imageSrc[100];
  573.    GLint unit;
  574.  
  575.    if (!Parse_Token(parseState, imageSrc))
  576.       RETURN_ERROR;
  577.    
  578.    if (imageSrc[0] != 'T' ||
  579.        imageSrc[1] != 'E' ||
  580.        imageSrc[2] != 'X') {
  581.       RETURN_ERROR1("Expected TEX# source");
  582.    }
  583.    unit = atoi((const char *) imageSrc + 3);
  584.    if ((unit < 0 || unit > MAX_TEXTURE_IMAGE_UNITS) ||
  585.        (unit == 0 && (imageSrc[3] != '0' || imageSrc[4] != 0))) {
  586.       RETURN_ERROR1("Invalied TEX# source index");
  587.    }
  588.    *texUnit = unit;
  589.  
  590.    if (!Parse_String(parseState, ","))
  591.       RETURN_ERROR1("Expected ,");
  592.  
  593.    if (Parse_String(parseState, "1D")) {
  594.       *texTargetBit = TEXTURE_1D_BIT;
  595.    }
  596.    else if (Parse_String(parseState, "2D")) {
  597.       *texTargetBit = TEXTURE_2D_BIT;
  598.    }
  599.    else if (Parse_String(parseState, "3D")) {
  600.       *texTargetBit = TEXTURE_3D_BIT;
  601.    }
  602.    else if (Parse_String(parseState, "CUBE")) {
  603.       *texTargetBit = TEXTURE_CUBE_BIT;
  604.    }
  605.    else if (Parse_String(parseState, "RECT")) {
  606.       *texTargetBit = TEXTURE_RECT_BIT;
  607.    }
  608.    else {
  609.       RETURN_ERROR1("Invalid texture target token");
  610.    }
  611.  
  612.    /* update record of referenced texture units */
  613.    parseState->texturesUsed[*texUnit] |= *texTargetBit;
  614.    if (_mesa_bitcount(parseState->texturesUsed[*texUnit]) > 1) {
  615.       RETURN_ERROR1("Only one texture target can be used per texture unit.");
  616.    }
  617.  
  618.    return GL_TRUE;
  619. }
  620.  
  621.  
  622. /**
  623.  * Parse a scalar suffix like .x, .y, .z or .w or parse a swizzle suffix
  624.  * like .wxyz, .xxyy, etc and return the swizzle indexes.
  625.  */
  626. static GLboolean
  627. Parse_SwizzleSuffix(const GLubyte *token, GLuint swizzle[4])
  628. {
  629.    if (token[1] == 0) {
  630.       /* single letter swizzle (scalar) */
  631.       if (token[0] == 'x')
  632.          ASSIGN_4V(swizzle, 0, 0, 0, 0);
  633.       else if (token[0] == 'y')
  634.          ASSIGN_4V(swizzle, 1, 1, 1, 1);
  635.       else if (token[0] == 'z')
  636.          ASSIGN_4V(swizzle, 2, 2, 2, 2);
  637.       else if (token[0] == 'w')
  638.          ASSIGN_4V(swizzle, 3, 3, 3, 3);
  639.       else
  640.          return GL_FALSE;
  641.    }
  642.    else {
  643.       /* 4-component swizzle (vector) */
  644.       GLint k;
  645.       for (k = 0; k < 4 && token[k]; k++) {
  646.          if (token[k] == 'x')
  647.             swizzle[k] = 0;
  648.          else if (token[k] == 'y')
  649.             swizzle[k] = 1;
  650.          else if (token[k] == 'z')
  651.             swizzle[k] = 2;
  652.          else if (token[k] == 'w')
  653.             swizzle[k] = 3;
  654.          else
  655.             return GL_FALSE;
  656.       }
  657.       if (k != 4)
  658.          return GL_FALSE;
  659.    }
  660.    return GL_TRUE;
  661. }
  662.  
  663.  
  664. static GLboolean
  665. Parse_CondCodeMask(struct parse_state *parseState,
  666.                    struct prog_dst_register *dstReg)
  667. {
  668.    if (Parse_String(parseState, "EQ"))
  669.       dstReg->CondMask = COND_EQ;
  670.    else if (Parse_String(parseState, "GE"))
  671.       dstReg->CondMask = COND_GE;
  672.    else if (Parse_String(parseState, "GT"))
  673.       dstReg->CondMask = COND_GT;
  674.    else if (Parse_String(parseState, "LE"))
  675.       dstReg->CondMask = COND_LE;
  676.    else if (Parse_String(parseState, "LT"))
  677.       dstReg->CondMask = COND_LT;
  678.    else if (Parse_String(parseState, "NE"))
  679.       dstReg->CondMask = COND_NE;
  680.    else if (Parse_String(parseState, "TR"))
  681.       dstReg->CondMask = COND_TR;
  682.    else if (Parse_String(parseState, "FL"))
  683.       dstReg->CondMask = COND_FL;
  684.    else
  685.       RETURN_ERROR1("Invalid condition code mask");
  686.  
  687.    /* look for optional .xyzw swizzle */
  688.    if (Parse_String(parseState, ".")) {
  689.       GLubyte token[100];
  690.       GLuint swz[4];
  691.  
  692.       if (!Parse_Token(parseState, token))  /* get xyzw suffix */
  693.          RETURN_ERROR;
  694.  
  695.       if (!Parse_SwizzleSuffix(token, swz))
  696.          RETURN_ERROR1("Invalid swizzle suffix");
  697.  
  698.       dstReg->CondSwizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
  699.    }
  700.  
  701.    return GL_TRUE;
  702. }
  703.  
  704.  
  705. /**
  706.  * Parse a temporary register: Rnn or Hnn
  707.  */
  708. static GLboolean
  709. Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
  710. {
  711.    GLubyte token[100];
  712.  
  713.    /* Should be 'R##' or 'H##' */
  714.    if (!Parse_Token(parseState, token))
  715.       RETURN_ERROR;
  716.    if (token[0] != 'R' && token[0] != 'H')
  717.       RETURN_ERROR1("Expected R## or H##");
  718.  
  719.    if (IsDigit(token[1])) {
  720.       GLint reg = atoi((const char *) (token + 1));
  721.       if (token[0] == 'H')
  722.          reg += 32;
  723.       if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS)
  724.          RETURN_ERROR1("Invalid temporary register name");
  725.       *tempRegNum = reg;
  726.    }
  727.    else {
  728.       RETURN_ERROR1("Invalid temporary register name");
  729.    }
  730.  
  731.    return GL_TRUE;
  732. }
  733.  
  734.  
  735. /**
  736.  * Parse a write-only dummy register: RC or HC.
  737.  */
  738. static GLboolean
  739. Parse_DummyReg(struct parse_state *parseState, GLint *regNum)
  740. {
  741.    if (Parse_String(parseState, "RC")) {
  742.        *regNum = 0;
  743.    }
  744.    else if (Parse_String(parseState, "HC")) {
  745.        *regNum = 1;
  746.    }
  747.    else {
  748.       RETURN_ERROR1("Invalid write-only register name");
  749.    }
  750.  
  751.    return GL_TRUE;
  752. }
  753.  
  754.  
  755. /**
  756.  * Parse a program local parameter register "p[##]"
  757.  */
  758. static GLboolean
  759. Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum)
  760. {
  761.    GLubyte token[100];
  762.  
  763.    if (!Parse_String(parseState, "p["))
  764.       RETURN_ERROR1("Expected p[");
  765.  
  766.    if (!Parse_Token(parseState, token))
  767.       RETURN_ERROR;
  768.  
  769.    if (IsDigit(token[0])) {
  770.       /* a numbered program parameter register */
  771.       GLint reg = atoi((const char *) token);
  772.       if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS)
  773.          RETURN_ERROR1("Invalid constant program number");
  774.       *regNum = reg;
  775.    }
  776.    else {
  777.       RETURN_ERROR;
  778.    }
  779.  
  780.    if (!Parse_String(parseState, "]"))
  781.       RETURN_ERROR1("Expected ]");
  782.  
  783.    return GL_TRUE;
  784. }
  785.  
  786.  
  787. /**
  788.  * Parse f[name]  - fragment input register
  789.  */
  790. static GLboolean
  791. Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum)
  792. {
  793.    GLubyte token[100];
  794.    GLint j;
  795.  
  796.    /* Match 'f[' */
  797.    if (!Parse_String(parseState, "f["))
  798.       RETURN_ERROR1("Expected f[");
  799.  
  800.    /* get <name> and look for match */
  801.    if (!Parse_Token(parseState, token)) {
  802.       RETURN_ERROR;
  803.    }
  804.    for (j = 0; InputRegisters[j]; j++) {
  805.       if (strcmp((const char *) token, InputRegisters[j]) == 0) {
  806.          *tempRegNum = j;
  807.          parseState->inputsRead |= (1 << j);
  808.          break;
  809.       }
  810.    }
  811.    if (!InputRegisters[j]) {
  812.       /* unknown input register label */
  813.       RETURN_ERROR2("Invalid register name", token);
  814.    }
  815.  
  816.    /* Match '[' */
  817.    if (!Parse_String(parseState, "]"))
  818.       RETURN_ERROR1("Expected ]");
  819.  
  820.    return GL_TRUE;
  821. }
  822.  
  823.  
  824. static GLboolean
  825. Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
  826. {
  827.    GLubyte token[100];
  828.  
  829.    /* Match "o[" */
  830.    if (!Parse_String(parseState, "o["))
  831.       RETURN_ERROR1("Expected o[");
  832.  
  833.    /* Get output reg name */
  834.    if (!Parse_Token(parseState, token))
  835.       RETURN_ERROR;
  836.  
  837.    /* try to match an output register name */
  838.    if (strcmp((char *) token, "COLR") == 0 ||
  839.        strcmp((char *) token, "COLH") == 0) {
  840.       /* note that we don't distinguish between COLR and COLH */
  841.       *outputRegNum = FRAG_RESULT_COLOR;
  842.       parseState->outputsWritten |= (1 << FRAG_RESULT_COLOR);
  843.    }
  844.    else if (strcmp((char *) token, "DEPR") == 0) {
  845.       *outputRegNum = FRAG_RESULT_DEPTH;
  846.       parseState->outputsWritten |= (1 << FRAG_RESULT_DEPTH);
  847.    }
  848.    else {
  849.       RETURN_ERROR1("Invalid output register name");
  850.    }
  851.  
  852.    /* Match ']' */
  853.    if (!Parse_String(parseState, "]"))
  854.       RETURN_ERROR1("Expected ]");
  855.  
  856.    return GL_TRUE;
  857. }
  858.  
  859.  
  860. static GLboolean
  861. Parse_MaskedDstReg(struct parse_state *parseState,
  862.                    struct prog_dst_register *dstReg)
  863. {
  864.    GLubyte token[100];
  865.    GLint idx;
  866.  
  867.    /* Dst reg can be R<n>, H<n>, o[n], RC or HC */
  868.    if (!Peek_Token(parseState, token))
  869.       RETURN_ERROR;
  870.  
  871.    if (strcmp((const char *) token, "RC") == 0 ||
  872.        strcmp((const char *) token, "HC") == 0) {
  873.       /* a write-only register */
  874.       dstReg->File = PROGRAM_WRITE_ONLY;
  875.       if (!Parse_DummyReg(parseState, &idx))
  876.          RETURN_ERROR;
  877.       dstReg->Index = idx;
  878.    }
  879.    else if (token[0] == 'R' || token[0] == 'H') {
  880.       /* a temporary register */
  881.       dstReg->File = PROGRAM_TEMPORARY;
  882.       if (!Parse_TempReg(parseState, &idx))
  883.          RETURN_ERROR;
  884.       dstReg->Index = idx;
  885.    }
  886.    else if (token[0] == 'o') {
  887.       /* an output register */
  888.       dstReg->File = PROGRAM_OUTPUT;
  889.       if (!Parse_OutputReg(parseState, &idx))
  890.          RETURN_ERROR;
  891.       dstReg->Index = idx;
  892.    }
  893.    else {
  894.       RETURN_ERROR1("Invalid destination register name");
  895.    }
  896.  
  897.    /* Parse optional write mask */
  898.    if (Parse_String(parseState, ".")) {
  899.       /* got a mask */
  900.       GLint k = 0;
  901.  
  902.       if (!Parse_Token(parseState, token))  /* get xyzw writemask */
  903.          RETURN_ERROR;
  904.  
  905.       dstReg->WriteMask = 0;
  906.  
  907.       if (token[k] == 'x') {
  908.          dstReg->WriteMask |= WRITEMASK_X;
  909.          k++;
  910.       }
  911.       if (token[k] == 'y') {
  912.          dstReg->WriteMask |= WRITEMASK_Y;
  913.          k++;
  914.       }
  915.       if (token[k] == 'z') {
  916.          dstReg->WriteMask |= WRITEMASK_Z;
  917.          k++;
  918.       }
  919.       if (token[k] == 'w') {
  920.          dstReg->WriteMask |= WRITEMASK_W;
  921.          k++;
  922.       }
  923.       if (k == 0) {
  924.          RETURN_ERROR1("Invalid writemask character");
  925.       }
  926.  
  927.    }
  928.    else {
  929.       dstReg->WriteMask = WRITEMASK_XYZW;
  930.    }
  931.  
  932.    /* optional condition code mask */
  933.    if (Parse_String(parseState, "(")) {
  934.       /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".x|y|z|w) */
  935.       /* ("EQ" | "GE" | "GT" | "LE" | "LT" | "NE" | "TR" | "FL".[xyzw]) */
  936.       if (!Parse_CondCodeMask(parseState, dstReg))
  937.          RETURN_ERROR;
  938.  
  939.       if (!Parse_String(parseState, ")"))  /* consume ")" */
  940.          RETURN_ERROR1("Expected )");
  941.  
  942.       return GL_TRUE;
  943.    }
  944.    else {
  945.       /* no cond code mask */
  946.       dstReg->CondMask = COND_TR;
  947.       dstReg->CondSwizzle = SWIZZLE_NOOP;
  948.       return GL_TRUE;
  949.    }
  950. }
  951.  
  952.  
  953. /**
  954.  * Parse a vector source (register, constant, etc):
  955.  *   <vectorSrc>    ::= <absVectorSrc>
  956.  *                    | <baseVectorSrc>
  957.  *   <absVectorSrc> ::= <negate> "|" <baseVectorSrc> "|"
  958.  */
  959. static GLboolean
  960. Parse_VectorSrc(struct parse_state *parseState,
  961.                 struct prog_src_register *srcReg)
  962. {
  963.    GLfloat sign = 1.0F;
  964.    GLubyte token[100];
  965.    GLint idx;
  966.    GLuint negateBase, negateAbs;
  967.  
  968.    /*
  969.     * First, take care of +/- and absolute value stuff.
  970.     */
  971.    if (Parse_String(parseState, "-"))
  972.       sign = -1.0F;
  973.    else if (Parse_String(parseState, "+"))
  974.       sign = +1.0F;
  975.  
  976.    if (Parse_String(parseState, "|")) {
  977.       srcReg->Abs = GL_TRUE;
  978.       negateAbs = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
  979.  
  980.       if (Parse_String(parseState, "-"))
  981.          negateBase = NEGATE_XYZW;
  982.       else if (Parse_String(parseState, "+"))
  983.          negateBase = NEGATE_NONE;
  984.       else
  985.          negateBase = NEGATE_NONE;
  986.    }
  987.    else {
  988.       srcReg->Abs = GL_FALSE;
  989.       negateAbs = NEGATE_NONE;
  990.       negateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
  991.    }
  992.  
  993.    srcReg->Negate = srcReg->Abs ? negateAbs : negateBase;
  994.  
  995.    /* This should be the real src vector/register name */
  996.    if (!Peek_Token(parseState, token))
  997.       RETURN_ERROR;
  998.  
  999.    /* Src reg can be Rn, Hn, f[n], p[n], a named parameter, a scalar
  1000.     * literal or vector literal.
  1001.     */
  1002.    if (token[0] == 'R' || token[0] == 'H') {
  1003.       srcReg->File = PROGRAM_TEMPORARY;
  1004.       if (!Parse_TempReg(parseState, &idx))
  1005.          RETURN_ERROR;
  1006.       srcReg->Index = idx;
  1007.    }
  1008.    else if (token[0] == 'f') {
  1009.       /* XXX this might be an identifier! */
  1010.       srcReg->File = PROGRAM_INPUT;
  1011.       if (!Parse_FragReg(parseState, &idx))
  1012.          RETURN_ERROR;
  1013.       srcReg->Index = idx;
  1014.    }
  1015.    else if (token[0] == 'p') {
  1016.       /* XXX this might be an identifier! */
  1017.       srcReg->File = PROGRAM_LOCAL_PARAM;
  1018.       if (!Parse_ProgramParamReg(parseState, &idx))
  1019.          RETURN_ERROR;
  1020.       srcReg->Index = idx;
  1021.    }
  1022.    else if (IsLetter(token[0])){
  1023.       GLubyte ident[100];
  1024.       GLint paramIndex;
  1025.       if (!Parse_Identifier(parseState, ident))
  1026.          RETURN_ERROR;
  1027.       paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
  1028.                                                 -1, (const char *) ident);
  1029.       if (paramIndex < 0) {
  1030.          RETURN_ERROR2("Undefined constant or parameter: ", ident);
  1031.       }
  1032.       srcReg->File = PROGRAM_NAMED_PARAM;
  1033.       srcReg->Index = paramIndex;      
  1034.    }
  1035.    else if (IsDigit(token[0]) || token[0] == '-' || token[0] == '+' || token[0] == '.'){
  1036.       /* literal scalar constant */
  1037.       GLfloat values[4];
  1038.       GLuint paramIndex;
  1039.       if (!Parse_ScalarConstant(parseState, values))
  1040.          RETURN_ERROR;
  1041.       paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
  1042.                                               values, 4, NULL);
  1043.       srcReg->File = PROGRAM_NAMED_PARAM;
  1044.       srcReg->Index = paramIndex;
  1045.    }
  1046.    else if (token[0] == '{'){
  1047.       /* literal vector constant */
  1048.       GLfloat values[4];
  1049.       GLuint paramIndex;
  1050.       (void) Parse_String(parseState, "{");
  1051.       if (!Parse_VectorConstant(parseState, values))
  1052.          RETURN_ERROR;
  1053.       paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
  1054.                                               values, 4, NULL);
  1055.       srcReg->File = PROGRAM_NAMED_PARAM;
  1056.       srcReg->Index = paramIndex;      
  1057.    }
  1058.    else {
  1059.       RETURN_ERROR2("Invalid source register name", token);
  1060.    }
  1061.  
  1062.    /* init swizzle fields */
  1063.    srcReg->Swizzle = SWIZZLE_NOOP;
  1064.  
  1065.    /* Look for optional swizzle suffix */
  1066.    if (Parse_String(parseState, ".")) {
  1067.       GLuint swz[4];
  1068.  
  1069.       if (!Parse_Token(parseState, token))
  1070.          RETURN_ERROR;
  1071.  
  1072.       if (!Parse_SwizzleSuffix(token, swz))
  1073.          RETURN_ERROR1("Invalid swizzle suffix");
  1074.  
  1075.       srcReg->Swizzle = MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
  1076.    }
  1077.  
  1078.    /* Finish absolute value */
  1079.    if (srcReg->Abs && !Parse_String(parseState, "|")) {
  1080.       RETURN_ERROR1("Expected |");
  1081.    }
  1082.  
  1083.    return GL_TRUE;
  1084. }
  1085.  
  1086.  
  1087. static GLboolean
  1088. Parse_ScalarSrcReg(struct parse_state *parseState,
  1089.                    struct prog_src_register *srcReg)
  1090. {
  1091.    GLubyte token[100];
  1092.    GLfloat sign = 1.0F;
  1093.    GLboolean needSuffix = GL_TRUE;
  1094.    GLint idx;
  1095.    GLuint negateBase, negateAbs;
  1096.  
  1097.    /*
  1098.     * First, take care of +/- and absolute value stuff.
  1099.     */
  1100.    if (Parse_String(parseState, "-"))
  1101.       sign = -1.0F;
  1102.    else if (Parse_String(parseState, "+"))
  1103.       sign = +1.0F;
  1104.  
  1105.    if (Parse_String(parseState, "|")) {
  1106.       srcReg->Abs = GL_TRUE;
  1107.       negateAbs = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
  1108.  
  1109.       if (Parse_String(parseState, "-"))
  1110.          negateBase = NEGATE_XYZW;
  1111.       else if (Parse_String(parseState, "+"))
  1112.          negateBase = NEGATE_NONE;
  1113.       else
  1114.          negateBase = NEGATE_NONE;
  1115.    }
  1116.    else {
  1117.       srcReg->Abs = GL_FALSE;
  1118.       negateAbs = NEGATE_NONE;
  1119.       negateBase = (sign < 0.0F) ? NEGATE_XYZW : NEGATE_NONE;
  1120.    }
  1121.  
  1122.    srcReg->Negate = srcReg->Abs ? negateAbs : negateBase;
  1123.  
  1124.    if (!Peek_Token(parseState, token))
  1125.       RETURN_ERROR;
  1126.  
  1127.    /* Src reg can be R<n>, H<n> or a named fragment attrib */
  1128.    if (token[0] == 'R' || token[0] == 'H') {
  1129.       srcReg->File = PROGRAM_TEMPORARY;
  1130.       if (!Parse_TempReg(parseState, &idx))
  1131.          RETURN_ERROR;
  1132.       srcReg->Index = idx;
  1133.    }
  1134.    else if (token[0] == 'f') {
  1135.       srcReg->File = PROGRAM_INPUT;
  1136.       if (!Parse_FragReg(parseState, &idx))
  1137.          RETURN_ERROR;
  1138.       srcReg->Index = idx;
  1139.    }
  1140.    else if (token[0] == '{') {
  1141.       /* vector literal */
  1142.       GLfloat values[4];
  1143.       GLuint paramIndex;
  1144.       (void) Parse_String(parseState, "{");
  1145.       if (!Parse_VectorConstant(parseState, values))
  1146.          RETURN_ERROR;
  1147.       paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
  1148.                                               values, 4, NULL);
  1149.       srcReg->File = PROGRAM_NAMED_PARAM;
  1150.       srcReg->Index = paramIndex;      
  1151.    }
  1152.    else if (IsLetter(token[0])){
  1153.       /* named param/constant */
  1154.       GLubyte ident[100];
  1155.       GLint paramIndex;
  1156.       if (!Parse_Identifier(parseState, ident))
  1157.          RETURN_ERROR;
  1158.       paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
  1159.                                                 -1, (const char *) ident);
  1160.       if (paramIndex < 0) {
  1161.          RETURN_ERROR2("Undefined constant or parameter: ", ident);
  1162.       }
  1163.       srcReg->File = PROGRAM_NAMED_PARAM;
  1164.       srcReg->Index = paramIndex;      
  1165.    }
  1166.    else if (IsDigit(token[0])) {
  1167.       /* scalar literal */
  1168.       GLfloat values[4];
  1169.       GLuint paramIndex;
  1170.       if (!Parse_ScalarConstant(parseState, values))
  1171.          RETURN_ERROR;
  1172.       paramIndex = _mesa_add_unnamed_constant(parseState->parameters,
  1173.                                               values, 4, NULL);
  1174.       srcReg->Index = paramIndex;      
  1175.       srcReg->File = PROGRAM_NAMED_PARAM;
  1176.       needSuffix = GL_FALSE;
  1177.    }
  1178.    else {
  1179.       RETURN_ERROR2("Invalid scalar source argument", token);
  1180.    }
  1181.  
  1182.    srcReg->Swizzle = 0;
  1183.    if (needSuffix) {
  1184.       /* parse .[xyzw] suffix */
  1185.       if (!Parse_String(parseState, "."))
  1186.          RETURN_ERROR1("Expected .");
  1187.  
  1188.       if (!Parse_Token(parseState, token))
  1189.          RETURN_ERROR;
  1190.  
  1191.       if (token[0] == 'x' && token[1] == 0) {
  1192.          srcReg->Swizzle = 0;
  1193.       }
  1194.       else if (token[0] == 'y' && token[1] == 0) {
  1195.          srcReg->Swizzle = 1;
  1196.       }
  1197.       else if (token[0] == 'z' && token[1] == 0) {
  1198.          srcReg->Swizzle = 2;
  1199.       }
  1200.       else if (token[0] == 'w' && token[1] == 0) {
  1201.          srcReg->Swizzle = 3;
  1202.       }
  1203.       else {
  1204.          RETURN_ERROR1("Invalid scalar source suffix");
  1205.       }
  1206.    }
  1207.  
  1208.    /* Finish absolute value */
  1209.    if (srcReg->Abs && !Parse_String(parseState, "|")) {
  1210.       RETURN_ERROR1("Expected |");
  1211.    }
  1212.  
  1213.    return GL_TRUE;
  1214. }
  1215.  
  1216.  
  1217. static GLboolean
  1218. Parse_PrintInstruction(struct parse_state *parseState,
  1219.                        struct prog_instruction *inst)
  1220. {
  1221.    const GLubyte *str;
  1222.    GLubyte *msg;
  1223.    GLuint len;
  1224.    GLint idx;
  1225.  
  1226.    /* The first argument is a literal string 'just like this' */
  1227.    if (!Parse_String(parseState, "'"))
  1228.       RETURN_ERROR1("Expected '");
  1229.  
  1230.    str = parseState->pos;
  1231.    for (len = 0; str[len] != '\''; len++) /* find closing quote */
  1232.       ;
  1233.    parseState->pos += len + 1;
  1234.    msg = (GLubyte*) malloc(len + 1);
  1235.  
  1236.    memcpy(msg, str, len);
  1237.    msg[len] = 0;
  1238.    inst->Data = msg;
  1239.  
  1240.    if (Parse_String(parseState, ",")) {
  1241.       /* got an optional register to print */
  1242.       GLubyte token[100];
  1243.       GetToken(parseState, token);
  1244.       if (token[0] == 'o') {
  1245.          /* dst reg */
  1246.          if (!Parse_OutputReg(parseState, &idx))
  1247.             RETURN_ERROR;
  1248.          inst->SrcReg[0].Index = idx;
  1249.          inst->SrcReg[0].File = PROGRAM_OUTPUT;
  1250.       }
  1251.       else {
  1252.          /* src reg */
  1253.          if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
  1254.             RETURN_ERROR;
  1255.       }
  1256.    }
  1257.    else {
  1258.       inst->SrcReg[0].File = PROGRAM_UNDEFINED;
  1259.    }
  1260.  
  1261.    inst->SrcReg[0].Swizzle = SWIZZLE_NOOP;
  1262.    inst->SrcReg[0].Abs = GL_FALSE;
  1263.    inst->SrcReg[0].Negate = NEGATE_NONE;
  1264.  
  1265.    return GL_TRUE;
  1266. }
  1267.  
  1268.  
  1269. static GLboolean
  1270. Parse_InstructionSequence(struct parse_state *parseState,
  1271.                           struct prog_instruction program[])
  1272. {
  1273.    while (1) {
  1274.       struct prog_instruction *inst = program + parseState->numInst;
  1275.       struct instruction_pattern instMatch;
  1276.       GLubyte token[100];
  1277.  
  1278.       /* Initialize the instruction */
  1279.       _mesa_init_instructions(inst, 1);
  1280.  
  1281.       /* special instructions */
  1282.       if (Parse_String(parseState, "DEFINE")) {
  1283.          GLubyte id[100];
  1284.          GLfloat value[7];  /* yes, 7 to be safe */
  1285.          if (!Parse_Identifier(parseState, id))
  1286.             RETURN_ERROR;
  1287.          /* XXX make sure id is not a reserved identifer, like R9 */
  1288.          if (!Parse_String(parseState, "="))
  1289.             RETURN_ERROR1("Expected =");
  1290.          if (!Parse_VectorOrScalarConstant(parseState, value))
  1291.             RETURN_ERROR;
  1292.          if (!Parse_String(parseState, ";"))
  1293.             RETURN_ERROR1("Expected ;");
  1294.          if (_mesa_lookup_parameter_index(parseState->parameters,
  1295.                                           -1, (const char *) id) >= 0) {
  1296.             RETURN_ERROR2(id, "already defined");
  1297.          }
  1298.          _mesa_add_named_parameter(parseState->parameters,
  1299.                                    (const char *) id, value);
  1300.       }
  1301.       else if (Parse_String(parseState, "DECLARE")) {
  1302.          GLubyte id[100];
  1303.          GLfloat value[7] = {0, 0, 0, 0, 0, 0, 0};  /* yes, to be safe */
  1304.          if (!Parse_Identifier(parseState, id))
  1305.             RETURN_ERROR;
  1306.          /* XXX make sure id is not a reserved identifer, like R9 */
  1307.          if (Parse_String(parseState, "=")) {
  1308.             if (!Parse_VectorOrScalarConstant(parseState, value))
  1309.                RETURN_ERROR;
  1310.          }
  1311.          if (!Parse_String(parseState, ";"))
  1312.             RETURN_ERROR1("Expected ;");
  1313.          if (_mesa_lookup_parameter_index(parseState->parameters,
  1314.                                           -1, (const char *) id) >= 0) {
  1315.             RETURN_ERROR2(id, "already declared");
  1316.          }
  1317.          _mesa_add_named_parameter(parseState->parameters,
  1318.                                    (const char *) id, value);
  1319.       }
  1320.       else if (Parse_String(parseState, "END")) {
  1321.          inst->Opcode = OPCODE_END;
  1322.          parseState->numInst++;
  1323.          if (Parse_Token(parseState, token)) {
  1324.             RETURN_ERROR1("Code after END opcode.");
  1325.          }
  1326.          break;
  1327.       }
  1328.       else {
  1329.          /* general/arithmetic instruction */
  1330.  
  1331.          /* get token */
  1332.          if (!Parse_Token(parseState, token)) {
  1333.             RETURN_ERROR1("Missing END instruction.");
  1334.          }
  1335.  
  1336.          /* try to find matching instuction */
  1337.          instMatch = MatchInstruction(token);
  1338.          if (instMatch.opcode >= MAX_OPCODE) {
  1339.             /* bad instruction name */
  1340.             RETURN_ERROR2("Unexpected token: ", token);
  1341.          }
  1342.  
  1343.          inst->Opcode = instMatch.opcode;
  1344.          inst->Precision = instMatch.suffixes & (_R | _H | _X);
  1345.          inst->SaturateMode = (instMatch.suffixes & (_S))
  1346.             ? SATURATE_ZERO_ONE : SATURATE_OFF;
  1347.          inst->CondUpdate = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE;
  1348.  
  1349.          /*
  1350.           * parse the input and output operands
  1351.           */
  1352.          if (instMatch.outputs == OUTPUT_S || instMatch.outputs == OUTPUT_V) {
  1353.             if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
  1354.                RETURN_ERROR;
  1355.             if (!Parse_String(parseState, ","))
  1356.                RETURN_ERROR1("Expected ,");
  1357.          }
  1358.          else if (instMatch.outputs == OUTPUT_NONE) {
  1359.             if (instMatch.opcode == OPCODE_KIL_NV) {
  1360.                /* This is a little weird, the cond code info is in
  1361.                 * the dest register.
  1362.                 */
  1363.                if (!Parse_CondCodeMask(parseState, &inst->DstReg))
  1364.                   RETURN_ERROR;
  1365.             }
  1366.             else {
  1367.                ASSERT(instMatch.opcode == OPCODE_PRINT);
  1368.             }
  1369.          }
  1370.  
  1371.          if (instMatch.inputs == INPUT_1V) {
  1372.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
  1373.                RETURN_ERROR;
  1374.          }
  1375.          else if (instMatch.inputs == INPUT_2V) {
  1376.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
  1377.                RETURN_ERROR;
  1378.             if (!Parse_String(parseState, ","))
  1379.                RETURN_ERROR1("Expected ,");
  1380.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
  1381.                RETURN_ERROR;
  1382.          }
  1383.          else if (instMatch.inputs == INPUT_3V) {
  1384.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
  1385.                RETURN_ERROR;
  1386.             if (!Parse_String(parseState, ","))
  1387.                RETURN_ERROR1("Expected ,");
  1388.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
  1389.                RETURN_ERROR;
  1390.             if (!Parse_String(parseState, ","))
  1391.                RETURN_ERROR1("Expected ,");
  1392.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
  1393.                RETURN_ERROR;
  1394.          }
  1395.          else if (instMatch.inputs == INPUT_1S) {
  1396.             if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
  1397.                RETURN_ERROR;
  1398.          }
  1399.          else if (instMatch.inputs == INPUT_2S) {
  1400.             if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
  1401.                RETURN_ERROR;
  1402.             if (!Parse_String(parseState, ","))
  1403.                RETURN_ERROR1("Expected ,");
  1404.             if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[1]))
  1405.                RETURN_ERROR;
  1406.          }
  1407.          else if (instMatch.inputs == INPUT_CC) {
  1408.             /* XXX to-do */
  1409.          }
  1410.          else if (instMatch.inputs == INPUT_1V_T) {
  1411.             GLubyte unit, idx;
  1412.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
  1413.                RETURN_ERROR;
  1414.             if (!Parse_String(parseState, ","))
  1415.                RETURN_ERROR1("Expected ,");
  1416.             if (!Parse_TextureImageId(parseState, &unit, &idx))
  1417.                RETURN_ERROR;
  1418.             inst->TexSrcUnit = unit;
  1419.             inst->TexSrcTarget = idx;
  1420.          }
  1421.          else if (instMatch.inputs == INPUT_3V_T) {
  1422.             GLubyte unit, idx;
  1423.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
  1424.                RETURN_ERROR;
  1425.             if (!Parse_String(parseState, ","))
  1426.                RETURN_ERROR1("Expected ,");
  1427.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
  1428.                RETURN_ERROR;
  1429.             if (!Parse_String(parseState, ","))
  1430.                RETURN_ERROR1("Expected ,");
  1431.             if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
  1432.                RETURN_ERROR;
  1433.             if (!Parse_String(parseState, ","))
  1434.                RETURN_ERROR1("Expected ,");
  1435.             if (!Parse_TextureImageId(parseState, &unit, &idx))
  1436.                RETURN_ERROR;
  1437.             inst->TexSrcUnit = unit;
  1438.             inst->TexSrcTarget = idx;
  1439.          }
  1440.          else if (instMatch.inputs == INPUT_1V_S) {
  1441.             if (!Parse_PrintInstruction(parseState, inst))
  1442.                RETURN_ERROR;
  1443.          }
  1444.  
  1445.          /* end of statement semicolon */
  1446.          if (!Parse_String(parseState, ";"))
  1447.             RETURN_ERROR1("Expected ;");
  1448.  
  1449.          parseState->numInst++;
  1450.  
  1451.          if (parseState->numInst >= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS)
  1452.             RETURN_ERROR1("Program too long");
  1453.       }
  1454.    }
  1455.    return GL_TRUE;
  1456. }
  1457.  
  1458.  
  1459.  
  1460. /**
  1461.  * Parse/compile the 'str' returning the compiled 'program'.
  1462.  * ctx->Program.ErrorPos will be -1 if successful.  Otherwise, ErrorPos
  1463.  * indicates the position of the error in 'str'.
  1464.  */
  1465. void
  1466. _mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum dstTarget,
  1467.                                 const GLubyte *str, GLsizei len,
  1468.                                 struct gl_fragment_program *program)
  1469. {
  1470.    struct parse_state parseState;
  1471.    struct prog_instruction instBuffer[MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS];
  1472.    struct prog_instruction *newInst;
  1473.    GLenum target;
  1474.    GLubyte *programString;
  1475.  
  1476.    /* Make a null-terminated copy of the program string */
  1477.    programString = (GLubyte *) MALLOC(len + 1);
  1478.    if (!programString) {
  1479.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
  1480.       return;
  1481.    }
  1482.    memcpy(programString, str, len);
  1483.    programString[len] = 0;
  1484.  
  1485.    /* Get ready to parse */
  1486.    memset(&parseState, 0, sizeof(struct parse_state));
  1487.    parseState.ctx = ctx;
  1488.    parseState.start = programString;
  1489.    parseState.program = program;
  1490.    parseState.numInst = 0;
  1491.    parseState.curLine = programString;
  1492.    parseState.parameters = _mesa_new_parameter_list();
  1493.  
  1494.    /* Reset error state */
  1495.    _mesa_set_program_error(ctx, -1, NULL);
  1496.  
  1497.    /* check the program header */
  1498.    if (strncmp((const char *) programString, "!!FP1.0", 7) == 0) {
  1499.       target = GL_FRAGMENT_PROGRAM_NV;
  1500.       parseState.pos = programString + 7;
  1501.    }
  1502.    else if (strncmp((const char *) programString, "!!FCP1.0", 8) == 0) {
  1503.       /* fragment / register combiner program - not supported */
  1504.       _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
  1505.       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
  1506.       return;
  1507.    }
  1508.    else {
  1509.       /* invalid header */
  1510.       _mesa_set_program_error(ctx, 0, "Invalid fragment program header");
  1511.       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
  1512.       return;
  1513.    }
  1514.  
  1515.    /* make sure target and header match */
  1516.    if (target != dstTarget) {
  1517.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1518.                   "glLoadProgramNV(target mismatch 0x%x != 0x%x)",
  1519.                   target, dstTarget);
  1520.       return;
  1521.    }
  1522.  
  1523.    if (Parse_InstructionSequence(&parseState, instBuffer)) {
  1524.       GLuint u;
  1525.       /* successful parse! */
  1526.  
  1527.       if (parseState.outputsWritten == 0) {
  1528.          /* must write at least one output! */
  1529.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1530.                      "Invalid fragment program - no outputs written.");
  1531.          return;
  1532.       }
  1533.  
  1534.       /* copy the compiled instructions */
  1535.       assert(parseState.numInst <= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS);
  1536.       newInst = _mesa_alloc_instructions(parseState.numInst);
  1537.       if (!newInst) {
  1538.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
  1539.          return;  /* out of memory */
  1540.       }
  1541.       _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);
  1542.  
  1543.       /* install the program */
  1544.       program->Base.Target = target;
  1545.       if (program->Base.String) {
  1546.          FREE(program->Base.String);
  1547.       }
  1548.       program->Base.String = programString;
  1549.       program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
  1550.       if (program->Base.Instructions) {
  1551.          free(program->Base.Instructions);
  1552.       }
  1553.       program->Base.Instructions = newInst;
  1554.       program->Base.NumInstructions = parseState.numInst;
  1555.       program->Base.InputsRead = parseState.inputsRead;
  1556.       program->Base.OutputsWritten = parseState.outputsWritten;
  1557.       for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++)
  1558.          program->Base.TexturesUsed[u] = parseState.texturesUsed[u];
  1559.  
  1560.       /* save program parameters */
  1561.       program->Base.Parameters = parseState.parameters;
  1562.  
  1563.       /* allocate registers for declared program parameters */
  1564. #if 00
  1565.       _mesa_assign_program_registers(&(program->SymbolTable));
  1566. #endif
  1567.  
  1568. #ifdef DEBUG_foo
  1569.       printf("--- glLoadProgramNV(%d) result ---\n", program->Base.Id);
  1570.       _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0);
  1571.       printf("----------------------------------\n");
  1572. #endif
  1573.    }
  1574.    else {
  1575.       /* Error! */
  1576.       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
  1577.       /* NOTE: _mesa_set_program_error would have been called already */
  1578.    }
  1579. }
  1580.  
  1581.  
  1582. const char *
  1583. _mesa_nv_fragment_input_register_name(GLuint i)
  1584. {
  1585.    ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
  1586.    return InputRegisters[i];
  1587. }
  1588.  
  1589.