Home | History | Annotate | Download | only in program
      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 	 (void)index;
   1428       }
   1429       program->Base.NumParameters = program->Base.Parameters->NumParameters;
   1430 
   1431       _mesa_setup_nv_temporary_count(&program->Base);
   1432       _mesa_emit_nv_temp_initialization(ctx, &program->Base);
   1433    }
   1434    else {
   1435       /* Error! */
   1436       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
   1437       /* NOTE: _mesa_set_program_error would have been called already */
   1438       /* GL_NV_vertex_program isn't supposed to set the error string
   1439        * so we reset it here.
   1440        */
   1441       _mesa_set_program_error(ctx, ctx->Program.ErrorPos, NULL);
   1442    }
   1443 }
   1444 
   1445 
   1446 const char *
   1447 _mesa_nv_vertex_input_register_name(GLuint i)
   1448 {
   1449    ASSERT(i < MAX_NV_VERTEX_PROGRAM_INPUTS);
   1450    return InputRegisters[i];
   1451 }
   1452 
   1453 
   1454 const char *
   1455 _mesa_nv_vertex_output_register_name(GLuint i)
   1456 {
   1457    ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
   1458    return OutputRegisters[i];
   1459 }
   1460 
   1461