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.2
  4.  *
  5.  * Copyright (C) 1999-2006  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 nvvertparse.c
  27.  * NVIDIA vertex program parser.
  28.  * \author Brian Paul
  29.  */
  30.  
  31. /*
  32.  * Regarding GL_NV_vertex_program, GL_NV_vertex_program1_1:
  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/nvprogram.h"
  44. #include "nvvertparse.h"
  45. #include "prog_instruction.h"
  46. #include "prog_parameter.h"
  47. #include "prog_print.h"
  48. #include "program.h"
  49.  
  50.  
  51. /**
  52.  * Current parsing state.  This structure is passed among the parsing
  53.  * functions and keeps track of the current parser position and various
  54.  * program attributes.
  55.  */
  56. struct parse_state {
  57.    struct gl_context *ctx;
  58.    const GLubyte *start;
  59.    const GLubyte *pos;
  60.    const GLubyte *curLine;
  61.    GLboolean isStateProgram;
  62.    GLboolean isPositionInvariant;
  63.    GLboolean isVersion1_1;
  64.    GLbitfield inputsRead;
  65.    GLbitfield outputsWritten;
  66.    GLboolean anyProgRegsWritten;
  67.    GLboolean indirectRegisterFiles;
  68.    GLuint numInst;                 /* number of instructions parsed */
  69. };
  70.  
  71.  
  72. /*
  73.  * Called whenever we find an error during parsing.
  74.  */
  75. static void
  76. record_error(struct parse_state *parseState, const char *msg, int lineNo)
  77. {
  78. #ifdef DEBUG
  79.    GLint line, column;
  80.    const GLubyte *lineStr;
  81.    lineStr = _mesa_find_line_column(parseState->start,
  82.                                     parseState->pos, &line, &column);
  83.    _mesa_debug(parseState->ctx,
  84.                "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
  85.                lineNo, line, column, (char *) lineStr, msg);
  86.    free((void *) lineStr);
  87. #else
  88.    (void) lineNo;
  89. #endif
  90.  
  91.    /* Check that no error was already recorded.  Only record the first one. */
  92.    if (parseState->ctx->Program.ErrorString[0] == 0) {
  93.       _mesa_set_program_error(parseState->ctx,
  94.                               parseState->pos - parseState->start,
  95.                               msg);
  96.    }
  97. }
  98.  
  99.  
  100. #define RETURN_ERROR                                                    \
  101. do {                                                                    \
  102.    record_error(parseState, "Unexpected end of input.", __LINE__);      \
  103.    return GL_FALSE;                                                     \
  104. } while(0)
  105.  
  106. #define RETURN_ERROR1(msg)                                              \
  107. do {                                                                    \
  108.    record_error(parseState, msg, __LINE__);                             \
  109.    return GL_FALSE;                                                     \
  110. } while(0)
  111.  
  112. #define RETURN_ERROR2(msg1, msg2)                                       \
  113. do {                                                                    \
  114.    char err[1000];                                                      \
  115.    sprintf(err, "%s %s", msg1, msg2);                           \
  116.    record_error(parseState, err, __LINE__);                             \
  117.    return GL_FALSE;                                                     \
  118. } while(0)
  119.  
  120.  
  121.  
  122.  
  123.  
  124. static GLboolean IsLetter(GLubyte b)
  125. {
  126.    return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z');
  127. }
  128.  
  129.  
  130. static GLboolean IsDigit(GLubyte b)
  131. {
  132.    return b >= '0' && b <= '9';
  133. }
  134.  
  135.  
  136. static GLboolean IsWhitespace(GLubyte b)
  137. {
  138.    return b == ' ' || b == '\t' || b == '\n' || b == '\r';
  139. }
  140.  
  141.  
  142. /**
  143.  * Starting at 'str' find the next token.  A token can be an integer,
  144.  * an identifier or punctuation symbol.
  145.  * \return <= 0 we found an error, else, return number of characters parsed.
  146.  */
  147. static GLint
  148. GetToken(struct parse_state *parseState, GLubyte *token)
  149. {
  150.    const GLubyte *str = parseState->pos;
  151.    GLint i = 0, j = 0;
  152.  
  153.    token[0] = 0;
  154.  
  155.    /* skip whitespace and comments */
  156.    while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {
  157.       if (str[i] == '#') {
  158.          /* skip comment */
  159.          while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
  160.             i++;
  161.          }
  162.          if (str[i] == '\n' || str[i] == '\r')
  163.             parseState->curLine = str + i + 1;
  164.       }
  165.       else {
  166.          /* skip whitespace */
  167.          if (str[i] == '\n' || str[i] == '\r')
  168.             parseState->curLine = str + i + 1;
  169.          i++;
  170.       }
  171.    }
  172.  
  173.    if (str[i] == 0)
  174.       return -i;
  175.  
  176.    /* try matching an integer */
  177.    while (str[i] && IsDigit(str[i])) {
  178.       token[j++] = str[i++];
  179.    }
  180.    if (j > 0 || !str[i]) {
  181.       token[j] = 0;
  182.       return i;
  183.    }
  184.  
  185.    /* try matching an identifier */
  186.    if (IsLetter(str[i])) {
  187.       while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {
  188.          token[j++] = str[i++];
  189.       }
  190.       token[j] = 0;
  191.       return i;
  192.    }
  193.  
  194.    /* punctuation character */
  195.    if (str[i]) {
  196.       token[0] = str[i++];
  197.       token[1] = 0;
  198.       return i;
  199.    }
  200.  
  201.    /* end of input */
  202.    token[0] = 0;
  203.    return i;
  204. }
  205.  
  206.  
  207. /**
  208.  * Get next token from input stream and increment stream pointer past token.
  209.  */
  210. static GLboolean
  211. Parse_Token(struct parse_state *parseState, GLubyte *token)
  212. {
  213.    GLint i;
  214.    i = GetToken(parseState, token);
  215.    if (i <= 0) {
  216.       parseState->pos += (-i);
  217.       return GL_FALSE;
  218.    }
  219.    parseState->pos += i;
  220.    return GL_TRUE;
  221. }
  222.  
  223.  
  224. /**
  225.  * Get next token from input stream but don't increment stream pointer.
  226.  */
  227. static GLboolean
  228. Peek_Token(struct parse_state *parseState, GLubyte *token)
  229. {
  230.    GLint i, len;
  231.    i = GetToken(parseState, token);
  232.    if (i <= 0) {
  233.       parseState->pos += (-i);
  234.       return GL_FALSE;
  235.    }
  236.    len = (GLint) strlen((const char *) token);
  237.    parseState->pos += (i - len);
  238.    return GL_TRUE;
  239. }
  240.  
  241.  
  242. /**
  243.  * Try to match 'pattern' as the next token after any whitespace/comments.
  244.  * Advance the current parsing position only if we match the pattern.
  245.  * \return GL_TRUE if pattern is matched, GL_FALSE otherwise.
  246.  */
  247. static GLboolean
  248. Parse_String(struct parse_state *parseState, const char *pattern)
  249. {
  250.    const GLubyte *m;
  251.    GLint i;
  252.  
  253.    /* skip whitespace and comments */
  254.    while (IsWhitespace(*parseState->pos) || *parseState->pos == '#') {
  255.       if (*parseState->pos == '#') {
  256.          while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {
  257.             parseState->pos += 1;
  258.          }
  259.          if (*parseState->pos == '\n' || *parseState->pos == '\r')
  260.             parseState->curLine = parseState->pos + 1;
  261.       }
  262.       else {
  263.          /* skip whitespace */
  264.          if (*parseState->pos == '\n' || *parseState->pos == '\r')
  265.             parseState->curLine = parseState->pos + 1;
  266.          parseState->pos += 1;
  267.       }
  268.    }
  269.  
  270.    /* Try to match the pattern */
  271.    m = parseState->pos;
  272.    for (i = 0; pattern[i]; i++) {
  273.       if (*m != (GLubyte) pattern[i])
  274.          return GL_FALSE;
  275.       m += 1;
  276.    }
  277.    parseState->pos = m;
  278.  
  279.    return GL_TRUE; /* success */
  280. }
  281.  
  282.  
  283. /**********************************************************************/
  284.  
  285. static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = {
  286.    "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7",
  287.    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
  288. };
  289.  
  290. static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = {
  291.    "HPOS", "COL0", "COL1", "FOGC",
  292.    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7",
  293.    "PSIZ", "BFC0", "BFC1", NULL
  294. };
  295.  
  296.  
  297.  
  298. /**
  299.  * Parse a temporary register: Rnn
  300.  */
  301. static GLboolean
  302. Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
  303. {
  304.    GLubyte token[100];
  305.  
  306.    /* Should be 'R##' */
  307.    if (!Parse_Token(parseState, token))
  308.       RETURN_ERROR;
  309.    if (token[0] != 'R')
  310.       RETURN_ERROR1("Expected R##");
  311.  
  312.    if (IsDigit(token[1])) {
  313.       GLint reg = atoi((char *) (token + 1));
  314.       if (reg >= MAX_NV_VERTEX_PROGRAM_TEMPS)
  315.          RETURN_ERROR1("Bad temporary register name");
  316.       *tempRegNum = reg;
  317.    }
  318.    else {
  319.       RETURN_ERROR1("Bad temporary register name");
  320.    }
  321.  
  322.    return GL_TRUE;
  323. }
  324.  
  325.  
  326. /**
  327.  * Parse address register "A0.x"
  328.  */
  329. static GLboolean
  330. Parse_AddrReg(struct parse_state *parseState)
  331. {
  332.    /* match 'A0' */
  333.    if (!Parse_String(parseState, "A0"))
  334.       RETURN_ERROR;
  335.  
  336.    /* match '.' */
  337.    if (!Parse_String(parseState, "."))
  338.       RETURN_ERROR;
  339.  
  340.    /* match 'x' */
  341.    if (!Parse_String(parseState, "x"))
  342.       RETURN_ERROR;
  343.  
  344.    return GL_TRUE;
  345. }
  346.  
  347.  
  348. /**
  349.  * Parse absolute program parameter register "c[##]"
  350.  */
  351. static GLboolean
  352. Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum)
  353. {
  354.    GLubyte token[100];
  355.  
  356.    if (!Parse_String(parseState, "c"))
  357.       RETURN_ERROR;
  358.  
  359.    if (!Parse_String(parseState, "["))
  360.       RETURN_ERROR;
  361.  
  362.    if (!Parse_Token(parseState, token))
  363.       RETURN_ERROR;
  364.  
  365.    if (IsDigit(token[0])) {
  366.       /* a numbered program parameter register */
  367.       GLint reg = atoi((char *) token);
  368.       if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
  369.          RETURN_ERROR1("Bad program parameter number");
  370.       *regNum = reg;
  371.    }
  372.    else {
  373.       RETURN_ERROR;
  374.    }
  375.  
  376.    if (!Parse_String(parseState, "]"))
  377.       RETURN_ERROR;
  378.  
  379.    return GL_TRUE;
  380. }
  381.  
  382.  
  383. static GLboolean
  384. Parse_ParamReg(struct parse_state *parseState, struct prog_src_register *srcReg)
  385. {
  386.    GLubyte token[100];
  387.  
  388.    if (!Parse_String(parseState, "c"))
  389.       RETURN_ERROR;
  390.  
  391.    if (!Parse_String(parseState, "["))
  392.       RETURN_ERROR;
  393.  
  394.    if (!Peek_Token(parseState, token))
  395.       RETURN_ERROR;
  396.  
  397.    if (IsDigit(token[0])) {
  398.       /* a numbered program parameter register */
  399.       GLint reg;
  400.       (void) Parse_Token(parseState, token);
  401.       reg = atoi((char *) token);
  402.       if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
  403.          RETURN_ERROR1("Bad program parameter number");
  404.       srcReg->File = PROGRAM_ENV_PARAM;
  405.       srcReg->Index = reg;
  406.    }
  407.    else if (strcmp((const char *) token, "A0") == 0) {
  408.       /* address register "A0.x" */
  409.       if (!Parse_AddrReg(parseState))
  410.          RETURN_ERROR;
  411.  
  412.       srcReg->RelAddr = GL_TRUE;
  413.       srcReg->File = PROGRAM_ENV_PARAM;
  414.       parseState->indirectRegisterFiles |= (1 << srcReg->File);
  415.       /* Look for +/-N offset */
  416.       if (!Peek_Token(parseState, token))
  417.          RETURN_ERROR;
  418.  
  419.       if (token[0] == '-' || token[0] == '+') {
  420.          const GLubyte sign = token[0];
  421.          (void) Parse_Token(parseState, token); /* consume +/- */
  422.  
  423.          /* an integer should be next */
  424.          if (!Parse_Token(parseState, token))
  425.             RETURN_ERROR;
  426.  
  427.          if (IsDigit(token[0])) {
  428.             const GLint k = atoi((char *) token);
  429.             if (sign == '-') {
  430.                if (k > 64)
  431.                   RETURN_ERROR1("Bad address offset");
  432.                srcReg->Index = -k;
  433.             }
  434.             else {
  435.                if (k > 63)
  436.                   RETURN_ERROR1("Bad address offset");
  437.                srcReg->Index = k;
  438.             }
  439.          }
  440.          else {
  441.             RETURN_ERROR;
  442.          }
  443.       }
  444.       else {
  445.          /* probably got a ']', catch it below */
  446.       }
  447.    }
  448.    else {
  449.       RETURN_ERROR;
  450.    }
  451.  
  452.    /* Match closing ']' */
  453.    if (!Parse_String(parseState, "]"))
  454.       RETURN_ERROR;
  455.  
  456.    return GL_TRUE;
  457. }
  458.  
  459.  
  460. /**
  461.  * Parse v[#] or v[<name>]
  462.  */
  463. static GLboolean
  464. Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum)
  465. {
  466.    GLubyte token[100];
  467.    GLint j;
  468.  
  469.    /* Match 'v' */
  470.    if (!Parse_String(parseState, "v"))
  471.       RETURN_ERROR;
  472.  
  473.    /* Match '[' */
  474.    if (!Parse_String(parseState, "["))
  475.       RETURN_ERROR;
  476.  
  477.    /* match number or named register */
  478.    if (!Parse_Token(parseState, token))
  479.       RETURN_ERROR;
  480.  
  481.    if (parseState->isStateProgram && token[0] != '0')
  482.       RETURN_ERROR1("Only v[0] accessible in vertex state programs");
  483.  
  484.    if (IsDigit(token[0])) {
  485.       GLint reg = atoi((char *) token);
  486.       if (reg >= MAX_NV_VERTEX_PROGRAM_INPUTS)
  487.          RETURN_ERROR1("Bad vertex attribute register name");
  488.       *tempRegNum = reg;
  489.    }
  490.    else {
  491.       for (j = 0; InputRegisters[j]; j++) {
  492.          if (strcmp((const char *) token, InputRegisters[j]) == 0) {
  493.             *tempRegNum = j;
  494.             break;
  495.          }
  496.       }
  497.       if (!InputRegisters[j]) {
  498.          /* unknown input register label */
  499.          RETURN_ERROR2("Bad register name", token);
  500.       }
  501.    }
  502.  
  503.    /* Match '[' */
  504.    if (!Parse_String(parseState, "]"))
  505.       RETURN_ERROR;
  506.  
  507.    return GL_TRUE;
  508. }
  509.  
  510.  
  511. static GLboolean
  512. Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
  513. {
  514.    GLubyte token[100];
  515.    GLint start, j;
  516.  
  517.    /* Match 'o' */
  518.    if (!Parse_String(parseState, "o"))
  519.       RETURN_ERROR;
  520.  
  521.    /* Match '[' */
  522.    if (!Parse_String(parseState, "["))
  523.       RETURN_ERROR;
  524.  
  525.    /* Get output reg name */
  526.    if (!Parse_Token(parseState, token))
  527.       RETURN_ERROR;
  528.  
  529.    if (parseState->isPositionInvariant)
  530.       start = 1; /* skip HPOS register name */
  531.    else
  532.       start = 0;
  533.  
  534.    /* try to match an output register name */
  535.    for (j = start; OutputRegisters[j]; j++) {
  536.       if (strcmp((const char *) token, OutputRegisters[j]) == 0) {
  537.          *outputRegNum = j;
  538.          break;
  539.       }
  540.    }
  541.    if (!OutputRegisters[j])
  542.       RETURN_ERROR1("Unrecognized output register name");
  543.  
  544.    /* Match ']' */
  545.    if (!Parse_String(parseState, "]"))
  546.       RETURN_ERROR1("Expected ]");
  547.  
  548.    return GL_TRUE;
  549. }
  550.  
  551.  
  552. static GLboolean
  553. Parse_MaskedDstReg(struct parse_state *parseState, struct prog_dst_register *dstReg)
  554. {
  555.    GLubyte token[100];
  556.    GLint idx;
  557.  
  558.    /* Dst reg can be R<n> or o[n] */
  559.    if (!Peek_Token(parseState, token))
  560.       RETURN_ERROR;
  561.  
  562.    if (token[0] == 'R') {
  563.       /* a temporary register */
  564.       dstReg->File = PROGRAM_TEMPORARY;
  565.       if (!Parse_TempReg(parseState, &idx))
  566.          RETURN_ERROR;
  567.       dstReg->Index = idx;
  568.    }
  569.    else if (!parseState->isStateProgram && token[0] == 'o') {
  570.       /* an output register */
  571.       dstReg->File = PROGRAM_OUTPUT;
  572.       if (!Parse_OutputReg(parseState, &idx))
  573.          RETURN_ERROR;
  574.       dstReg->Index = idx;
  575.    }
  576.    else if (parseState->isStateProgram && token[0] == 'c' &&
  577.             parseState->isStateProgram) {
  578.       /* absolute program parameter register */
  579.       /* Only valid for vertex state programs */
  580.       dstReg->File = PROGRAM_ENV_PARAM;
  581.       if (!Parse_AbsParamReg(parseState, &idx))
  582.          RETURN_ERROR;
  583.       dstReg->Index = idx;
  584.    }
  585.    else {
  586.       RETURN_ERROR1("Bad destination register name");
  587.    }
  588.  
  589.    /* Parse optional write mask */
  590.    if (!Peek_Token(parseState, token))
  591.       RETURN_ERROR;
  592.  
  593.    if (token[0] == '.') {
  594.       /* got a mask */
  595.       GLint k = 0;
  596.  
  597.       if (!Parse_String(parseState, "."))
  598.          RETURN_ERROR;
  599.  
  600.       if (!Parse_Token(parseState, token))
  601.          RETURN_ERROR;
  602.  
  603.       dstReg->WriteMask = 0;
  604.  
  605.       if (token[k] == 'x') {
  606.          dstReg->WriteMask |= WRITEMASK_X;
  607.          k++;
  608.       }
  609.       if (token[k] == 'y') {
  610.          dstReg->WriteMask |= WRITEMASK_Y;
  611.          k++;
  612.       }
  613.       if (token[k] == 'z') {
  614.          dstReg->WriteMask |= WRITEMASK_Z;
  615.          k++;
  616.       }
  617.       if (token[k] == 'w') {
  618.          dstReg->WriteMask |= WRITEMASK_W;
  619.          k++;
  620.       }
  621.       if (k == 0) {
  622.          RETURN_ERROR1("Bad writemask character");
  623.       }
  624.       return GL_TRUE;
  625.    }
  626.    else {
  627.       dstReg->WriteMask = WRITEMASK_XYZW;
  628.       return GL_TRUE;
  629.    }
  630. }
  631.  
  632.  
  633. static GLboolean
  634. Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
  635. {
  636.    GLubyte token[100];
  637.    GLint idx;
  638.  
  639.    srcReg->RelAddr = GL_FALSE;
  640.  
  641.    /* check for '-' */
  642.    if (!Peek_Token(parseState, token))
  643.       RETURN_ERROR;
  644.    if (token[0] == '-') {
  645.       (void) Parse_String(parseState, "-");
  646.       srcReg->Negate = NEGATE_XYZW;
  647.       if (!Peek_Token(parseState, token))
  648.          RETURN_ERROR;
  649.    }
  650.    else {
  651.       srcReg->Negate = NEGATE_NONE;
  652.    }
  653.  
  654.    /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
  655.    if (token[0] == 'R') {
  656.       srcReg->File = PROGRAM_TEMPORARY;
  657.       if (!Parse_TempReg(parseState, &idx))
  658.          RETURN_ERROR;
  659.       srcReg->Index = idx;
  660.    }
  661.    else if (token[0] == 'c') {
  662.       if (!Parse_ParamReg(parseState, srcReg))
  663.          RETURN_ERROR;
  664.    }
  665.    else if (token[0] == 'v') {
  666.       srcReg->File = PROGRAM_INPUT;
  667.       if (!Parse_AttribReg(parseState, &idx))
  668.          RETURN_ERROR;
  669.       srcReg->Index = idx;
  670.    }
  671.    else {
  672.       RETURN_ERROR2("Bad source register name", token);
  673.    }
  674.  
  675.    /* init swizzle fields */
  676.    srcReg->Swizzle = SWIZZLE_NOOP;
  677.  
  678.    /* Look for optional swizzle suffix */
  679.    if (!Peek_Token(parseState, token))
  680.       RETURN_ERROR;
  681.    if (token[0] == '.') {
  682.       (void) Parse_String(parseState, ".");  /* consume . */
  683.  
  684.       if (!Parse_Token(parseState, token))
  685.          RETURN_ERROR;
  686.  
  687.       if (token[1] == 0) {
  688.          /* single letter swizzle */
  689.          if (token[0] == 'x')
  690.             srcReg->Swizzle = SWIZZLE_XXXX;
  691.          else if (token[0] == 'y')
  692.             srcReg->Swizzle = SWIZZLE_YYYY;
  693.          else if (token[0] == 'z')
  694.             srcReg->Swizzle = SWIZZLE_ZZZZ;
  695.          else if (token[0] == 'w')
  696.             srcReg->Swizzle = SWIZZLE_WWWW;
  697.          else
  698.             RETURN_ERROR1("Expected x, y, z, or w");
  699.       }
  700.       else {
  701.          /* 2, 3 or 4-component swizzle */
  702.          GLint k;
  703.  
  704.          srcReg->Swizzle = 0;
  705.  
  706.          for (k = 0; token[k] && k < 5; k++) {
  707.             if (token[k] == 'x')
  708.                srcReg->Swizzle |= 0 << (k*3);
  709.             else if (token[k] == 'y')
  710.                srcReg->Swizzle |= 1 << (k*3);
  711.             else if (token[k] == 'z')
  712.                srcReg->Swizzle |= 2 << (k*3);
  713.             else if (token[k] == 'w')
  714.                srcReg->Swizzle |= 3 << (k*3);
  715.             else
  716.                RETURN_ERROR;
  717.          }
  718.          if (k >= 5)
  719.             RETURN_ERROR;
  720.       }
  721.    }
  722.  
  723.    return GL_TRUE;
  724. }
  725.  
  726.  
  727. static GLboolean
  728. Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
  729. {
  730.    GLubyte token[100];
  731.    GLint idx;
  732.  
  733.    srcReg->RelAddr = GL_FALSE;
  734.  
  735.    /* check for '-' */
  736.    if (!Peek_Token(parseState, token))
  737.       RETURN_ERROR;
  738.    if (token[0] == '-') {
  739.       srcReg->Negate = NEGATE_XYZW;
  740.       (void) Parse_String(parseState, "-"); /* consume '-' */
  741.       if (!Peek_Token(parseState, token))
  742.          RETURN_ERROR;
  743.    }
  744.    else {
  745.       srcReg->Negate = NEGATE_NONE;
  746.    }
  747.  
  748.    /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
  749.    if (token[0] == 'R') {
  750.       srcReg->File = PROGRAM_TEMPORARY;
  751.       if (!Parse_TempReg(parseState, &idx))
  752.          RETURN_ERROR;
  753.       srcReg->Index = idx;
  754.    }
  755.    else if (token[0] == 'c') {
  756.       if (!Parse_ParamReg(parseState, srcReg))
  757.          RETURN_ERROR;
  758.    }
  759.    else if (token[0] == 'v') {
  760.       srcReg->File = PROGRAM_INPUT;
  761.       if (!Parse_AttribReg(parseState, &idx))
  762.          RETURN_ERROR;
  763.       srcReg->Index = idx;
  764.    }
  765.    else {
  766.       RETURN_ERROR2("Bad source register name", token);
  767.    }
  768.  
  769.    /* Look for .[xyzw] suffix */
  770.    if (!Parse_String(parseState, "."))
  771.       RETURN_ERROR;
  772.  
  773.    if (!Parse_Token(parseState, token))
  774.       RETURN_ERROR;
  775.  
  776.    if (token[0] == 'x' && token[1] == 0) {
  777.       srcReg->Swizzle = 0;
  778.    }
  779.    else if (token[0] == 'y' && token[1] == 0) {
  780.       srcReg->Swizzle = 1;
  781.    }
  782.    else if (token[0] == 'z' && token[1] == 0) {
  783.       srcReg->Swizzle = 2;
  784.    }
  785.    else if (token[0] == 'w' && token[1] == 0) {
  786.       srcReg->Swizzle = 3;
  787.    }
  788.    else {
  789.       RETURN_ERROR1("Bad scalar source suffix");
  790.    }
  791.  
  792.    return GL_TRUE;
  793. }
  794.  
  795.  
  796. static GLint
  797. Parse_UnaryOpInstruction(struct parse_state *parseState,
  798.                          struct prog_instruction *inst,
  799.                          enum prog_opcode opcode)
  800. {
  801.    if (opcode == OPCODE_ABS && !parseState->isVersion1_1)
  802.       RETURN_ERROR1("ABS illegal for vertex program 1.0");
  803.  
  804.    inst->Opcode = opcode;
  805.  
  806.    /* dest reg */
  807.    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
  808.       RETURN_ERROR;
  809.  
  810.    /* comma */
  811.    if (!Parse_String(parseState, ","))
  812.       RETURN_ERROR;
  813.  
  814.    /* src arg */
  815.    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
  816.       RETURN_ERROR;
  817.  
  818.    /* semicolon */
  819.    if (!Parse_String(parseState, ";"))
  820.       RETURN_ERROR;
  821.  
  822.    return GL_TRUE;
  823. }
  824.  
  825.  
  826. static GLboolean
  827. Parse_BiOpInstruction(struct parse_state *parseState,
  828.                       struct prog_instruction *inst,
  829.                       enum prog_opcode opcode)
  830. {
  831.    if (opcode == OPCODE_DPH && !parseState->isVersion1_1)
  832.       RETURN_ERROR1("DPH illegal for vertex program 1.0");
  833.    if (opcode == OPCODE_SUB && !parseState->isVersion1_1)
  834.       RETURN_ERROR1("SUB illegal for vertex program 1.0");
  835.  
  836.    inst->Opcode = opcode;
  837.  
  838.    /* dest reg */
  839.    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
  840.       RETURN_ERROR;
  841.  
  842.    /* comma */
  843.    if (!Parse_String(parseState, ","))
  844.       RETURN_ERROR;
  845.  
  846.    /* first src arg */
  847.    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
  848.       RETURN_ERROR;
  849.  
  850.    /* comma */
  851.    if (!Parse_String(parseState, ","))
  852.       RETURN_ERROR;
  853.  
  854.    /* second src arg */
  855.    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1]))
  856.       RETURN_ERROR;
  857.  
  858.    /* semicolon */
  859.    if (!Parse_String(parseState, ";"))
  860.       RETURN_ERROR;
  861.  
  862.    /* make sure we don't reference more than one program parameter register */
  863.    if (inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
  864.        inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
  865.        inst->SrcReg[0].Index != inst->SrcReg[1].Index)
  866.       RETURN_ERROR1("Can't reference two program parameter registers");
  867.  
  868.    /* make sure we don't reference more than one vertex attribute register */
  869.    if (inst->SrcReg[0].File == PROGRAM_INPUT &&
  870.        inst->SrcReg[1].File == PROGRAM_INPUT &&
  871.        inst->SrcReg[0].Index != inst->SrcReg[1].Index)
  872.       RETURN_ERROR1("Can't reference two vertex attribute registers");
  873.  
  874.    return GL_TRUE;
  875. }
  876.  
  877.  
  878. static GLboolean
  879. Parse_TriOpInstruction(struct parse_state *parseState,
  880.                        struct prog_instruction *inst,
  881.                        enum prog_opcode opcode)
  882. {
  883.    inst->Opcode = opcode;
  884.  
  885.    /* dest reg */
  886.    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
  887.       RETURN_ERROR;
  888.  
  889.    /* comma */
  890.    if (!Parse_String(parseState, ","))
  891.       RETURN_ERROR;
  892.  
  893.    /* first src arg */
  894.    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[0]))
  895.       RETURN_ERROR;
  896.  
  897.    /* comma */
  898.    if (!Parse_String(parseState, ","))
  899.       RETURN_ERROR;
  900.  
  901.    /* second src arg */
  902.    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[1]))
  903.       RETURN_ERROR;
  904.  
  905.    /* comma */
  906.    if (!Parse_String(parseState, ","))
  907.       RETURN_ERROR;
  908.  
  909.    /* third src arg */
  910.    if (!Parse_SwizzleSrcReg(parseState, &inst->SrcReg[2]))
  911.       RETURN_ERROR;
  912.  
  913.    /* semicolon */
  914.    if (!Parse_String(parseState, ";"))
  915.       RETURN_ERROR;
  916.  
  917.    /* make sure we don't reference more than one program parameter register */
  918.    if ((inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
  919.         inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
  920.         inst->SrcReg[0].Index != inst->SrcReg[1].Index) ||
  921.        (inst->SrcReg[0].File == PROGRAM_ENV_PARAM &&
  922.         inst->SrcReg[2].File == PROGRAM_ENV_PARAM &&
  923.         inst->SrcReg[0].Index != inst->SrcReg[2].Index) ||
  924.        (inst->SrcReg[1].File == PROGRAM_ENV_PARAM &&
  925.         inst->SrcReg[2].File == PROGRAM_ENV_PARAM &&
  926.         inst->SrcReg[1].Index != inst->SrcReg[2].Index))
  927.       RETURN_ERROR1("Can only reference one program register");
  928.  
  929.    /* make sure we don't reference more than one vertex attribute register */
  930.    if ((inst->SrcReg[0].File == PROGRAM_INPUT &&
  931.         inst->SrcReg[1].File == PROGRAM_INPUT &&
  932.         inst->SrcReg[0].Index != inst->SrcReg[1].Index) ||
  933.        (inst->SrcReg[0].File == PROGRAM_INPUT &&
  934.         inst->SrcReg[2].File == PROGRAM_INPUT &&
  935.         inst->SrcReg[0].Index != inst->SrcReg[2].Index) ||
  936.        (inst->SrcReg[1].File == PROGRAM_INPUT &&
  937.         inst->SrcReg[2].File == PROGRAM_INPUT &&
  938.         inst->SrcReg[1].Index != inst->SrcReg[2].Index))
  939.       RETURN_ERROR1("Can only reference one input register");
  940.  
  941.    return GL_TRUE;
  942. }
  943.  
  944.  
  945. static GLboolean
  946. Parse_ScalarInstruction(struct parse_state *parseState,
  947.                         struct prog_instruction *inst,
  948.                         enum prog_opcode opcode)
  949. {
  950.    if (opcode == OPCODE_RCC && !parseState->isVersion1_1)
  951.       RETURN_ERROR1("RCC illegal for vertex program 1.0");
  952.  
  953.    inst->Opcode = opcode;
  954.  
  955.    /* dest reg */
  956.    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
  957.       RETURN_ERROR;
  958.  
  959.    /* comma */
  960.    if (!Parse_String(parseState, ","))
  961.       RETURN_ERROR;
  962.  
  963.    /* first src arg */
  964.    if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
  965.       RETURN_ERROR;
  966.  
  967.    /* semicolon */
  968.    if (!Parse_String(parseState, ";"))
  969.       RETURN_ERROR;
  970.  
  971.    return GL_TRUE;
  972. }
  973.  
  974.  
  975. static GLboolean
  976. Parse_AddressInstruction(struct parse_state *parseState, struct prog_instruction *inst)
  977. {
  978.    inst->Opcode = OPCODE_ARL;
  979.  
  980.    /* Make ARB_vp backends happy */
  981.    inst->DstReg.File = PROGRAM_ADDRESS;
  982.    inst->DstReg.WriteMask = WRITEMASK_X;
  983.    inst->DstReg.Index = 0;
  984.  
  985.    /* dest A0 reg */
  986.    if (!Parse_AddrReg(parseState))
  987.       RETURN_ERROR;
  988.  
  989.    /* comma */
  990.    if (!Parse_String(parseState, ","))
  991.       RETURN_ERROR;
  992.  
  993.    /* parse src reg */
  994.    if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
  995.       RETURN_ERROR;
  996.  
  997.    /* semicolon */
  998.    if (!Parse_String(parseState, ";"))
  999.       RETURN_ERROR;
  1000.  
  1001.    return GL_TRUE;
  1002. }
  1003.  
  1004.  
  1005. static GLboolean
  1006. Parse_EndInstruction(struct parse_state *parseState, struct prog_instruction *inst)
  1007. {
  1008.    GLubyte token[100];
  1009.  
  1010.    inst->Opcode = OPCODE_END;
  1011.  
  1012.    /* this should fail! */
  1013.    if (Parse_Token(parseState, token))
  1014.       RETURN_ERROR2("Unexpected token after END:", token);
  1015.    else
  1016.       return GL_TRUE;
  1017. }
  1018.  
  1019.  
  1020. /**
  1021.  * The PRINT instruction is Mesa-specific and is meant as a debugging aid for
  1022.  * the vertex program developer.
  1023.  * The NV_vertex_program extension grammar is modified as follows:
  1024.  *
  1025.  *  <instruction>        ::= <ARL-instruction>
  1026.  *                         | ...
  1027.  *                         | <PRINT-instruction>
  1028.  *
  1029.  *  <PRINT-instruction>  ::= "PRINT" <string literal>
  1030.  *                         | "PRINT" <string literal> "," <srcReg>
  1031.  *                         | "PRINT" <string literal> "," <dstReg>
  1032.  */
  1033. static GLboolean
  1034. Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst)
  1035. {
  1036.    const GLubyte *str;
  1037.    GLubyte *msg;
  1038.    GLuint len;
  1039.    GLubyte token[100];
  1040.    struct prog_src_register *srcReg = &inst->SrcReg[0];
  1041.    GLint idx;
  1042.  
  1043.    inst->Opcode = OPCODE_PRINT;
  1044.  
  1045.    /* The first argument is a literal string 'just like this' */
  1046.    if (!Parse_String(parseState, "'"))
  1047.       RETURN_ERROR;
  1048.  
  1049.    str = parseState->pos;
  1050.    for (len = 0; str[len] != '\''; len++) /* find closing quote */
  1051.       ;
  1052.    parseState->pos += len + 1;
  1053.    msg = (GLubyte*) malloc(len + 1);
  1054.  
  1055.    memcpy(msg, str, len);
  1056.    msg[len] = 0;
  1057.    inst->Data = msg;
  1058.  
  1059.    /* comma */
  1060.    if (Parse_String(parseState, ",")) {
  1061.  
  1062.       /* The second argument is a register name */
  1063.       if (!Peek_Token(parseState, token))
  1064.          RETURN_ERROR;
  1065.  
  1066.       srcReg->RelAddr = GL_FALSE;
  1067.       srcReg->Negate = NEGATE_NONE;
  1068.       srcReg->Swizzle = SWIZZLE_NOOP;
  1069.  
  1070.       /* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib,
  1071.        * or an o[n] output register.
  1072.        */
  1073.       if (token[0] == 'R') {
  1074.          srcReg->File = PROGRAM_TEMPORARY;
  1075.          if (!Parse_TempReg(parseState, &idx))
  1076.             RETURN_ERROR;
  1077.          srcReg->Index = idx;
  1078.       }
  1079.       else if (token[0] == 'c') {
  1080.          srcReg->File = PROGRAM_ENV_PARAM;
  1081.          if (!Parse_ParamReg(parseState, srcReg))
  1082.             RETURN_ERROR;
  1083.       }
  1084.       else if (token[0] == 'v') {
  1085.          srcReg->File = PROGRAM_INPUT;
  1086.          if (!Parse_AttribReg(parseState, &idx))
  1087.             RETURN_ERROR;
  1088.          srcReg->Index = idx;
  1089.       }
  1090.       else if (token[0] == 'o') {
  1091.          srcReg->File = PROGRAM_OUTPUT;
  1092.          if (!Parse_OutputReg(parseState, &idx))
  1093.             RETURN_ERROR;
  1094.          srcReg->Index = idx;
  1095.       }
  1096.       else {
  1097.          RETURN_ERROR2("Bad source register name", token);
  1098.       }
  1099.    }
  1100.    else {
  1101.       srcReg->File = PROGRAM_UNDEFINED;
  1102.    }
  1103.  
  1104.    /* semicolon */
  1105.    if (!Parse_String(parseState, ";"))
  1106.       RETURN_ERROR;
  1107.  
  1108.    return GL_TRUE;
  1109. }
  1110.  
  1111.  
  1112. static GLboolean
  1113. Parse_OptionSequence(struct parse_state *parseState,
  1114.                      struct prog_instruction program[])
  1115. {
  1116.    (void) program;
  1117.    while (1) {
  1118.       if (!Parse_String(parseState, "OPTION"))
  1119.          return GL_TRUE;  /* ok, not an OPTION statement */
  1120.       if (Parse_String(parseState, "NV_position_invariant")) {
  1121.          parseState->isPositionInvariant = GL_TRUE;
  1122.       }
  1123.       else {
  1124.          RETURN_ERROR1("unexpected OPTION statement");
  1125.       }
  1126.       if (!Parse_String(parseState, ";"))
  1127.          return GL_FALSE;
  1128.    }
  1129. }
  1130.  
  1131.  
  1132. static GLboolean
  1133. Parse_InstructionSequence(struct parse_state *parseState,
  1134.                           struct prog_instruction program[])
  1135. {
  1136.    while (1) {
  1137.       struct prog_instruction *inst = program + parseState->numInst;
  1138.  
  1139.       /* Initialize the instruction */
  1140.       _mesa_init_instructions(inst, 1);
  1141.  
  1142.       if (Parse_String(parseState, "MOV")) {
  1143.          if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV))
  1144.             RETURN_ERROR;
  1145.       }
  1146.       else if (Parse_String(parseState, "LIT")) {
  1147.          if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT))
  1148.             RETURN_ERROR;
  1149.       }
  1150.       else if (Parse_String(parseState, "ABS")) {
  1151.          if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS))
  1152.             RETURN_ERROR;
  1153.       }
  1154.       else if (Parse_String(parseState, "MUL")) {
  1155.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL))
  1156.             RETURN_ERROR;
  1157.       }
  1158.       else if (Parse_String(parseState, "ADD")) {
  1159.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD))
  1160.             RETURN_ERROR;
  1161.       }
  1162.       else if (Parse_String(parseState, "DP3")) {
  1163.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3))
  1164.             RETURN_ERROR;
  1165.       }
  1166.       else if (Parse_String(parseState, "DP4")) {
  1167.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4))
  1168.             RETURN_ERROR;
  1169.       }
  1170.       else if (Parse_String(parseState, "DST")) {
  1171.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST))
  1172.             RETURN_ERROR;
  1173.       }
  1174.       else if (Parse_String(parseState, "MIN")) {
  1175.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN))
  1176.             RETURN_ERROR;
  1177.       }
  1178.       else if (Parse_String(parseState, "MAX")) {
  1179.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX))
  1180.             RETURN_ERROR;
  1181.       }
  1182.       else if (Parse_String(parseState, "SLT")) {
  1183.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT))
  1184.             RETURN_ERROR;
  1185.       }
  1186.       else if (Parse_String(parseState, "SGE")) {
  1187.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE))
  1188.             RETURN_ERROR;
  1189.       }
  1190.       else if (Parse_String(parseState, "DPH")) {
  1191.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH))
  1192.             RETURN_ERROR;
  1193.       }
  1194.       else if (Parse_String(parseState, "SUB")) {
  1195.          if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB))
  1196.             RETURN_ERROR;
  1197.       }
  1198.       else if (Parse_String(parseState, "MAD")) {
  1199.          if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD))
  1200.             RETURN_ERROR;
  1201.       }
  1202.       else if (Parse_String(parseState, "RCP")) {
  1203.          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP))
  1204.             RETURN_ERROR;
  1205.       }
  1206.       else if (Parse_String(parseState, "RSQ")) {
  1207.          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ))
  1208.             RETURN_ERROR;
  1209.       }
  1210.       else if (Parse_String(parseState, "EXP")) {
  1211.          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP))
  1212.             RETURN_ERROR;
  1213.       }
  1214.       else if (Parse_String(parseState, "LOG")) {
  1215.          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG))
  1216.             RETURN_ERROR;
  1217.       }
  1218.       else if (Parse_String(parseState, "RCC")) {
  1219.          if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCC))
  1220.             RETURN_ERROR;
  1221.       }
  1222.       else if (Parse_String(parseState, "ARL")) {
  1223.          if (!Parse_AddressInstruction(parseState, inst))
  1224.             RETURN_ERROR;
  1225.       }
  1226.       else if (Parse_String(parseState, "PRINT")) {
  1227.          if (!Parse_PrintInstruction(parseState, inst))
  1228.             RETURN_ERROR;
  1229.       }
  1230.       else if (Parse_String(parseState, "END")) {
  1231.          if (!Parse_EndInstruction(parseState, inst))
  1232.             RETURN_ERROR;
  1233.          else {
  1234.             parseState->numInst++;
  1235.             return GL_TRUE;  /* all done */
  1236.          }
  1237.       }
  1238.       else {
  1239.          /* bad instruction name */
  1240.          RETURN_ERROR1("Unexpected token");
  1241.       }
  1242.  
  1243.       /* examine input/output registers */
  1244.       if (inst->DstReg.File == PROGRAM_OUTPUT)
  1245.          parseState->outputsWritten |= (1 << inst->DstReg.Index);
  1246.       else if (inst->DstReg.File == PROGRAM_ENV_PARAM)
  1247.          parseState->anyProgRegsWritten = GL_TRUE;
  1248.  
  1249.       if (inst->SrcReg[0].File == PROGRAM_INPUT)
  1250.          parseState->inputsRead |= (1 << inst->SrcReg[0].Index);
  1251.       if (inst->SrcReg[1].File == PROGRAM_INPUT)
  1252.          parseState->inputsRead |= (1 << inst->SrcReg[1].Index);
  1253.       if (inst->SrcReg[2].File == PROGRAM_INPUT)
  1254.          parseState->inputsRead |= (1 << inst->SrcReg[2].Index);
  1255.  
  1256.       parseState->numInst++;
  1257.  
  1258.       if (parseState->numInst >= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
  1259.          RETURN_ERROR1("Program too long");
  1260.    }
  1261.  
  1262.    RETURN_ERROR;
  1263. }
  1264.  
  1265.  
  1266. static GLboolean
  1267. Parse_Program(struct parse_state *parseState,
  1268.               struct prog_instruction instBuffer[])
  1269. {
  1270.    if (parseState->isVersion1_1) {
  1271.       if (!Parse_OptionSequence(parseState, instBuffer)) {
  1272.          return GL_FALSE;
  1273.       }
  1274.    }
  1275.    return Parse_InstructionSequence(parseState, instBuffer);
  1276. }
  1277.  
  1278.  
  1279. /**
  1280.  * Parse/compile the 'str' returning the compiled 'program'.
  1281.  * ctx->Program.ErrorPos will be -1 if successful.  Otherwise, ErrorPos
  1282.  * indicates the position of the error in 'str'.
  1283.  */
  1284. void
  1285. _mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum dstTarget,
  1286.                               const GLubyte *str, GLsizei len,
  1287.                               struct gl_vertex_program *program)
  1288. {
  1289.    struct parse_state parseState;
  1290.    struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS];
  1291.    struct prog_instruction *newInst;
  1292.    GLenum target;
  1293.    GLubyte *programString;
  1294.  
  1295.    /* Make a null-terminated copy of the program string */
  1296.    programString = (GLubyte *) MALLOC(len + 1);
  1297.    if (!programString) {
  1298.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
  1299.       return;
  1300.    }
  1301.    memcpy(programString, str, len);
  1302.    programString[len] = 0;
  1303.  
  1304.    /* Get ready to parse */
  1305.    parseState.ctx = ctx;
  1306.    parseState.start = programString;
  1307.    parseState.isPositionInvariant = GL_FALSE;
  1308.    parseState.isVersion1_1 = GL_FALSE;
  1309.    parseState.numInst = 0;
  1310.    parseState.inputsRead = 0;
  1311.    parseState.outputsWritten = 0;
  1312.    parseState.anyProgRegsWritten = GL_FALSE;
  1313.    parseState.indirectRegisterFiles = 0x0;
  1314.  
  1315.    /* Reset error state */
  1316.    _mesa_set_program_error(ctx, -1, NULL);
  1317.  
  1318.    /* check the program header */
  1319.    if (strncmp((const char *) programString, "!!VP1.0", 7) == 0) {
  1320.       target = GL_VERTEX_PROGRAM_NV;
  1321.       parseState.pos = programString + 7;
  1322.       parseState.isStateProgram = GL_FALSE;
  1323.    }
  1324.    else if (strncmp((const char *) programString, "!!VP1.1", 7) == 0) {
  1325.       target = GL_VERTEX_PROGRAM_NV;
  1326.       parseState.pos = programString + 7;
  1327.       parseState.isStateProgram = GL_FALSE;
  1328.       parseState.isVersion1_1 = GL_TRUE;
  1329.    }
  1330.    else if (strncmp((const char *) programString, "!!VSP1.0", 8) == 0) {
  1331.       target = GL_VERTEX_STATE_PROGRAM_NV;
  1332.       parseState.pos = programString + 8;
  1333.       parseState.isStateProgram = GL_TRUE;
  1334.    }
  1335.    else {
  1336.       /* invalid header */
  1337.       ctx->Program.ErrorPos = 0;
  1338.       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
  1339.       return;
  1340.    }
  1341.  
  1342.    /* make sure target and header match */
  1343.    if (target != dstTarget) {
  1344.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1345.                   "glLoadProgramNV(target mismatch)");
  1346.       return;
  1347.    }
  1348.  
  1349.  
  1350.    if (Parse_Program(&parseState, instBuffer)) {
  1351.       gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
  1352.       int i;
  1353.  
  1354.       /* successful parse! */
  1355.  
  1356.       if (parseState.isStateProgram) {
  1357.          if (!parseState.anyProgRegsWritten) {
  1358.             _mesa_error(ctx, GL_INVALID_OPERATION,
  1359.                         "glLoadProgramNV(c[#] not written)");
  1360.             return;
  1361.          }
  1362.       }
  1363.       else {
  1364.          if (!parseState.isPositionInvariant &&
  1365.              !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) {
  1366.             /* bit 1 = HPOS register */
  1367.             _mesa_error(ctx, GL_INVALID_OPERATION,
  1368.                         "glLoadProgramNV(HPOS not written)");
  1369.             return;
  1370.          }
  1371.       }
  1372.  
  1373.       /* copy the compiled instructions */
  1374.       assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS);
  1375.       newInst = _mesa_alloc_instructions(parseState.numInst);
  1376.       if (!newInst) {
  1377.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
  1378.          free(programString);
  1379.          return;  /* out of memory */
  1380.       }
  1381.       _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);
  1382.  
  1383.       /* install the program */
  1384.       program->Base.Target = target;
  1385.       if (program->Base.String) {
  1386.          free(program->Base.String);
  1387.       }
  1388.       program->Base.String = programString;
  1389.       program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
  1390.       if (program->Base.Instructions) {
  1391.          free(program->Base.Instructions);
  1392.       }
  1393.       program->Base.Instructions = newInst;
  1394.       program->Base.InputsRead = parseState.inputsRead;
  1395.       if (parseState.isPositionInvariant)
  1396.          program->Base.InputsRead |= VERT_BIT_POS;
  1397.       program->Base.NumInstructions = parseState.numInst;
  1398.       program->Base.OutputsWritten = parseState.outputsWritten;
  1399.       program->IsPositionInvariant = parseState.isPositionInvariant;
  1400.       program->IsNVProgram = GL_TRUE;
  1401.  
  1402. #ifdef DEBUG_foo
  1403.       printf("--- glLoadProgramNV result ---\n");
  1404.       _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0);
  1405.       printf("------------------------------\n");
  1406. #endif
  1407.  
  1408.       if (program->Base.Parameters)
  1409.          _mesa_free_parameter_list(program->Base.Parameters);
  1410.  
  1411.       program->Base.Parameters = _mesa_new_parameter_list ();
  1412.       program->Base.NumParameters = 0;
  1413.  
  1414.       program->Base.IndirectRegisterFiles = parseState.indirectRegisterFiles;
  1415.  
  1416.       state_tokens[0] = STATE_VERTEX_PROGRAM;
  1417.       state_tokens[1] = STATE_ENV;
  1418.       /* Add refs to all of the potential params, in order.  If we want to not
  1419.        * upload everything, _mesa_layout_parameters is the answer.
  1420.        */
  1421.       for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS; i++) {
  1422.          GLint index;
  1423.          state_tokens[2] = i;
  1424.          index = _mesa_add_state_reference(program->Base.Parameters,
  1425.                                            state_tokens);
  1426.          assert(index == i);
  1427.       }
  1428.       program->Base.NumParameters = program->Base.Parameters->NumParameters;
  1429.  
  1430.       _mesa_setup_nv_temporary_count(ctx, &program->Base);
  1431.       _mesa_emit_nv_temp_initialization(ctx, &program->Base);
  1432.    }
  1433.    else {
  1434.       /* Error! */
  1435.       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
  1436.       /* NOTE: _mesa_set_program_error would have been called already */
  1437.       /* GL_NV_vertex_program isn't supposed to set the error string
  1438.        * so we reset it here.
  1439.        */
  1440.       _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL);
  1441.    }
  1442. }
  1443.  
  1444.  
  1445. const char *
  1446. _mesa_nv_vertex_input_register_name(GLuint i)
  1447. {
  1448.    ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS);
  1449.    return InputRegisters[i];
  1450. }
  1451.  
  1452.  
  1453. const char *
  1454. _mesa_nv_vertex_output_register_name(GLuint i)
  1455. {
  1456.    ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
  1457.    return OutputRegisters[i];
  1458. }
  1459.  
  1460.