home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / vpparse.cpp < prev    next >
C/C++ Source or Header  |  2002-12-15  |  44KB  |  1,633 lines

  1. /* $Id: vpparse.c,v 1.15 2002/11/27 03:40:13 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27. /*
  28.  * -------- Regarding NV_vertex_program --------
  29.  * Redistribution and use in source and binary forms, with or without
  30.  * modification, are permitted provided that the following conditions are met:
  31.  *
  32.  * o Redistribution of the source code must contain a copyright notice
  33.  *   and this list of conditions;
  34.  *
  35.  * o Redistribution in binary and source code form must contain the
  36.  *   following Notice in the software and any documentation and/or other
  37.  *   materials provided with the distribution; and
  38.  *
  39.  * o The name of Nvidia may not be used to promote or endorse software
  40.  *   derived from the software.
  41.  *
  42.  * NOTICE: Nvidia hereby grants to each recipient a non-exclusive worldwide
  43.  * royalty free patent license under patent claims that are licensable by
  44.  * Nvidia and which are necessarily required and for which no commercially
  45.  * viable non infringing alternative exists to make, use, sell, offer to sell,
  46.  * import and otherwise transfer the vertex extension for the Mesa 3D Graphics
  47.  * Library as distributed in source code and object code form.  No hardware or
  48.  * hardware implementation (including a semiconductor implementation and chips)
  49.  * are licensed hereunder. If a recipient makes a patent claim or institutes
  50.  * patent litigation against Nvidia or Nvidia's customers for use or sale of
  51.  * Nvidia products, then this license grant as to such recipient shall
  52.  * immediately terminate and recipient immediately agrees to cease use and
  53.  * distribution of the Mesa Program and derivatives thereof.
  54.  *
  55.  * THE MESA 3D GRAPHICS LIBRARY IS PROVIDED ON AN "AS IS BASIS, WITHOUT
  56.  * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
  57.  * WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-NFRINGEMENT
  58.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  59.  *
  60.  * NVIDIA SHALL NOT HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  61.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
  62.  * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  63.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  64.  * ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE MESA 3D GRAPHICS
  65.  * LIBRARY OR EVIDENCE OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDR, EVEN
  66.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  67.  *
  68.  * If you do not comply with this agreement, then Nvidia may cancel the license
  69.  * and rights granted herein.
  70.  * ---------------------------------------------
  71.  */
  72.  
  73. /**
  74.  * \file vpparse.c
  75.  * \brief Vertex program parser.
  76.  * \author Brian Paul
  77.  */
  78.  
  79.  
  80. #include "glheader.h"
  81. #include "context.h"
  82. #include "hash.h"
  83. #include "imports.h"
  84. #include "macros.h"
  85. #include "mtypes.h"
  86. #include "vpparse.h"
  87.  
  88.  
  89.  
  90. /************************ Symbol Table ******************************/
  91.  
  92. /* A simple symbol table implementation for ARB_vertex_program
  93.  * (not used yet)
  94.  */
  95.  
  96. #if 000
  97. struct symbol
  98. {
  99.    GLubyte *name;
  100.    GLint value;
  101.    struct symbol *next;
  102. };
  103.  
  104. static struct symbol *SymbolTable = NULL;
  105.  
  106. static GLboolean
  107. IsSymbol(const GLubyte *symbol)
  108. {
  109.    struct symbol *s;
  110.    for (s = SymbolTable; s; s = s->next) {
  111.       if (strcmp((char *) symbol, (char *)s->name) == 0)
  112.          return GL_TRUE;
  113.    }
  114.    return GL_FALSE;
  115. }
  116.  
  117. static GLint
  118. GetSymbolValue(const GLubyte *symbol)
  119. {
  120.    struct symbol *s;
  121.    for (s = SymbolTable; s; s = s->next) {
  122.       if (strcmp((char *) symbol, (char *)s->name) == 0)
  123.          return s->value;
  124.    }
  125.    return 0;
  126. }
  127.  
  128. static void
  129. AddSymbol(const GLubyte *symbol, GLint value)
  130. {
  131.    struct symbol *s = MALLOC_STRUCT(symbol);
  132.    if (s) {
  133.       s->name = (GLubyte *) strdup((char *) symbol);
  134.       s->value = value;
  135.       s->next = SymbolTable;
  136.       SymbolTable = s;
  137.    }
  138. }
  139.  
  140. static void
  141. ResetSymbolTable(void)
  142. {
  143.    struct symbol *s, *next;
  144.    for (s = SymbolTable; s; s = next) {
  145.       next = s->next;
  146.       FREE(s->name);
  147.       FREE(s);
  148.       s = next;
  149.    }
  150.    SymbolTable = NULL;
  151. }
  152. #endif
  153.  
  154. /***************************** Parsing ******************************/
  155.  
  156.  
  157. static GLboolean IsLetter(GLubyte b)
  158. {
  159.    return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z');
  160. }
  161.  
  162.  
  163. static GLboolean IsDigit(GLubyte b)
  164. {
  165.    return b >= '0' && b <= '9';
  166. }
  167.  
  168.  
  169. static GLboolean IsWhitespace(GLubyte b)
  170. {
  171.    return b == ' ' || b == '\t' || b == '\n' || b == '\r';
  172. }
  173.  
  174.  
  175. /**
  176.  * Starting at 'str' find the next token.  A token can be an integer,
  177.  * an identifier or punctuation symbol.
  178.  * \return <= 0 we found an error, else, return number of characters parsed.
  179.  */
  180. static GLint
  181. GetToken(const GLubyte *str, GLubyte *token)
  182. {
  183.    GLint i = 0, j = 0;
  184.  
  185.    token[0] = 0;
  186.  
  187.    /* skip whitespace and comments */
  188.    while (str[i] && (IsWhitespace(str[i]) || str[i] == '#')) {
  189.       if (str[i] == '#') {
  190.          /* skip comment */
  191.          while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
  192.             i++;
  193.          }
  194.       }
  195.       else {
  196.          /* skip whitespace */
  197.          i++;
  198.       }
  199.    }
  200.  
  201.    if (str[i] == 0)
  202.       return -i;
  203.  
  204.    /* try matching an integer */
  205.    while (str[i] && IsDigit(str[i])) {
  206.       token[j++] = str[i++];
  207.    }
  208.    if (j > 0 || !str[i]) {
  209.       token[j] = 0;
  210.       return i;
  211.    }
  212.  
  213.    /* try matching an identifier */
  214.    if (IsLetter(str[i])) {
  215.       while (str[i] && (IsLetter(str[i]) || IsDigit(str[i]))) {
  216.          token[j++] = str[i++];
  217.       }
  218.       token[j] = 0;
  219.       return i;
  220.    }
  221.  
  222.    /* punctuation */
  223.    if (str[i]) {
  224.       token[0] = str[i++];
  225.       token[1] = 0;
  226.       return i;
  227.    }
  228.  
  229.    /* end of input */
  230.    token[0] = 0;
  231.    return i;
  232. }
  233.  
  234.  
  235. /**
  236.  * Get next token from input stream and increment stream pointer past token.
  237.  */
  238. static GLboolean
  239. Parse_Token(const GLubyte **s, GLubyte *token)
  240. {
  241.    GLint i;
  242.    i = GetToken(*s, token);
  243.    if (i <= 0) {
  244.       *s += (-i);
  245.       return GL_FALSE;
  246.    }
  247.    *s += i;
  248.    return GL_TRUE;
  249. }
  250.  
  251.  
  252. /**
  253.  * Get next token from input stream but don't increment stream pointer.
  254.  */
  255. static GLboolean
  256. Peek_Token(const GLubyte **s, GLubyte *token)
  257. {
  258.    GLint i, len;
  259.    i = GetToken(*s, token);
  260.    if (i <= 0) {
  261.       *s += (-i);
  262.       return GL_FALSE;
  263.    }
  264.    len = _mesa_strlen((char *) token);
  265.    *s += (i - len);
  266.    return GL_TRUE;
  267. }
  268.  
  269.  
  270. /**
  271.  * String equality test
  272.  */
  273. static GLboolean
  274. StrEq(const GLubyte *a, const GLubyte *b)
  275. {
  276.    GLint i;
  277.    for (i = 0; a[i] && b[i] && a[i] == b[i]; i++)
  278.       ;
  279.    if (a[i] == 0 && b[i] == 0)
  280.       return GL_TRUE;
  281.    else
  282.       return GL_FALSE;
  283. }
  284.  
  285.  
  286. /**********************************************************************/
  287.  
  288. static const char *InputRegisters[] = {
  289.    "OPOS", "WGHT", "NRML", "COL0", "COL1", "FOGC", "6", "7",
  290.    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
  291. };
  292.  
  293. static const char *OutputRegisters[] = {
  294.    "HPOS", "COL0", "COL1", "BFC0", "BFC1", "FOGC", "PSIZ",
  295.    "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
  296. };
  297.  
  298. static const char *Opcodes[] = {
  299.    "MOV", "LIT", "RCP", "RSQ", "EXP", "LOG", "MUL", "ADD", "DP3", "DP4",
  300.    "DST", "MIN", "MAX", "SLT", "SGE", "MAD", "ARL", "DPH", "RCC", "SUB",
  301.    "ABS", "END", NULL
  302. };
  303.  
  304.  
  305. #ifdef DEBUG
  306.  
  307. #define PARSE_ERROR                                            \
  308. do {                                                           \
  309.    _mesa_printf("vpparse.c error at %d: parse error\n", __LINE__);     \
  310.    return GL_FALSE;                                            \
  311. } while(0)
  312.  
  313. #define PARSE_ERROR1(msg)                                      \
  314. do {                                                           \
  315.    _mesa_printf("vpparse.c error at %d: %s\n", __LINE__, msg); \
  316.    return GL_FALSE;                                            \
  317. } while(0)
  318.  
  319. #define PARSE_ERROR2(msg1, msg2)                                       \
  320. do {                                                                   \
  321.    _mesa_printf("vpparse.c error at %d: %s %s\n", __LINE__, msg1, msg2);       \
  322.    return GL_FALSE;                                                    \
  323. } while(0)
  324.  
  325. #else
  326.  
  327. #define PARSE_ERROR                return GL_FALSE
  328. #define PARSE_ERROR1(msg1)         return GL_FALSE
  329. #define PARSE_ERROR2(msg1, msg2)   return GL_FALSE
  330.  
  331. #endif
  332.  
  333.  
  334. static GLuint
  335. IsProgRegister(GLuint r)
  336. {
  337.    return (GLuint) (r >= VP_PROG_REG_START && r <= VP_PROG_REG_END);
  338. }
  339.  
  340. static GLuint
  341. IsInputRegister(GLuint r)
  342. {
  343.    return (GLuint) (r >= VP_INPUT_REG_START && r <= VP_INPUT_REG_END);
  344. }
  345.  
  346. static GLuint
  347. IsOutputRegister(GLuint r)
  348. {
  349.    return (GLuint) (r >= VP_OUTPUT_REG_START && r <= VP_OUTPUT_REG_END);
  350. }
  351.  
  352.  
  353.  
  354. /**********************************************************************/
  355.  
  356. /* XXX
  357.  * These shouldn't be globals as that makes the parser non-reentrant.
  358.  * We should really define a "ParserContext" class which contains these
  359.  * and the <s> pointer into the program text.
  360.  */
  361. static GLboolean IsStateProgram = GL_FALSE;
  362. static GLboolean IsPositionInvariant = GL_FALSE;
  363. static GLboolean IsVersion1_1 = GL_FALSE;
  364.  
  365. /**
  366.  * Try to match 'pattern' as the next token after any whitespace/comments.
  367.  */
  368. static GLboolean
  369. Parse_String(const GLubyte **s, const char *pattern)
  370. {
  371.    GLint i;
  372.  
  373.    /* skip whitespace and comments */
  374.    while (IsWhitespace(**s) || **s == '#') {
  375.       if (**s == '#') {
  376.          while (**s && (**s != '\n' && **s != '\r')) {
  377.             *s += 1;
  378.          }
  379.       }
  380.       else {
  381.          /* skip whitespace */
  382.          *s += 1;
  383.       }
  384.    }
  385.  
  386.    /* Try to match the pattern */
  387.    for (i = 0; pattern[i]; i++) {
  388.       if (**s != pattern[i])
  389.          PARSE_ERROR2("failed to match", pattern); /* failure */
  390.       *s += 1;
  391.    }
  392.  
  393.    return GL_TRUE; /* success */
  394. }
  395.  
  396.  
  397. /**
  398.  * Parse a temporary register: Rnn
  399.  */
  400. static GLboolean
  401. Parse_TempReg(const GLubyte **s, GLint *tempRegNum)
  402. {
  403.    GLubyte token[100];
  404.  
  405.    /* Should be 'R##' */
  406.    if (!Parse_Token(s, token))
  407.       PARSE_ERROR;
  408.    if (token[0] != 'R')
  409.       PARSE_ERROR1("Expected R##");
  410.  
  411.    if (IsDigit(token[1])) {
  412.       GLint reg = _mesa_atoi((char *) (token + 1));
  413.       if (reg >= VP_NUM_TEMP_REGS)
  414.          PARSE_ERROR1("Bad temporary register name");
  415.       *tempRegNum = VP_TEMP_REG_START + reg;
  416.    }
  417.    else {
  418.       PARSE_ERROR1("Bad temporary register name");
  419.    }
  420.  
  421.    return GL_TRUE;
  422. }
  423.  
  424.  
  425. /**
  426.  * Parse address register "A0.x"
  427.  */
  428. static GLboolean
  429. Parse_AddrReg(const GLubyte **s)
  430. {
  431.    /* match 'A0' */
  432.    if (!Parse_String(s, "A0"))
  433.       PARSE_ERROR;
  434.  
  435.    /* match '.' */
  436.    if (!Parse_String(s, "."))
  437.       PARSE_ERROR;
  438.  
  439.    /* match 'x' */
  440.    if (!Parse_String(s, "x"))
  441.       PARSE_ERROR;
  442.  
  443.    return GL_TRUE;
  444. }
  445.  
  446.  
  447. /**
  448.  * Parse absolute program parameter register "c[##]"
  449.  */
  450. static GLboolean
  451. Parse_AbsParamReg(const GLubyte **s, GLint *regNum)
  452. {
  453.    GLubyte token[100];
  454.  
  455.    if (!Parse_String(s, "c"))
  456.       PARSE_ERROR;
  457.  
  458.    if (!Parse_String(s, "["))
  459.       PARSE_ERROR;
  460.  
  461.    if (!Parse_Token(s, token))
  462.       PARSE_ERROR;
  463.  
  464.    if (IsDigit(token[0])) {
  465.       /* a numbered program parameter register */
  466.       GLint reg = _mesa_atoi((char *) token);
  467.       if (reg >= VP_NUM_PROG_REGS)
  468.          PARSE_ERROR1("Bad constant program number");
  469.       *regNum = VP_PROG_REG_START + reg;
  470.    }
  471.    else {
  472.       PARSE_ERROR;
  473.    }
  474.  
  475.    if (!Parse_String(s, "]"))
  476.       PARSE_ERROR;
  477.  
  478.    return GL_TRUE;
  479. }
  480.  
  481.  
  482. static GLboolean
  483. Parse_ParamReg(const GLubyte **s, struct vp_src_register *srcReg)
  484. {
  485.    GLubyte token[100];
  486.  
  487.    if (!Parse_String(s, "c"))
  488.       PARSE_ERROR;
  489.  
  490.    if (!Parse_String(s, "["))
  491.       PARSE_ERROR;
  492.  
  493.    if (!Peek_Token(s, token))
  494.       PARSE_ERROR;
  495.  
  496.    if (IsDigit(token[0])) {
  497.       /* a numbered program parameter register */
  498.       GLint reg;
  499.       (void) Parse_Token(s, token);
  500.       reg = _mesa_atoi((char *) token);
  501.       if (reg >= VP_NUM_PROG_REGS)
  502.          PARSE_ERROR1("Bad constant program number");
  503.       srcReg->Register = VP_PROG_REG_START + reg;
  504.    }
  505.    else if (StrEq(token, (GLubyte *) "A0")) {
  506.       /* address register "A0.x" */
  507.       if (!Parse_AddrReg(s))
  508.          PARSE_ERROR;
  509.  
  510.       srcReg->RelAddr = GL_TRUE;
  511.       srcReg->Register = 0;
  512.  
  513.       /* Look for +/-N offset */
  514.       if (!Peek_Token(s, token))
  515.          PARSE_ERROR;
  516.  
  517.       if (token[0] == '-' || token[0] == '+') {
  518.          const GLubyte sign = token[0];
  519.          (void) Parse_Token(s, token); /* consume +/- */
  520.  
  521.          /* an integer should be next */
  522.          if (!Parse_Token(s, token))
  523.             PARSE_ERROR;
  524.  
  525.          if (IsDigit(token[0])) {
  526.             const GLint k = _mesa_atoi((char *) token);
  527.             if (sign == '-') {
  528.                if (k > 64)
  529.                   PARSE_ERROR1("Bad address offset");
  530.                srcReg->Register = -k;
  531.             }
  532.             else {
  533.                if (k > 63)
  534.                   PARSE_ERROR1("Bad address offset");
  535.                srcReg->Register = k;
  536.             }
  537.          }
  538.          else {
  539.             PARSE_ERROR;
  540.          }
  541.       }
  542.       else {
  543.          /* probably got a ']', catch it below */
  544.       }
  545.    }
  546.    else {
  547.       PARSE_ERROR;
  548.    }
  549.  
  550.    /* Match closing ']' */
  551.    if (!Parse_String(s, "]"))
  552.       PARSE_ERROR;
  553.  
  554.    return GL_TRUE;
  555. }
  556.  
  557.  
  558. /**
  559.  * Parse v[#] or v[<name>]
  560.  */
  561. static GLboolean
  562. Parse_AttribReg(const GLubyte **s, GLint *tempRegNum)
  563. {
  564.    GLubyte token[100];
  565.    GLint j;
  566.  
  567.    /* Match 'v' */
  568.    if (!Parse_String(s, "v"))
  569.       PARSE_ERROR;
  570.  
  571.    /* Match '[' */
  572.    if (!Parse_String(s, "["))
  573.       PARSE_ERROR;
  574.  
  575.    /* match number or named register */
  576.    if (!Parse_Token(s, token))
  577.       PARSE_ERROR;
  578.  
  579.    if (IsStateProgram && token[0] != '0')
  580.       PARSE_ERROR1("Only v[0] accessible in vertex state programs");
  581.  
  582.    if (IsDigit(token[0])) {
  583.       GLint reg = _mesa_atoi((char *) token);
  584.       if (reg >= VP_NUM_INPUT_REGS)
  585.          PARSE_ERROR1("Bad vertex attribute register name");
  586.       *tempRegNum = VP_INPUT_REG_START + reg;
  587.    }
  588.    else {
  589.       for (j = 0; InputRegisters[j]; j++) {
  590.          if (StrEq(token, (const GLubyte *) InputRegisters[j])) {
  591.             *tempRegNum = VP_INPUT_REG_START + j;
  592.             break;
  593.          }
  594.       }
  595.       if (!InputRegisters[j]) {
  596.          /* unknown input register label */
  597.          PARSE_ERROR2("Bad register name", token);
  598.       }
  599.    }
  600.  
  601.    /* Match '[' */
  602.    if (!Parse_String(s, "]"))
  603.       PARSE_ERROR;
  604.  
  605.    return GL_TRUE;
  606. }
  607.  
  608.  
  609. static GLboolean
  610. Parse_OutputReg(const GLubyte **s, GLint *outputRegNum)
  611. {
  612.    GLubyte token[100];
  613.    GLint start, j;
  614.  
  615.    /* Match 'o' */
  616.    if (!Parse_String(s, "o"))
  617.       PARSE_ERROR;
  618.  
  619.    /* Match '[' */
  620.    if (!Parse_String(s, "["))
  621.       PARSE_ERROR;
  622.  
  623.    /* Get output reg name */
  624.    if (!Parse_Token(s, token))
  625.       PARSE_ERROR;
  626.  
  627.    if (IsPositionInvariant)
  628.       start = 1; /* skip HPOS register name */
  629.    else
  630.       start = 0;
  631.  
  632.    /* try to match an output register name */
  633.    for (j = start; OutputRegisters[j]; j++) {
  634.       if (StrEq(token, (const GLubyte *) OutputRegisters[j])) {
  635.          *outputRegNum = VP_OUTPUT_REG_START + j;
  636.          break;
  637.       }
  638.    }
  639.    if (!OutputRegisters[j])
  640.       PARSE_ERROR1("Unrecognized output register name");
  641.  
  642.    /* Match ']' */
  643.    if (!Parse_String(s, "]"))
  644.       PARSE_ERROR1("Expected ]");
  645.  
  646.    return GL_TRUE;
  647. }
  648.  
  649.  
  650. static GLboolean
  651. Parse_MaskedDstReg(const GLubyte **s, struct vp_dst_register *dstReg)
  652. {
  653.    GLubyte token[100];
  654.  
  655.    /* Dst reg can be R<n> or o[n] */
  656.    if (!Peek_Token(s, token))
  657.       PARSE_ERROR;
  658.  
  659.    if (token[0] == 'R') {
  660.       /* a temporary register */
  661.       if (!Parse_TempReg(s, &dstReg->Register))
  662.          PARSE_ERROR;
  663.    }
  664.    else if (!IsStateProgram && token[0] == 'o') {
  665.       /* an output register */
  666.       if (!Parse_OutputReg(s, &dstReg->Register))
  667.          PARSE_ERROR;
  668.    }
  669.    else if (IsStateProgram && token[0] == 'c') {
  670.       /* absolute program parameter register */
  671.       if (!Parse_AbsParamReg(s, &dstReg->Register))
  672.          PARSE_ERROR;
  673.    }
  674.    else {
  675.       PARSE_ERROR1("Bad destination register name");
  676.    }
  677.  
  678.    /* Parse optional write mask */
  679.    if (!Peek_Token(s, token))
  680.       PARSE_ERROR;
  681.  
  682.    if (token[0] == '.') {
  683.       /* got a mask */
  684.       GLint k = 0;
  685.  
  686.       if (!Parse_String(s, "."))
  687.          PARSE_ERROR;
  688.  
  689.       if (!Parse_Token(s, token))
  690.          PARSE_ERROR;
  691.  
  692.       dstReg->WriteMask[0] = GL_FALSE;
  693.       dstReg->WriteMask[1] = GL_FALSE;
  694.       dstReg->WriteMask[2] = GL_FALSE;
  695.       dstReg->WriteMask[3] = GL_FALSE;
  696.  
  697.       if (token[k] == 'x') {
  698.          dstReg->WriteMask[0] = GL_TRUE;
  699.          k++;
  700.       }
  701.       if (token[k] == 'y') {
  702.          dstReg->WriteMask[1] = GL_TRUE;
  703.          k++;
  704.       }
  705.       if (token[k] == 'z') {
  706.          dstReg->WriteMask[2] = GL_TRUE;
  707.          k++;
  708.       }
  709.       if (token[k] == 'w') {
  710.          dstReg->WriteMask[3] = GL_TRUE;
  711.          k++;
  712.       }
  713.       if (k == 0) {
  714.          PARSE_ERROR1("Bad writemask character");
  715.       }
  716.       return GL_TRUE;
  717.    }
  718.    else {
  719.       dstReg->WriteMask[0] = GL_TRUE;
  720.       dstReg->WriteMask[1] = GL_TRUE;
  721.       dstReg->WriteMask[2] = GL_TRUE;
  722.       dstReg->WriteMask[3] = GL_TRUE;
  723.       return GL_TRUE;
  724.    }
  725. }
  726.  
  727.  
  728. static GLboolean
  729. Parse_SwizzleSrcReg(const GLubyte **s, struct vp_src_register *srcReg)
  730. {
  731.    GLubyte token[100];
  732.  
  733.    srcReg->RelAddr = GL_FALSE;
  734.  
  735.    /* check for '-' */
  736.    if (!Peek_Token(s, token))
  737.       PARSE_ERROR;
  738.    if (token[0] == '-') {
  739.       (void) Parse_String(s, "-");
  740.       srcReg->Negate = GL_TRUE;
  741.       if (!Peek_Token(s, token))
  742.          PARSE_ERROR;
  743.    }
  744.    else {
  745.       srcReg->Negate = GL_FALSE;
  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.       if (!Parse_TempReg(s, &srcReg->Register))
  751.          PARSE_ERROR;
  752.    }
  753.    else if (token[0] == 'c') {
  754.       if (!Parse_ParamReg(s, srcReg))
  755.          PARSE_ERROR;
  756.    }
  757.    else if (token[0] == 'v') {
  758.       if (!Parse_AttribReg(s, &srcReg->Register))
  759.          PARSE_ERROR;
  760.    }
  761.    else {
  762.       PARSE_ERROR2("Bad source register name", token);
  763.    }
  764.  
  765.    /* init swizzle fields */
  766.    srcReg->Swizzle[0] = 0;
  767.    srcReg->Swizzle[1] = 1;
  768.    srcReg->Swizzle[2] = 2;
  769.    srcReg->Swizzle[3] = 3;
  770.  
  771.    /* Look for optional swizzle suffix */
  772.    if (!Peek_Token(s, token))
  773.       PARSE_ERROR;
  774.    if (token[0] == '.') {
  775.       (void) Parse_String(s, ".");  /* consume . */
  776.  
  777.       if (!Parse_Token(s, token))
  778.          PARSE_ERROR;
  779.  
  780.       if (token[1] == 0) {
  781.          /* single letter swizzle */
  782.          if (token[0] == 'x')
  783.             ASSIGN_4V(srcReg->Swizzle, 0, 0, 0, 0)
  784.          else if (token[0] == 'y')
  785.             ASSIGN_4V(srcReg->Swizzle, 1, 1, 1, 1)
  786.          else if (token[0] == 'z')
  787.             ASSIGN_4V(srcReg->Swizzle, 2, 2, 2, 2)
  788.          else if (token[0] == 'w')
  789.             ASSIGN_4V(srcReg->Swizzle, 3, 3, 3, 3)
  790.          else
  791.             PARSE_ERROR1("Expected x, y, z, or w");
  792.       }
  793.       else {
  794.          /* 2, 3 or 4-component swizzle */
  795.          GLint k;
  796.          for (k = 0; token[k] && k < 5; k++) {
  797.             if (token[k] == 'x')
  798.                srcReg->Swizzle[k] = 0;
  799.             else if (token[k] == 'y')
  800.                srcReg->Swizzle[k] = 1;
  801.             else if (token[k] == 'z')
  802.                srcReg->Swizzle[k] = 2;
  803.             else if (token[k] == 'w')
  804.                srcReg->Swizzle[k] = 3;
  805.             else
  806.                PARSE_ERROR;
  807.          }
  808.          if (k >= 5)
  809.             PARSE_ERROR;
  810.       }
  811.    }
  812.  
  813.    return GL_TRUE;
  814. }
  815.  
  816.  
  817. static GLboolean
  818. Parse_ScalarSrcReg(const GLubyte **s, struct vp_src_register *srcReg)
  819. {
  820.    GLubyte token[100];
  821.  
  822.    srcReg->RelAddr = GL_FALSE;
  823.  
  824.    /* check for '-' */
  825.    if (!Peek_Token(s, token))
  826.       PARSE_ERROR;
  827.    if (token[0] == '-') {
  828.       srcReg->Negate = GL_TRUE;
  829.       (void) Parse_String(s, "-"); /* consume '-' */
  830.       if (!Peek_Token(s, token))
  831.          PARSE_ERROR;
  832.    }
  833.    else {
  834.       srcReg->Negate = GL_FALSE;
  835.    }
  836.  
  837.    /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
  838.    if (token[0] == 'R') {
  839.       if (!Parse_TempReg(s, &srcReg->Register))
  840.          PARSE_ERROR;
  841.    }
  842.    else if (token[0] == 'c') {
  843.       if (!Parse_ParamReg(s, srcReg))
  844.          PARSE_ERROR;
  845.    }
  846.    else if (token[0] == 'v') {
  847.       if (!Parse_AttribReg(s, &srcReg->Register))
  848.          PARSE_ERROR;
  849.    }
  850.    else {
  851.       PARSE_ERROR2("Bad source register name", token);
  852.    }
  853.  
  854.    /* Look for .[xyzw] suffix */
  855.    if (!Parse_String(s, "."))
  856.       PARSE_ERROR;
  857.  
  858.    if (!Parse_Token(s, token))
  859.       PARSE_ERROR;
  860.  
  861.    if (token[0] == 'x' && token[1] == 0) {
  862.       srcReg->Swizzle[0] = 0;
  863.    }
  864.    else if (token[0] == 'y' && token[1] == 0) {
  865.       srcReg->Swizzle[0] = 1;
  866.    }
  867.    else if (token[0] == 'z' && token[1] == 0) {
  868.       srcReg->Swizzle[0] = 2;
  869.    }
  870.    else if (token[0] == 'w' && token[1] == 0) {
  871.       srcReg->Swizzle[0] = 3;
  872.    }
  873.    else {
  874.       PARSE_ERROR1("Bad scalar source suffix");
  875.    }
  876.    srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;
  877.  
  878.    return GL_TRUE;
  879. }
  880.  
  881.  
  882. static GLint
  883. Parse_UnaryOpInstruction(const GLubyte **s, struct vp_instruction *inst)
  884. {
  885.    GLubyte token[100];
  886.  
  887.    /* opcode */
  888.    if (!Parse_Token(s, token))
  889.       PARSE_ERROR;
  890.  
  891.    if (StrEq(token, (GLubyte *) "MOV")) {
  892.       inst->Opcode = MOV;
  893.    }
  894.    else if (StrEq(token, (GLubyte *) "LIT")) {
  895.       inst->Opcode = LIT;
  896.    }
  897.    else if (StrEq(token, (GLubyte *) "ABS") && IsVersion1_1) {
  898.       inst->Opcode = ABS;
  899.    }
  900.    else {
  901.       PARSE_ERROR;
  902.    }
  903.  
  904.    /* dest reg */
  905.    if (!Parse_MaskedDstReg(s, &inst->DstReg))
  906.       PARSE_ERROR;
  907.  
  908.    /* comma */
  909.    if (!Parse_String(s, ","))
  910.       PARSE_ERROR;
  911.  
  912.    /* src arg */
  913.    if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
  914.       PARSE_ERROR;
  915.  
  916.    /* semicolon */
  917.    if (!Parse_String(s, ";"))
  918.       PARSE_ERROR;
  919.  
  920.    return GL_TRUE;
  921. }
  922.  
  923.  
  924. static GLboolean
  925. Parse_BiOpInstruction(const GLubyte **s, struct vp_instruction *inst)
  926. {
  927.    GLubyte token[100];
  928.  
  929.    /* opcode */
  930.    if (!Parse_Token(s, token))
  931.       PARSE_ERROR;
  932.  
  933.    if (StrEq(token, (GLubyte *) "MUL")) {
  934.       inst->Opcode = MUL;
  935.    }
  936.    else if (StrEq(token, (GLubyte *) "ADD")) {
  937.       inst->Opcode = ADD;
  938.    }
  939.    else if (StrEq(token, (GLubyte *) "DP3")) {
  940.       inst->Opcode = DP3;
  941.    }
  942.    else if (StrEq(token, (GLubyte *) "DP4")) {
  943.       inst->Opcode = DP4;
  944.    }
  945.    else if (StrEq(token, (GLubyte *) "DST")) {
  946.       inst->Opcode = DST;
  947.    }
  948.    else if (StrEq(token, (GLubyte *) "MIN")) {
  949.       inst->Opcode = ADD;
  950.    }
  951.    else if (StrEq(token, (GLubyte *) "MAX")) {
  952.       inst->Opcode = ADD;
  953.    }
  954.    else if (StrEq(token, (GLubyte *) "SLT")) {
  955.       inst->Opcode = SLT;
  956.    }
  957.    else if (StrEq(token, (GLubyte *) "SGE")) {
  958.       inst->Opcode = SGE;
  959.    }
  960.    else if (StrEq(token, (GLubyte *) "DPH") && IsVersion1_1) {
  961.       inst->Opcode = DPH;
  962.    }
  963.    else if (StrEq(token, (GLubyte *) "SUB") && IsVersion1_1) {
  964.       inst->Opcode = SUB;
  965.    }
  966.    else {
  967.       PARSE_ERROR;
  968.    }
  969.  
  970.    /* dest reg */
  971.    if (!Parse_MaskedDstReg(s, &inst->DstReg))
  972.       PARSE_ERROR;
  973.  
  974.    /* comma */
  975.    if (!Parse_String(s, ","))
  976.       PARSE_ERROR;
  977.  
  978.    /* first src arg */
  979.    if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
  980.       PARSE_ERROR;
  981.  
  982.    /* comma */
  983.    if (!Parse_String(s, ","))
  984.       PARSE_ERROR;
  985.  
  986.    /* second src arg */
  987.    if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
  988.       PARSE_ERROR;
  989.  
  990.    /* semicolon */
  991.    if (!Parse_String(s, ";"))
  992.       PARSE_ERROR;
  993.  
  994.    /* make sure we don't reference more than one program parameter register */
  995.    if (IsProgRegister(inst->SrcReg[0].Register) &&
  996.        IsProgRegister(inst->SrcReg[1].Register) &&
  997.        inst->SrcReg[0].Register != inst->SrcReg[1].Register)
  998.       PARSE_ERROR1("Can't reference two program parameter registers");
  999.  
  1000.    /* make sure we don't reference more than one vertex attribute register */
  1001.    if (IsInputRegister(inst->SrcReg[0].Register) &&
  1002.        IsInputRegister(inst->SrcReg[1].Register) &&
  1003.        inst->SrcReg[0].Register != inst->SrcReg[1].Register)
  1004.       PARSE_ERROR1("Can't reference two vertex attribute registers");
  1005.  
  1006.    return GL_TRUE;
  1007. }
  1008.  
  1009.  
  1010. static GLboolean
  1011. Parse_TriOpInstruction(const GLubyte **s, struct vp_instruction *inst)
  1012. {
  1013.    GLubyte token[100];
  1014.  
  1015.    /* opcode */
  1016.    if (!Parse_Token(s, token))
  1017.       PARSE_ERROR;
  1018.  
  1019.    if (StrEq(token, (GLubyte *) "MAD")) {
  1020.       inst->Opcode = MAD;
  1021.    }
  1022.    else {
  1023.       PARSE_ERROR;
  1024.    }
  1025.  
  1026.    /* dest reg */
  1027.    if (!Parse_MaskedDstReg(s, &inst->DstReg))
  1028.       PARSE_ERROR;
  1029.  
  1030.    /* comma */
  1031.    if (!Parse_String(s, ","))
  1032.       PARSE_ERROR;
  1033.  
  1034.    /* first src arg */
  1035.    if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
  1036.       PARSE_ERROR;
  1037.  
  1038.    /* comma */
  1039.    if (!Parse_String(s, ","))
  1040.       PARSE_ERROR;
  1041.  
  1042.    /* second src arg */
  1043.    if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
  1044.       PARSE_ERROR;
  1045.  
  1046.    /* comma */
  1047.    if (!Parse_String(s, ","))
  1048.       PARSE_ERROR;
  1049.  
  1050.    /* third src arg */
  1051.    if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[2]))
  1052.       PARSE_ERROR;
  1053.  
  1054.    /* semicolon */
  1055.    if (!Parse_String(s, ";"))
  1056.       PARSE_ERROR;
  1057.  
  1058.    /* make sure we don't reference more than one program parameter register */
  1059.    if ((IsProgRegister(inst->SrcReg[0].Register) &&
  1060.         IsProgRegister(inst->SrcReg[1].Register) &&
  1061.         inst->SrcReg[0].Register != inst->SrcReg[1].Register) ||
  1062.        (IsProgRegister(inst->SrcReg[0].Register) &&
  1063.         IsProgRegister(inst->SrcReg[2].Register) &&
  1064.         inst->SrcReg[0].Register != inst->SrcReg[2].Register) ||
  1065.        (IsProgRegister(inst->SrcReg[1].Register) &&
  1066.         IsProgRegister(inst->SrcReg[2].Register) &&
  1067.         inst->SrcReg[1].Register != inst->SrcReg[2].Register))
  1068.       PARSE_ERROR1("Can only reference one program register");
  1069.  
  1070.    /* make sure we don't reference more than one vertex attribute register */
  1071.    if ((IsInputRegister(inst->SrcReg[0].Register) &&
  1072.         IsInputRegister(inst->SrcReg[1].Register) &&
  1073.         inst->SrcReg[0].Register != inst->SrcReg[1].Register) ||
  1074.        (IsInputRegister(inst->SrcReg[0].Register) &&
  1075.         IsInputRegister(inst->SrcReg[2].Register) &&
  1076.         inst->SrcReg[0].Register != inst->SrcReg[2].Register) ||
  1077.        (IsInputRegister(inst->SrcReg[1].Register) &&
  1078.         IsInputRegister(inst->SrcReg[2].Register) &&
  1079.         inst->SrcReg[1].Register != inst->SrcReg[2].Register))
  1080.       PARSE_ERROR1("Can only reference one input register");
  1081.  
  1082.    return GL_TRUE;
  1083. }
  1084.  
  1085.  
  1086. static GLboolean
  1087. Parse_ScalarInstruction(const GLubyte **s, struct vp_instruction *inst)
  1088. {
  1089.    GLubyte token[100];
  1090.  
  1091.    /* opcode */
  1092.    if (!Parse_Token(s, token))
  1093.       PARSE_ERROR;
  1094.  
  1095.    if (StrEq(token, (GLubyte *) "RCP")) {
  1096.       inst->Opcode = RCP;
  1097.    }
  1098.    else if (StrEq(token, (GLubyte *) "RSQ")) {
  1099.       inst->Opcode = RSQ;
  1100.    }
  1101.    else if (StrEq(token, (GLubyte *) "EXP")) {
  1102.       inst->Opcode = EXP;
  1103.    }
  1104.    else if (StrEq(token, (GLubyte *) "LOG")) {
  1105.       inst->Opcode = LOG;
  1106.    }
  1107.    else if (StrEq(token, (GLubyte *) "RCC") && IsVersion1_1) {
  1108.       inst->Opcode = RCC;
  1109.    }
  1110.    else {
  1111.       PARSE_ERROR;
  1112.    }
  1113.  
  1114.    /* dest reg */
  1115.    if (!Parse_MaskedDstReg(s, &inst->DstReg))
  1116.       PARSE_ERROR;
  1117.  
  1118.    /* comma */
  1119.    if (!Parse_String(s, ","))
  1120.       PARSE_ERROR;
  1121.  
  1122.    /* first src arg */
  1123.    if (!Parse_ScalarSrcReg(s, &inst->SrcReg[0]))
  1124.       PARSE_ERROR;
  1125.  
  1126.    /* semicolon */
  1127.    if (!Parse_String(s, ";"))
  1128.       PARSE_ERROR;
  1129.  
  1130.    return GL_TRUE;
  1131. }
  1132.  
  1133.  
  1134. static GLboolean
  1135. Parse_AddressInstruction(const GLubyte **s, struct vp_instruction *inst)
  1136. {
  1137.    inst->Opcode = ARL;
  1138.  
  1139.    /* opcode */
  1140.    if (!Parse_String(s, "ARL"))
  1141.       PARSE_ERROR;
  1142.  
  1143.    /* dest A0 reg */
  1144.    if (!Parse_AddrReg(s))
  1145.       PARSE_ERROR;
  1146.  
  1147.    /* comma */
  1148.    if (!Parse_String(s, ","))
  1149.       PARSE_ERROR;
  1150.  
  1151.    /* parse src reg */
  1152.    if (!Parse_ScalarSrcReg(s, &inst->SrcReg[0]))
  1153.       PARSE_ERROR;
  1154.  
  1155.    /* semicolon */
  1156.    if (!Parse_String(s, ";"))
  1157.       PARSE_ERROR;
  1158.  
  1159.    return GL_TRUE;
  1160. }
  1161.  
  1162.  
  1163. static GLboolean
  1164. Parse_EndInstruction(const GLubyte **s, struct vp_instruction *inst)
  1165. {
  1166.    GLubyte token[100];
  1167.  
  1168.    /* opcode */
  1169.    if (!Parse_String(s, "END"))
  1170.       PARSE_ERROR;
  1171.  
  1172.    inst->Opcode = END;
  1173.  
  1174.    /* this should fail! */
  1175.    if (Parse_Token(s, token))
  1176.       PARSE_ERROR2("Unexpected token after END:", token);
  1177.    else
  1178.       return GL_TRUE;
  1179. }
  1180.  
  1181.  
  1182. static GLboolean
  1183. Parse_OptionSequence(const GLubyte **s, struct vp_instruction program[])
  1184. {
  1185.    while (1) {
  1186.       GLubyte token[100];
  1187.       if (!Peek_Token(s, token)) {
  1188.          PARSE_ERROR1("Unexpected end of input");
  1189.          return GL_FALSE; /* end of input */
  1190.       }
  1191.  
  1192.       if (!StrEq(token, (GLubyte *) "OPTION"))
  1193.          return GL_TRUE;  /* probably an instruction */
  1194.  
  1195.       Parse_Token(s, token);
  1196.  
  1197.       if (!Parse_String(s, "NV_position_invariant"))
  1198.          return GL_FALSE;
  1199.       if (!Parse_String(s, ";"))
  1200.          return GL_FALSE;
  1201.       IsPositionInvariant = GL_TRUE;
  1202.    }
  1203. }
  1204.  
  1205.  
  1206. static GLboolean
  1207. Parse_InstructionSequence(const GLubyte **s, struct vp_instruction program[])
  1208. {
  1209.    GLubyte token[100];
  1210.    GLint count = 0;
  1211.  
  1212.    while (1) {
  1213.       struct vp_instruction *inst = program + count;
  1214.  
  1215.       /* Initialize the instruction */
  1216.       inst->SrcReg[0].Register = -1;
  1217.       inst->SrcReg[1].Register = -1;
  1218.       inst->SrcReg[2].Register = -1;
  1219.       inst->DstReg.Register = -1;
  1220.  
  1221.       if (!Peek_Token(s, token))
  1222.          PARSE_ERROR;
  1223.  
  1224.       if (StrEq(token, (GLubyte *) "MOV") ||
  1225.           StrEq(token, (GLubyte *) "LIT") ||
  1226.           StrEq(token, (GLubyte *) "ABS")) {
  1227.          if (!Parse_UnaryOpInstruction(s, inst))
  1228.             PARSE_ERROR;
  1229.       }
  1230.       else if (StrEq(token, (GLubyte *) "MUL") ||
  1231.           StrEq(token, (GLubyte *) "ADD") ||
  1232.           StrEq(token, (GLubyte *) "DP3") ||
  1233.           StrEq(token, (GLubyte *) "DP4") ||
  1234.           StrEq(token, (GLubyte *) "DST") ||
  1235.           StrEq(token, (GLubyte *) "MIN") ||
  1236.           StrEq(token, (GLubyte *) "MAX") ||
  1237.           StrEq(token, (GLubyte *) "SLT") ||
  1238.           StrEq(token, (GLubyte *) "SGE") ||
  1239.           StrEq(token, (GLubyte *) "DPH") ||
  1240.           StrEq(token, (GLubyte *) "SUB")) {
  1241.          if (!Parse_BiOpInstruction(s, inst))
  1242.             PARSE_ERROR;
  1243.       }
  1244.       else if (StrEq(token, (GLubyte *) "MAD")) {
  1245.          if (!Parse_TriOpInstruction(s, inst))
  1246.             PARSE_ERROR;
  1247.       }
  1248.       else if (StrEq(token, (GLubyte *) "RCP") ||
  1249.                StrEq(token, (GLubyte *) "RSQ") ||
  1250.                StrEq(token, (GLubyte *) "EXP") ||
  1251.                StrEq(token, (GLubyte *) "LOG") ||
  1252.                StrEq(token, (GLubyte *) "RCC")) {
  1253.          if (!Parse_ScalarInstruction(s, inst))
  1254.             PARSE_ERROR;
  1255.       }
  1256.       else if (StrEq(token, (GLubyte *) "ARL")) {
  1257.          if (!Parse_AddressInstruction(s, inst))
  1258.             PARSE_ERROR;
  1259.       }
  1260.       else if (StrEq(token, (GLubyte *) "END")) {
  1261.          if (!Parse_EndInstruction(s, inst))
  1262.             PARSE_ERROR;
  1263.          else
  1264.             return GL_TRUE;  /* all done */
  1265.       }
  1266.       else {
  1267.          /* bad instruction name */
  1268.          PARSE_ERROR2("Unexpected token: ", token);
  1269.       }
  1270.  
  1271.       count++;
  1272.       if (count >= VP_MAX_INSTRUCTIONS)
  1273.          PARSE_ERROR1("Program too long");
  1274.    }
  1275.  
  1276.    PARSE_ERROR;
  1277. }
  1278.  
  1279.  
  1280. static GLboolean
  1281. Parse_Program(const GLubyte **s, struct vp_instruction instBuffer[])
  1282. {
  1283.    if (IsVersion1_1) {
  1284.       if (!Parse_OptionSequence(s, instBuffer)) {
  1285.          return GL_FALSE;
  1286.       }
  1287.    }
  1288.    return Parse_InstructionSequence(s, instBuffer);
  1289. }
  1290.  
  1291.  
  1292. /**
  1293.  * Parse/compile the 'str' returning the compiled 'program'.
  1294.  * ctx->VertexProgram.ErrorPos will be -1 if successful.  Otherwise, ErrorPos
  1295.  * indicates the position of the error in 'str'.
  1296.  */
  1297. void
  1298. _mesa_parse_vertex_program(GLcontext *ctx, GLenum dstTarget,
  1299.                            const GLubyte *str, GLsizei len,
  1300.                            struct vp_program *program)
  1301. {
  1302.    const GLubyte *s;
  1303.    struct vp_instruction instBuffer[VP_MAX_INSTRUCTIONS];
  1304.    GLubyte *newString;
  1305.    struct vp_instruction *newInst;
  1306.    GLenum target;
  1307.  
  1308.    ctx->VertexProgram.ErrorPos = -1;
  1309.    IsPositionInvariant = GL_FALSE;
  1310.    IsVersion1_1 = GL_FALSE;
  1311.  
  1312.    /* check the program header */
  1313.    if (_mesa_strncmp((const char *) str, "!!VP1.0", 7) == 0) {
  1314.       target = GL_VERTEX_PROGRAM_NV;
  1315.       s = str + 7;
  1316.       IsStateProgram = GL_FALSE;
  1317.    }
  1318.    else if (_mesa_strncmp((const char *) str, "!!VP1.1", 7) == 0) {
  1319.       target = GL_VERTEX_PROGRAM_NV;
  1320.       s = str + 7;
  1321.       IsStateProgram = GL_FALSE;
  1322.       IsVersion1_1 = GL_TRUE;
  1323.    }
  1324.    else if (_mesa_strncmp((const char *) str, "!!VSP1.0", 8) == 0) {
  1325.       target = GL_VERTEX_STATE_PROGRAM_NV;
  1326.       s = str + 8;
  1327.       IsStateProgram = GL_TRUE;
  1328.    }
  1329.    else {
  1330.       /* invalid header */
  1331.       ctx->VertexProgram.ErrorPos = 0;
  1332.       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(bad header)");
  1333.       return;
  1334.    }
  1335.  
  1336.    /* make sure target and header match */
  1337.    if (target != dstTarget) {
  1338.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1339.                   "glLoadProgramNV(target mismatch)");
  1340.       return;
  1341.    }
  1342.  
  1343.    if (Parse_Program(&s, instBuffer)) {
  1344.       GLuint numInst;
  1345.       GLuint strLen;
  1346.       GLuint inputsRead = 0;
  1347.       GLuint outputsWritten = 0;
  1348.       GLuint progRegsWritten = 0;
  1349.  
  1350.       /* Find length of the program and compute bitmasks to indicate which
  1351.        * vertex input registers are read, which vertex result registers are
  1352.        * written to, and which program registers are written to.
  1353.        * We could actually do this while we parse the program.
  1354.        */
  1355.       for (numInst = 0; instBuffer[numInst].Opcode != END; numInst++) {
  1356.          const GLint srcReg0 = instBuffer[numInst].SrcReg[0].Register;
  1357.          const GLint srcReg1 = instBuffer[numInst].SrcReg[1].Register;
  1358.          const GLint srcReg2 = instBuffer[numInst].SrcReg[2].Register;
  1359.          const GLint dstReg = instBuffer[numInst].DstReg.Register;
  1360.  
  1361.          if (IsOutputRegister(dstReg))
  1362.             outputsWritten |= (1 << (dstReg - VP_OUTPUT_REG_START));
  1363.          else if (IsProgRegister(dstReg))
  1364.             progRegsWritten |= (1 << (dstReg - VP_PROG_REG_START));
  1365.          if (IsInputRegister(srcReg0)
  1366.              && !instBuffer[numInst].SrcReg[0].RelAddr)
  1367.             inputsRead |= (1 << (srcReg0 - VP_INPUT_REG_START));
  1368.          if (IsInputRegister(srcReg1)
  1369.              && !instBuffer[numInst].SrcReg[1].RelAddr)
  1370.             inputsRead |= (1 << (srcReg1 - VP_INPUT_REG_START));
  1371.          if (IsInputRegister(srcReg2)
  1372.              && !instBuffer[numInst].SrcReg[2].RelAddr)
  1373.             inputsRead |= (1 << (srcReg2 - VP_INPUT_REG_START));
  1374.       }
  1375.       numInst++;
  1376.  
  1377.       if (IsStateProgram) {
  1378.          if (progRegsWritten == 0) {
  1379.             _mesa_error(ctx, GL_INVALID_OPERATION,
  1380.                         "glLoadProgramNV(c[#] not written)");
  1381.             return;
  1382.          }
  1383.       }
  1384.       else {
  1385.          if (!IsPositionInvariant && !(outputsWritten & 1)) {
  1386.             /* bit 1 = HPOS register */
  1387.             _mesa_error(ctx, GL_INVALID_OPERATION,
  1388.                         "glLoadProgramNV(HPOS not written)");
  1389.             return;
  1390.          }
  1391.       }
  1392.  
  1393.       program->InputsRead = inputsRead;
  1394.       program->OutputsWritten = outputsWritten;
  1395.       program->IsPositionInvariant = IsPositionInvariant;
  1396.  
  1397.       /* make copy of the input program string */
  1398.       strLen = _mesa_strlen((const char *) str);
  1399.       newString = (GLubyte *) MALLOC(strLen + 1);
  1400.       if (!newString) {
  1401.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
  1402.          return;
  1403.       }
  1404.       MEMCPY(newString, str, strLen);
  1405.       newString[strLen] = 0; /* terminate */
  1406.  
  1407.       /* copy the compiled instructions */
  1408.       assert(numInst <= VP_MAX_INSTRUCTIONS);
  1409.       newInst = (struct vp_instruction *) MALLOC(numInst * sizeof(struct vp_instruction));
  1410.       if (!newInst) {
  1411.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
  1412.          return;  /* out of memory */
  1413.       }
  1414.       MEMCPY(newInst, instBuffer, numInst * sizeof(struct vp_instruction));
  1415.  
  1416.       /* install the program */
  1417.       program->Target = target;
  1418.       if (program->String) {
  1419.          FREE(program->String);
  1420.       }
  1421.       program->String = newString;
  1422.       if (program->Instructions) {
  1423.          FREE(program->Instructions);
  1424.       }
  1425.       program->Instructions = newInst;
  1426.  
  1427. #ifdef DEBUG_foo
  1428.       _mesa_printf("--- glLoadProgramNV result ---\n");
  1429.       _mesa_print_vertex_program(program);
  1430.       _mesa_printf("------------------------------\n");
  1431. #endif
  1432.    }
  1433.    else {
  1434.       /* Error! */
  1435. #ifdef DEBUG
  1436.       /* print a message showing the program line containing the error */
  1437.       ctx->VertexProgram.ErrorPos = s - str;
  1438.       {
  1439.          const GLubyte *p = str, *line = str;
  1440.          int lineNum = 1, statementNum = 1, column = 0;
  1441.          char errorLine[1000];
  1442.          int i;
  1443.          while (*p && p < s) {  /* s is the error position */
  1444.             if (*p == '\n') {
  1445.                line = p + 1;
  1446.                lineNum++;
  1447.                column = 0;
  1448.             }
  1449.             else if (*p == ';') {
  1450.                statementNum++;
  1451.             }
  1452.             else
  1453.                column++;
  1454.             p++;
  1455.          }
  1456.          if (p) {
  1457.             /* Copy the line with the error into errorLine so we can null-
  1458.              * terminate it.
  1459.              */
  1460.             for (i = 0; line[i] != '\n' && line[i]; i++)
  1461.                errorLine[i] = (char) line[i];
  1462.             errorLine[i] = 0;
  1463.          }
  1464.          /*
  1465.          _mesa_debug("Error pos = %d  (%c) col %d\n",
  1466.                  ctx->VertexProgram.ErrorPos, *s, column);
  1467.          */
  1468.          _mesa_debug(ctx, "Vertex program error on line %2d: %s\n", lineNum, errorLine);
  1469.          _mesa_debug(ctx, "  (statement %2d) near column %2d: ", statementNum, column+1);
  1470.          for (i = 0; i < column; i++)
  1471.             _mesa_debug(ctx, " ");
  1472.          _mesa_debug(ctx, "^\n");
  1473.       }
  1474. #endif
  1475.       _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV");
  1476.    }
  1477. }
  1478.  
  1479.  
  1480. static void
  1481. PrintSrcReg(const struct vp_src_register *src)
  1482. {
  1483.    static const char comps[5] = "xyzw";
  1484.    if (src->Negate)
  1485.       _mesa_printf("-");
  1486.    if (src->RelAddr) {
  1487.       if (src->Register > 0)
  1488.          _mesa_printf("c[A0.x + %d]", src->Register);
  1489.       else if (src->Register < 0)
  1490.          _mesa_printf("c[A0.x - %d]", -src->Register);
  1491.       else
  1492.          _mesa_printf("c[A0.x]");
  1493.    }
  1494.    else if (src->Register >= VP_OUTPUT_REG_START
  1495.        && src->Register <= VP_OUTPUT_REG_END) {
  1496.       _mesa_printf("o[%s]", OutputRegisters[src->Register - VP_OUTPUT_REG_START]);
  1497.    }
  1498.    else if (src->Register >= VP_INPUT_REG_START
  1499.             && src->Register <= VP_INPUT_REG_END) {
  1500.       _mesa_printf("v[%s]", InputRegisters[src->Register - VP_INPUT_REG_START]);
  1501.    }
  1502.    else if (src->Register >= VP_PROG_REG_START
  1503.             && src->Register <= VP_PROG_REG_END) {
  1504.       _mesa_printf("c[%d]", src->Register - VP_PROG_REG_START);
  1505.    }
  1506.    else {
  1507.       _mesa_printf("R%d", src->Register - VP_TEMP_REG_START);
  1508.    }
  1509.  
  1510.    if (src->Swizzle[0] == src->Swizzle[1] &&
  1511.        src->Swizzle[0] == src->Swizzle[2] &&
  1512.        src->Swizzle[0] == src->Swizzle[3]) {
  1513.       _mesa_printf(".%c", comps[src->Swizzle[0]]);
  1514.    }
  1515.    else if (src->Swizzle[0] != 0 ||
  1516.             src->Swizzle[1] != 1 ||
  1517.             src->Swizzle[2] != 2 ||
  1518.             src->Swizzle[3] != 3) {
  1519.       _mesa_printf(".%c%c%c%c",
  1520.              comps[src->Swizzle[0]],
  1521.              comps[src->Swizzle[1]],
  1522.              comps[src->Swizzle[2]],
  1523.              comps[src->Swizzle[3]]);
  1524.    }
  1525. }
  1526.  
  1527.  
  1528. static void
  1529. PrintDstReg(const struct vp_dst_register *dst)
  1530. {
  1531.    GLint w = dst->WriteMask[0] + dst->WriteMask[1]
  1532.            + dst->WriteMask[2] + dst->WriteMask[3];
  1533.  
  1534.    if (dst->Register >= VP_OUTPUT_REG_START
  1535.        && dst->Register <= VP_OUTPUT_REG_END) {
  1536.       _mesa_printf("o[%s]", OutputRegisters[dst->Register - VP_OUTPUT_REG_START]);
  1537.    }
  1538.    else if (dst->Register >= VP_INPUT_REG_START
  1539.             && dst->Register <= VP_INPUT_REG_END) {
  1540.       _mesa_printf("v[%s]", InputRegisters[dst->Register - VP_INPUT_REG_START]);
  1541.    }
  1542.    else if (dst->Register >= VP_PROG_REG_START
  1543.             && dst->Register <= VP_PROG_REG_END) {
  1544.       _mesa_printf("c[%d]", dst->Register - VP_PROG_REG_START);
  1545.    }
  1546.    else {
  1547.       _mesa_printf("R%d", dst->Register - VP_TEMP_REG_START);
  1548.    }
  1549.  
  1550.    if (w != 0 && w != 4) {
  1551.       _mesa_printf(".");
  1552.       if (dst->WriteMask[0])
  1553.          _mesa_printf("x");
  1554.       if (dst->WriteMask[1])
  1555.          _mesa_printf("y");
  1556.       if (dst->WriteMask[2])
  1557.          _mesa_printf("z");
  1558.       if (dst->WriteMask[3])
  1559.          _mesa_printf("w");
  1560.    }
  1561. }
  1562.  
  1563.  
  1564. /**
  1565.  * Print (unparse) the given vertex program.  Just for debugging.
  1566.  */
  1567. void
  1568. _mesa_print_vertex_program(const struct vp_program *program)
  1569. {
  1570.    const struct vp_instruction *inst;
  1571.  
  1572.    for (inst = program->Instructions; ; inst++) {
  1573.       switch (inst->Opcode) {
  1574.       case MOV:
  1575.       case LIT:
  1576.       case RCP:
  1577.       case RSQ:
  1578.       case EXP:
  1579.       case LOG:
  1580.       case RCC:
  1581.       case ABS:
  1582.          _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
  1583.          PrintDstReg(&inst->DstReg);
  1584.          _mesa_printf(", ");
  1585.          PrintSrcReg(&inst->SrcReg[0]);
  1586.          _mesa_printf(";\n");
  1587.          break;
  1588.       case MUL:
  1589.       case ADD:
  1590.       case DP3:
  1591.       case DP4:
  1592.       case DST:
  1593.       case MIN:
  1594.       case MAX:
  1595.       case SLT:
  1596.       case SGE:
  1597.       case DPH:
  1598.       case SUB:
  1599.          _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
  1600.          PrintDstReg(&inst->DstReg);
  1601.          _mesa_printf(", ");
  1602.          PrintSrcReg(&inst->SrcReg[0]);
  1603.          _mesa_printf(", ");
  1604.          PrintSrcReg(&inst->SrcReg[1]);
  1605.          _mesa_printf(";\n");
  1606.          break;
  1607.       case MAD:
  1608.          _mesa_printf("MAD ");
  1609.          PrintDstReg(&inst->DstReg);
  1610.          _mesa_printf(", ");
  1611.          PrintSrcReg(&inst->SrcReg[0]);
  1612.          _mesa_printf(", ");
  1613.          PrintSrcReg(&inst->SrcReg[1]);
  1614.          _mesa_printf(", ");
  1615.          PrintSrcReg(&inst->SrcReg[2]);
  1616.          _mesa_printf(";\n");
  1617.          break;
  1618.       case ARL:
  1619.          _mesa_printf("ARL A0.x, ");
  1620.          PrintSrcReg(&inst->SrcReg[0]);
  1621.          _mesa_printf(";\n");
  1622.          break;
  1623.       case END:
  1624.          _mesa_printf("END\n");
  1625.          return;
  1626.          break;
  1627.       default:
  1628.          _mesa_printf("BAD INSTRUCTION\n");
  1629.       }
  1630.    }
  1631. }
  1632.  
  1633.