Committing in .

 Updated OpenVMS compile support due to shader directory.
 Removed <CR>'s in arbprogparse.c

 Modified Files:
 	Mesa/src/mesa/descrip.mms
 	Mesa/src/mesa/drivers/common/descrip.mms
 	Mesa/src/mesa/main/descrip.mms
 	Mesa/src/mesa/shader/arbprogparse.c
 	Mesa/src/mesa/shader/descrip.mms
 	Mesa/src/mesa/swrast/descrip.mms Mesa/src/mesa/tnl/descrip.mms
 ----------------------------------------------------------------------
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c
index 9099fd8..6cbdd39 100644
--- a/src/mesa/shader/arbprogparse.c
+++ b/src/mesa/shader/arbprogparse.c
@@ -1,3727 +1,3727 @@
-/*
- * Mesa 3-D graphics library
- * Version:  6.1
- *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#define DEBUG_PARSING 0
-
-/**
- * \file arbprogparse.c
- * ARB_*_program parser core
- * \author Karl Rasche
- */
-
-#include "mtypes.h"
-#include "glheader.h"
-#include "context.h"
-#include "hash.h"
-#include "imports.h"
-#include "macros.h"
-#include "program.h"
-#include "nvvertprog.h"
-#include "nvfragprog.h"
-#include "arbprogparse.h"
-#include "grammar_mesa.h"
-
-/* TODO:
- *    Fragment Program Stuff:
- *    -----------------------------------------------------
- *
- *    - things from Michal's email
- *       + overflow on atoi
- *       + not-overflowing floats (don't use parse_integer..)
- *       + can remove range checking in arbparse.c
- *
- *    - check all limits of number of various variables
- *      + parameters
- *
- *    - test! test! test!
- *
- *    Vertex Program Stuff:
- *    -----------------------------------------------------
- *    - Optimize param array usage and count limits correctly, see spec,
- *         section 2.14.3.7
- *       + Record if an array is reference absolutly or relatively (or both)
- *       + For absolute arrays, store a bitmap of accesses
- *       + For single parameters, store an access flag
- *       + After parsing, make a parameter cleanup and merging pass, where
- *           relative arrays are layed out first, followed by abs arrays, and
- *           finally single state.
- *       + Remap offsets for param src and dst registers
- *       + Now we can properly count parameter usage
- *
- *    - Multiple state binding errors in param arrays (see spec, just before
- *         section 2.14.3.3)
- *    - grep for XXX
- *
- *    Mesa Stuff
- *    -----------------------------------------------------
- *    - User clipping planes vs. PositionInvariant
- *    - Is it sufficient to just multiply by the mvp to transform in the
- *        PositionInvariant case? Or do we need something more involved?
- *
- *    - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
- *    - fetch state listed in program_parameters list
- *       + WTF should this go???
- *       + currently in nvvertexec.c and s_nvfragprog.c
- *
- *    - allow for multiple address registers (and fetch address regs properly)
- *
- *    Cosmetic Stuff
- *    -----------------------------------------------------
- * 	- remove any leftover unused grammer.c stuff (dict_ ?)
- * 	- fix grammer.c error handling so its not static
- * 	- #ifdef around stuff pertaining to extentions
- *
- *    Outstanding Questions:
- *    -----------------------------------------------------
- *    - ARB_matrix_palette / ARB_vertex_blend -- not supported
- *      what gets hacked off because of this:
- *       + VERTEX_ATTRIB_MATRIXINDEX
- *       + VERTEX_ATTRIB_WEIGHT
- *       + MATRIX_MODELVIEW
- *       + MATRIX_PALETTE
- *
- *    - When can we fetch env/local params from their own register files, and
- *      when to we have to fetch them into the main state register file?
- *      (think arrays)
- *
- *    Grammar Changes:
- *    -----------------------------------------------------
- */
-
-/* Changes since moving the file to shader directory
-
-2004-III-4 ------------------------------------------------------------
-- added #include "grammar_mesa.h"
-- removed grammar specific code part (it resides now in grammar.c)
-- added GL_ARB_fragment_program_shadow tokens
-- modified #include "arbparse_syn.h"
-- major changes inside _mesa_parse_arb_program()
-- check the program string for '\0' characters
-- copy the program string to a one-byte-longer location to have
-  it null-terminated
-- position invariance test (not writing to result.position) moved
-  to syntax part
-*/
-
-typedef GLubyte *production;
-
-/**
- * This is the text describing the rules to parse the grammar
- */
-static char arb_grammar_text[] =
-#include "arbprogram_syn.h"
-;
-
-/**
- * These should match up with the values defined in arbprogram.syn
- */
-
-/*
-    Changes:
-    - changed and merged V_* and F_* opcode values to OP_*.
-    - added GL_ARB_fragment_program_shadow specific tokens (michal)
-*/
-#define  REVISION                                   0x07
-
-/* program type */
-#define  FRAGMENT_PROGRAM                           0x01
-#define  VERTEX_PROGRAM                             0x02
-
-/* program section */
-#define  OPTION                                     0x01
-#define  INSTRUCTION                                0x02
-#define  DECLARATION                                0x03
-#define  END                                        0x04
-
-/* GL_ARB_fragment_program option flags */
-#define  ARB_PRECISION_HINT_FASTEST                 0x01
-#define  ARB_PRECISION_HINT_NICEST                  0x02
-#define  ARB_FOG_EXP                                0x04
-#define  ARB_FOG_EXP2                               0x08
-#define  ARB_FOG_LINEAR                             0x10
-
-/* GL_ARB_vertex_program option flags */
-#define  ARB_POSITION_INVARIANT                     0x20
-
-/* GL_ARB_fragment_program_shadow option flags */
-#define  ARB_FRAGMENT_PROGRAM_SHADOW                0x40
-
-/* GL_ARB_fragment_program instruction class */
-#define  OP_ALU_INST                                0x00
-#define  OP_TEX_INST                                0x01
-
-/* GL_ARB_vertex_program instruction class */
-/*       OP_ALU_INST */
-
-/* GL_ARB_fragment_program instruction type */
-#define  OP_ALU_VECTOR                               0x00
-#define  OP_ALU_SCALAR                               0x01
-#define  OP_ALU_BINSC                                0x02
-#define  OP_ALU_BIN                                  0x03
-#define  OP_ALU_TRI                                  0x04
-#define  OP_ALU_SWZ                                  0x05
-#define  OP_TEX_SAMPLE                               0x06
-#define  OP_TEX_KIL                                  0x07
-
-/* GL_ARB_vertex_program instruction type */
-#define  OP_ALU_ARL                                  0x08
-/*       OP_ALU_VECTOR */
-/*       OP_ALU_SCALAR */
-/*       OP_ALU_BINSC */
-/*       OP_ALU_BIN */
-/*       OP_ALU_TRI */
-/*       OP_ALU_SWZ */
-
-/* GL_ARB_fragment_program instruction code */
-#define  OP_ABS                                     0x00
-#define  OP_ABS_SAT                                 0x1B
-#define  OP_FLR                                     0x09
-#define  OP_FLR_SAT                                 0x26
-#define  OP_FRC                                     0x0A
-#define  OP_FRC_SAT                                 0x27
-#define  OP_LIT                                     0x0C
-#define  OP_LIT_SAT                                 0x2A
-#define  OP_MOV                                     0x11
-#define  OP_MOV_SAT                                 0x30
-#define  OP_COS                                     0x1F
-#define  OP_COS_SAT                                 0x20
-#define  OP_EX2                                     0x07
-#define  OP_EX2_SAT                                 0x25
-#define  OP_LG2                                     0x0B
-#define  OP_LG2_SAT                                 0x29
-#define  OP_RCP                                     0x14
-#define  OP_RCP_SAT                                 0x33
-#define  OP_RSQ                                     0x15
-#define  OP_RSQ_SAT                                 0x34
-#define  OP_SIN                                     0x38
-#define  OP_SIN_SAT                                 0x39
-#define  OP_SCS                                     0x35
-#define  OP_SCS_SAT                                 0x36
-#define  OP_POW                                     0x13
-#define  OP_POW_SAT                                 0x32
-#define  OP_ADD                                     0x01
-#define  OP_ADD_SAT                                 0x1C
-#define  OP_DP3                                     0x03
-#define  OP_DP3_SAT                                 0x21
-#define  OP_DP4                                     0x04
-#define  OP_DP4_SAT                                 0x22
-#define  OP_DPH                                     0x05
-#define  OP_DPH_SAT                                 0x23
-#define  OP_DST                                     0x06
-#define  OP_DST_SAT                                 0x24
-#define  OP_MAX                                     0x0F
-#define  OP_MAX_SAT                                 0x2E
-#define  OP_MIN                                     0x10
-#define  OP_MIN_SAT                                 0x2F
-#define  OP_MUL                                     0x12
-#define  OP_MUL_SAT                                 0x31
-#define  OP_SGE                                     0x16
-#define  OP_SGE_SAT                                 0x37
-#define  OP_SLT                                     0x17
-#define  OP_SLT_SAT                                 0x3A
-#define  OP_SUB                                     0x18
-#define  OP_SUB_SAT                                 0x3B
-#define  OP_XPD                                     0x1A
-#define  OP_XPD_SAT                                 0x43
-#define  OP_CMP                                     0x1D
-#define  OP_CMP_SAT                                 0x1E
-#define  OP_LRP                                     0x2B
-#define  OP_LRP_SAT                                 0x2C
-#define  OP_MAD                                     0x0E
-#define  OP_MAD_SAT                                 0x2D
-#define  OP_SWZ                                     0x19
-#define  OP_SWZ_SAT                                 0x3C
-#define  OP_TEX                                     0x3D
-#define  OP_TEX_SAT                                 0x3E
-#define  OP_TXB                                     0x3F
-#define  OP_TXB_SAT                                 0x40
-#define  OP_TXP                                     0x41
-#define  OP_TXP_SAT                                 0x42
-#define  OP_KIL                                     0x28
-
-/* GL_ARB_vertex_program instruction code */
-#define  OP_ARL                                     0x02
-/*       OP_ABS */
-/*       OP_FLR */
-/*       OP_FRC */
-/*       OP_LIT */
-/*       OP_MOV */
-/*       OP_EX2 */
-#define  OP_EXP                                     0x08
-/*       OP_LG2 */
-#define  OP_LOG                                     0x0D
-/*       OP_RCP */
-/*       OP_RSQ */
-/*       OP_POW */
-/*       OP_ADD */
-/*       OP_DP3 */
-/*       OP_DP4 */
-/*       OP_DPH */
-/*       OP_DST */
-/*       OP_MAX */
-/*       OP_MIN */
-/*       OP_MUL */
-/*       OP_SGE */
-/*       OP_SLT */
-/*       OP_SUB */
-/*       OP_XPD */
-/*       OP_MAD */
-/*       OP_SWZ */
-
-/* fragment attribute binding */
-#define  FRAGMENT_ATTRIB_COLOR                      0x01
-#define  FRAGMENT_ATTRIB_TEXCOORD                   0x02
-#define  FRAGMENT_ATTRIB_FOGCOORD                   0x03
-#define  FRAGMENT_ATTRIB_POSITION                   0x04
-
-/* vertex attribute binding */
-#define  VERTEX_ATTRIB_POSITION                     0x01
-#define  VERTEX_ATTRIB_WEIGHT                       0x02
-#define  VERTEX_ATTRIB_NORMAL                       0x03
-#define  VERTEX_ATTRIB_COLOR                        0x04
-#define  VERTEX_ATTRIB_FOGCOORD                     0x05
-#define  VERTEX_ATTRIB_TEXCOORD                     0x06
-#define  VERTEX_ATTRIB_MATRIXINDEX                  0x07
-#define  VERTEX_ATTRIB_GENERIC                      0x08
-
-/* fragment result binding */
-#define  FRAGMENT_RESULT_COLOR                      0x01
-#define  FRAGMENT_RESULT_DEPTH                      0x02
-
-/* vertex result binding */
-#define  VERTEX_RESULT_POSITION                     0x01
-#define  VERTEX_RESULT_COLOR                        0x02
-#define  VERTEX_RESULT_FOGCOORD                     0x03
-#define  VERTEX_RESULT_POINTSIZE                    0x04
-#define  VERTEX_RESULT_TEXCOORD                     0x05
-
-/* texture target */
-#define  TEXTARGET_1D                               0x01
-#define  TEXTARGET_2D                               0x02
-#define  TEXTARGET_3D                               0x03
-#define  TEXTARGET_RECT                             0x04
-#define  TEXTARGET_CUBE                             0x05
-/* GL_ARB_fragment_program_shadow */
-#define  TEXTARGET_SHADOW1D                         0x06
-#define  TEXTARGET_SHADOW2D                         0x07
-#define  TEXTARGET_SHADOWRECT                       0x08
-
-/* face type */
-#define  FACE_FRONT                                 0x00
-#define  FACE_BACK                                  0x01
-
-/* color type */
-#define  COLOR_PRIMARY                              0x00
-#define  COLOR_SECONDARY                            0x01
-
-/* component */
-#define  COMPONENT_X                                0x00
-#define  COMPONENT_Y                                0x01
-#define  COMPONENT_Z                                0x02
-#define  COMPONENT_W                                0x03
-#define  COMPONENT_0                                0x04
-#define  COMPONENT_1                                0x05
-
-/* array index type */
-#define  ARRAY_INDEX_ABSOLUTE                       0x00
-#define  ARRAY_INDEX_RELATIVE                       0x01
-
-/* matrix name */
-#define  MATRIX_MODELVIEW                           0x01
-#define  MATRIX_PROJECTION                          0x02
-#define  MATRIX_MVP                                 0x03
-#define  MATRIX_TEXTURE                             0x04
-#define  MATRIX_PALETTE                             0x05
-#define  MATRIX_PROGRAM                             0x06
-
-/* matrix modifier */
-#define  MATRIX_MODIFIER_IDENTITY                   0x00
-#define  MATRIX_MODIFIER_INVERSE                    0x01
-#define  MATRIX_MODIFIER_TRANSPOSE                  0x02
-#define  MATRIX_MODIFIER_INVTRANS                   0x03
-
-/* constant type */
-#define  CONSTANT_SCALAR                            0x01
-#define  CONSTANT_VECTOR                            0x02
-
-/* program param type */
-#define  PROGRAM_PARAM_ENV                          0x01
-#define  PROGRAM_PARAM_LOCAL                        0x02
-
-/* register type */
-#define  REGISTER_ATTRIB                            0x01
-#define  REGISTER_PARAM                             0x02
-#define  REGISTER_RESULT                            0x03
-#define  REGISTER_ESTABLISHED_NAME                  0x04
-
-/* param binding */
-#define  PARAM_NULL                                 0x00
-#define  PARAM_ARRAY_ELEMENT                        0x01
-#define  PARAM_STATE_ELEMENT                        0x02
-#define  PARAM_PROGRAM_ELEMENT                      0x03
-#define  PARAM_PROGRAM_ELEMENTS                     0x04
-#define  PARAM_CONSTANT                             0x05
-
-/* param state property */
-#define  STATE_MATERIAL_PARSER                      0x01
-#define  STATE_LIGHT_PARSER                         0x02
-#define  STATE_LIGHT_MODEL                          0x03
-#define  STATE_LIGHT_PROD                           0x04
-#define  STATE_FOG                                  0x05
-#define  STATE_MATRIX_ROWS                          0x06
-/* GL_ARB_fragment_program */
-#define  STATE_TEX_ENV                              0x07
-#define  STATE_DEPTH                                0x08
-/* GL_ARB_vertex_program */
-#define  STATE_TEX_GEN                              0x09
-#define  STATE_CLIP_PLANE                           0x0A
-#define  STATE_POINT                                0x0B
-
-/* state material property */
-#define  MATERIAL_AMBIENT                           0x01
-#define  MATERIAL_DIFFUSE                           0x02
-#define  MATERIAL_SPECULAR                          0x03
-#define  MATERIAL_EMISSION                          0x04
-#define  MATERIAL_SHININESS                         0x05
-
-/* state light property */
-#define  LIGHT_AMBIENT                              0x01
-#define  LIGHT_DIFFUSE                              0x02
-#define  LIGHT_SPECULAR                             0x03
-#define  LIGHT_POSITION                             0x04
-#define  LIGHT_ATTENUATION                          0x05
-#define  LIGHT_HALF                                 0x06
-#define  LIGHT_SPOT_DIRECTION                       0x07
-
-/* state light model property */
-#define  LIGHT_MODEL_AMBIENT                        0x01
-#define  LIGHT_MODEL_SCENECOLOR                     0x02
-
-/* state light product property */
-#define  LIGHT_PROD_AMBIENT                         0x01
-#define  LIGHT_PROD_DIFFUSE                         0x02
-#define  LIGHT_PROD_SPECULAR                        0x03
-
-/* state texture environment property */
-#define  TEX_ENV_COLOR                              0x01
-
-/* state texture generation coord property */
-#define  TEX_GEN_EYE                                0x01
-#define  TEX_GEN_OBJECT                             0x02
-
-/* state fog property */
-#define  FOG_COLOR                                  0x01
-#define  FOG_PARAMS                                 0x02
-
-/* state depth property */
-#define  DEPTH_RANGE                                0x01
-
-/* state point parameters property */
-#define  POINT_SIZE                                 0x01
-#define  POINT_ATTENUATION                          0x02
-
-/* declaration */
-#define  ATTRIB                                     0x01
-#define  PARAM                                      0x02
-#define  TEMP                                       0x03
-#define  OUTPUT                                     0x04
-#define  ALIAS                                      0x05
-/* GL_ARB_vertex_program */
-#define  ADDRESS                                    0x06
-
-/*-----------------------------------------------------------------------
- * From here on down is the semantic checking portion
- *
- */
-
-/**
- * Variable Table Handling functions
- */
-typedef enum
-{
-   vt_none,
-   vt_address,
-   vt_attrib,
-   vt_param,
-   vt_temp,
-   vt_output,
-   vt_alias
-} var_type;
-
-
-/*
- * Setting an explicit field for each of the binding properties is a bit wasteful
- * of space, but it should be much more clear when reading later on..
- */
-struct var_cache
-{
-   GLubyte *name;
-   var_type type;
-   GLuint address_binding;      /* The index of the address register we should
-                                 * be using                                        */
-   GLuint attrib_binding;       /* For type vt_attrib, see nvfragprog.h for values */
-   GLuint attrib_binding_idx;   /* The index into the attrib register file corresponding
-                                 * to the state in attrib_binding                  */
-   GLuint attrib_is_generic;    /* If the attrib was specified through a generic
-                                 * vertex attrib                                   */
-   GLuint temp_binding;         /* The index of the temp register we are to use    */
-   GLuint output_binding;       /* For type vt_output, see nvfragprog.h for values */
-   GLuint output_binding_idx;   /* This is the index into the result register file
-                                 * corresponding to the bound result state         */
-   struct var_cache *alias_binding;     /* For type vt_alias, points to the var_cache entry
-                                         * that this is aliased to                         */
-   GLuint param_binding_type;   /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
-                                 *    PROGRAM_ENV_PARAM}                           */
-   GLuint param_binding_begin;  /* This is the offset into the program_parameter_list where
-                                 * the tokens representing our bound state (or constants)
-                                 * start */
-   GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
-                                 * we take up with our state tokens or constants. Note that
-                                 * this is _not_ the same as the number of param registers
-                                 * we eventually use */
-   struct var_cache *next;
-};
-
-static GLvoid
-var_cache_create (struct var_cache **va)
-{
-   *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));
-   if (*va) {
-      (**va).name = NULL;
-      (**va).type = vt_none;
-      (**va).attrib_binding = ~0;
-      (**va).attrib_is_generic = 0;
-      (**va).temp_binding = ~0;
-      (**va).output_binding = ~0;
-      (**va).output_binding_idx = ~0;
-      (**va).param_binding_type = ~0;
-      (**va).param_binding_begin = ~0;
-      (**va).param_binding_length = ~0;
-      (**va).alias_binding = NULL;
-      (**va).next = NULL;
-   }
-}
-
-static GLvoid
-var_cache_destroy (struct var_cache **va)
-{
-   if (*va) {
-      var_cache_destroy (&(**va).next);
-      _mesa_free (*va);
-      *va = NULL;
-   }
-}
-
-static GLvoid
-var_cache_append (struct var_cache **va, struct var_cache *nv)
-{
-   if (*va)
-      var_cache_append (&(**va).next, nv);
-   else
-      *va = nv;
-}
-
-static struct var_cache *
-var_cache_find (struct var_cache *va, GLubyte * name)
-{
-   struct var_cache *first = va;
-
-   while (va) {
-      if (!strcmp ( (const char*) name, (const char*) va->name)) {
-         if (va->type == vt_alias)
-            return var_cache_find (first, va->name);
-         return va;
-      }
-
-      va = va->next;
-   }
-
-   return NULL;
-}
-
-/**
- * constructs an integer from 4 GLubytes in LE format
- */
-static GLuint
-parse_position (GLubyte ** inst)
-{
-   GLuint value;
-
-   value =  (GLuint) (*(*inst)++);
-   value += (GLuint) (*(*inst)++) * 0x100;
-   value += (GLuint) (*(*inst)++) * 0x10000;
-   value += (GLuint) (*(*inst)++) * 0x1000000;
-
-   return value;
-}
-
-/**
- * This will, given a string, lookup the string as a variable name in the
- * var cache. If the name is found, the var cache node corresponding to the
- * var name is returned. If it is not found, a new entry is allocated
- *
- * \param  I     Points into the binary array where the string identifier begins
- * \param  found 1 if the string was found in the var_cache, 0 if it was allocated
- * \return       The location on the var_cache corresponding the the string starting at I
- */
-static struct var_cache *
-parse_string (GLubyte ** inst, struct var_cache **vc_head,
-              struct arb_program *Program, GLuint * found)
-{
-   GLubyte *i = *inst;
-   struct var_cache *va = NULL;
-
-   *inst += _mesa_strlen ((char *) i) + 1;
-
-   va = var_cache_find (*vc_head, i);
-
-   if (va) {
-      *found = 1;
-      return va;
-   }
-
-   *found = 0;
-   var_cache_create (&va);
-   va->name = i;
-
-   var_cache_append (vc_head, va);
-
-   return va;
-}
-
-static char *
-parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
-{
-   GLubyte *i = *inst;
-
-   *inst += _mesa_strlen ((char *) i) + 1;
-
-   return (char *) i;
-}
-
-/**
- * \return 0 if sign is plus, 1 if sign is minus
- */
-static GLuint
-parse_sign (GLubyte ** inst)
-{
-   /*return *(*inst)++ != '+'; */
-
-   if (**inst == '-') {
-      (*inst)++;
-      return 1;
-   }
-   else if (**inst == '+') {
-      (*inst)++;
-      return 0;
-   }
-
-   return 0;
-}
-
-/**
- * parses and returns signed integer
- */
-static GLint
-parse_integer (GLubyte ** inst, struct arb_program *Program)
-{
-   GLint sign;
-   GLint value;
-
-   /* check if *inst points to '+' or '-'
-    * if yes, grab the sign and increment *inst
-    */
-   sign = parse_sign (inst);
-
-   /* now check if *inst points to 0
-    * if yes, increment the *inst and return the default value
-    */
-   if (**inst == 0) {
-      (*inst)++;
-      return 0;
-   }
-
-   /* parse the integer as you normally would do it */
-   value = _mesa_atoi (parse_string_without_adding (inst, Program));
-
-   /* now, after terminating 0 there is a position
-    * to parse it - parse_position()
-    */
-   Program->Position = parse_position (inst);
-
-   if (sign)
-      value *= -1;
-
-   return value;
-}
-
-/**
- */
-static GLfloat
-parse_float (GLubyte ** inst, struct arb_program *Program)
-{
-   GLint tmp[5], denom;
-   GLuint leading_zeros =0;
-   GLfloat value = 0;
-
-#if 0
-   tmp[0] = parse_sign (inst);  /* This is the sign of the number + - >0, - -> 1 */
-#endif
-   tmp[1] = parse_integer (inst, Program);   /* This is the integer portion of the number */
-
-   /* Now we grab the fractional portion of the number (the digits after
-	* the .). We can have leading 0's here, which parse_integer will ignore,
-	* so we'll check for those first
-	*/
-   while ((**inst == '0') && ( *(*inst+1) != 0))
-   {
-	  leading_zeros++;
-	  (*inst)++;
-   }
-   tmp[2] = parse_integer (inst, Program);   /* This is the fractional portion of the number */
-   tmp[3] = parse_sign (inst);               /* This is the sign of the exponent */
-   tmp[4] = parse_integer (inst, Program);   /* This is the exponent */
-
-   value = (GLfloat) tmp[1];
-   denom = 1;
-   while (denom < tmp[2])
-      denom *= 10;
-   denom *= (GLint) _mesa_pow( 10, leading_zeros );
-   value += (GLfloat) tmp[2] / (GLfloat) denom;
-#if 0
-   if (tmp[0])
-      value *= -1;
-#endif
-   value *= (GLfloat) _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);
-
-   return value;
-}
-
-
-/**
- */
-static GLfloat
-parse_signed_float (GLubyte ** inst, struct arb_program *Program)
-{
-   GLint negate;
-   GLfloat value;
-
-   negate = parse_sign (inst);
-
-   value = parse_float (inst, Program);
-
-   if (negate)
-      value *= -1;
-
-   return value;
-}
-
-/**
- * This picks out a constant value from the parsed array. The constant vector is r
- * returned in the *values array, which should be of length 4.
- *
- * \param values - The 4 component vector with the constant value in it
- */
-static GLvoid
-parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
-                GLboolean use)
-{
-   GLuint components, i;
-
-
-   switch (*(*inst)++) {
-      case CONSTANT_SCALAR:
-         if (use == GL_TRUE) {
-            values[0] =
-               values[1] =
-               values[2] = values[3] = parse_float (inst, Program);
-         }
-         else {
-            values[0] =
-               values[1] =
-               values[2] = values[3] = parse_signed_float (inst, Program);
-         }
-
-         break;
-      case CONSTANT_VECTOR:
-         values[0] = values[1] = values[2] = 0;
-         values[3] = 1;
-         components = *(*inst)++;
-         for (i = 0; i < components; i++) {
-            values[i] = parse_signed_float (inst, Program);
-         }
-         break;
-   }
-}
-
-/**
- * \param offset The offset from the address register that we should
- *                address
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,
-                        GLint *offset)
-{
-   *offset = parse_integer(inst, Program);
-   if ((*offset > 63) || (*offset < -64)) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Relative offset out of range");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Relative offset %d out of range",
-                                                *offset);
-      return 1;
-   }
-
-   return 0;
-}
-
-/**
- * \param  color 0 if color type is primary, 1 if color type is secondary
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
-                  GLint * color)
-{
-   *color = *(*inst)++ != COLOR_PRIMARY;
-   return 0;
-}
-
-/**
- * Get an integer corresponding to a generic vertex attribute.
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
-                       struct arb_program *Program, GLuint *attrib)
-{
-   *attrib = parse_integer(inst, Program);
-
-   if ((*attrib < 0) || (*attrib > MAX_VERTEX_PROGRAM_ATTRIBS))
-   {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Invalid generic vertex attribute index");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");
-
-      return 1;
-   }
-
-   return 0;
-}
-
-
-/**
- * \param coord The texture unit index
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
-                    struct arb_program *Program, GLuint * coord)
-{
-   *coord = parse_integer (inst, Program);
-
-   if ((*coord < 0) || (*coord >= ctx->Const.MaxTextureUnits)) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Invalid texture unit index");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
-      return 1;
-   }
-
-   return 0;
-}
-
-/**
- * \param coord The weight index
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
-                  GLint * coord)
-{
-   *coord = parse_integer (inst, Program);
-
-   if ((*coord < 0) || (*coord >= 1)) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Invalid weight index");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");
-      return 1;
-   }
-
-   return 0;
-}
-
-/**
- * \param coord The clip plane index
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
-                     struct arb_program *Program, GLint * coord)
-{
-   *coord = parse_integer (inst, Program);
-
-   if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Invalid clip plane index");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");
-      return 1;
-   }
-
-   return 0;
-}
-
-
-/**
- * \return 0 on front face, 1 on back face
- */
-static GLuint
-parse_face_type (GLubyte ** inst)
-{
-   switch (*(*inst)++) {
-      case FACE_FRONT:
-         return 0;
-
-      case FACE_BACK:
-         return 1;
-   }
-   return 0;
-}
-
-
-/**
- * Given a matrix and a modifier token on the binary array, return tokens
- * that _mesa_fetch_state() [program.c] can understand.
- *
- * \param matrix - the matrix we are talking about
- * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
- * \param matrix_modifier - the matrix modifier (trans, inv, etc)
- * \return 0 on sucess, 1 on failure
- */
-static GLuint
-parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
-              GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
-{
-   GLubyte mat = *(*inst)++;
-
-   *matrix_idx = 0;
-
-   switch (mat) {
-      case MATRIX_MODELVIEW:
-         *matrix = STATE_MODELVIEW;
-         *matrix_idx = parse_integer (inst, Program);
-         if (*matrix_idx > 0) {
-            _mesa_set_program_error (ctx, Program->Position,
-               "ARB_vertex_blend not supported\n");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-               "ARB_vertex_blend not supported\n");
-            return 1;
-         }
-         break;
-
-      case MATRIX_PROJECTION:
-         *matrix = STATE_PROJECTION;
-         break;
-
-      case MATRIX_MVP:
-         *matrix = STATE_MVP;
-         break;
-
-      case MATRIX_TEXTURE:
-         *matrix = STATE_TEXTURE;
-         *matrix_idx = parse_integer (inst, Program);
-         if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {
-            _mesa_set_program_error (ctx, Program->Position,
-                                     "Invalid Texture Unit");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-                         "Invalid Texture Unit: %d", *matrix_idx);
-            return 1;
-         }
-         break;
-
-         /* This is not currently supported (ARB_matrix_palette) */
-      case MATRIX_PALETTE:
-         *matrix_idx = parse_integer (inst, Program);
-         _mesa_set_program_error (ctx, Program->Position,
-              "ARB_matrix_palette not supported\n");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-              "ARB_matrix_palette not supported\n");
-         return 1;
-         break;
-
-      case MATRIX_PROGRAM:
-         *matrix = STATE_PROGRAM;
-         *matrix_idx = parse_integer (inst, Program);
-         if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {
-            _mesa_set_program_error (ctx, Program->Position,
-                                     "Invalid Program Matrix");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-                         "Invalid Program Matrix: %d", *matrix_idx);
-            return 1;
-         }
-         break;
-   }
-
-   switch (*(*inst)++) {
-      case MATRIX_MODIFIER_IDENTITY:
-         *matrix_modifier = 0;
-         break;
-      case MATRIX_MODIFIER_INVERSE:
-         *matrix_modifier = STATE_MATRIX_INVERSE;
-         break;
-      case MATRIX_MODIFIER_TRANSPOSE:
-         *matrix_modifier = STATE_MATRIX_TRANSPOSE;
-         break;
-      case MATRIX_MODIFIER_INVTRANS:
-         *matrix_modifier = STATE_MATRIX_INVTRANS;
-         break;
-   }
-
-   return 0;
-}
-
-
-/**
- * This parses a state string (rather, the binary version of it) into
- * a 6-token sequence as described in _mesa_fetch_state() [program.c]
- *
- * \param inst         - the start in the binary arry to start working from
- * \param state_tokens - the storage for the 6-token state description
- * \return             - 0 on sucess, 1 on error
- */
-static GLuint
-parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
-                         struct arb_program *Program, GLint * state_tokens)
-{
-   switch (*(*inst)++) {
-      case STATE_MATERIAL_PARSER:
-         state_tokens[0] = STATE_MATERIAL;
-         state_tokens[1] = parse_face_type (inst);
-         switch (*(*inst)++) {
-            case MATERIAL_AMBIENT:
-               state_tokens[2] = STATE_AMBIENT;
-               break;
-            case MATERIAL_DIFFUSE:
-               state_tokens[2] = STATE_DIFFUSE;
-               break;
-            case MATERIAL_SPECULAR:
-               state_tokens[2] = STATE_SPECULAR;
-               break;
-            case MATERIAL_EMISSION:
-               state_tokens[2] = STATE_EMISSION;
-	       break;
-            case MATERIAL_SHININESS:
-               state_tokens[2] = STATE_SHININESS;
-               break;
-         }
-         break;
-
-      case STATE_LIGHT_PARSER:
-         state_tokens[0] = STATE_LIGHT;
-         state_tokens[1] = parse_integer (inst, Program);
-
-         /* Check the value of state_tokens[1] against the # of lights */
-         if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
-            _mesa_set_program_error (ctx, Program->Position,
-                                     "Invalid Light Number");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-                         "Invalid Light Number: %d", state_tokens[1]);
-            return 1;
-         }
-
-         switch (*(*inst)++) {
-            case LIGHT_AMBIENT:
-               state_tokens[2] = STATE_AMBIENT;
-               break;
-            case LIGHT_DIFFUSE:
-               state_tokens[2] = STATE_DIFFUSE;
-               break;
-            case LIGHT_SPECULAR:
-               state_tokens[2] = STATE_SPECULAR;
-               break;
-            case LIGHT_POSITION:
-               state_tokens[2] = STATE_POSITION;
-               break;
-            case LIGHT_ATTENUATION:
-               state_tokens[2] = STATE_ATTENUATION;
-               break;
-            case LIGHT_HALF:
-               state_tokens[2] = STATE_HALF;
-               break;
-            case LIGHT_SPOT_DIRECTION:
-               state_tokens[2] = STATE_SPOT_DIRECTION;
-               break;
-         }
-         break;
-
-      case STATE_LIGHT_MODEL:
-         switch (*(*inst)++) {
-            case LIGHT_MODEL_AMBIENT:
-               state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
-               break;
-            case LIGHT_MODEL_SCENECOLOR:
-               state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
-               state_tokens[1] = parse_face_type (inst);
-               break;
-         }
-         break;
-
-      case STATE_LIGHT_PROD:
-         state_tokens[0] = STATE_LIGHTPROD;
-         state_tokens[1] = parse_integer (inst, Program);
-
-         /* Check the value of state_tokens[1] against the # of lights */
-         if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {
-            _mesa_set_program_error (ctx, Program->Position,
-                                     "Invalid Light Number");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-                         "Invalid Light Number: %d", state_tokens[1]);
-            return 1;
-         }
-
-         state_tokens[2] = parse_face_type (inst);
-         switch (*(*inst)++) {
-            case LIGHT_PROD_AMBIENT:
-               state_tokens[3] = STATE_AMBIENT;
-               break;
-            case LIGHT_PROD_DIFFUSE:
-               state_tokens[3] = STATE_DIFFUSE;
-               break;
-            case LIGHT_PROD_SPECULAR:
-               state_tokens[3] = STATE_SPECULAR;
-               break;
-         }
-         break;
-
-
-      case STATE_FOG:
-         switch (*(*inst)++) {
-            case FOG_COLOR:
-               state_tokens[0] = STATE_FOG_COLOR;
-               break;
-            case FOG_PARAMS:
-               state_tokens[0] = STATE_FOG_PARAMS;
-               break;
-         }
-         break;
-
-      case STATE_TEX_ENV:
-         state_tokens[1] = parse_integer (inst, Program);
-         switch (*(*inst)++) {
-            case TEX_ENV_COLOR:
-               state_tokens[0] = STATE_TEXENV_COLOR;
-               break;
-         }
-         break;
-
-      case STATE_TEX_GEN:
-         {
-            GLuint type, coord;
-
-            state_tokens[0] = STATE_TEXGEN;
-            /*state_tokens[1] = parse_integer (inst, Program);*/    /* Texture Unit */
-
-            if (parse_texcoord_num (ctx, inst, Program, &coord))
-               return 1;
-	    state_tokens[1] = coord;
-
-            /* EYE or OBJECT */
-            type = *(*inst++);
-
-            /* 0 - s, 1 - t, 2 - r, 3 - q */
-            coord = *(*inst++);
-
-            if (type == TEX_GEN_EYE) {
-               switch (coord) {
-                  case COMPONENT_X:
-                     state_tokens[2] = STATE_TEXGEN_EYE_S;
-                     break;
-                  case COMPONENT_Y:
-                     state_tokens[2] = STATE_TEXGEN_EYE_T;
-                     break;
-                  case COMPONENT_Z:
-                     state_tokens[2] = STATE_TEXGEN_EYE_R;
-                     break;
-                  case COMPONENT_W:
-                     state_tokens[2] = STATE_TEXGEN_EYE_Q;
-                     break;
-               }
-            }
-            else {
-               switch (coord) {
-                  case COMPONENT_X:
-                     state_tokens[2] = STATE_TEXGEN_OBJECT_S;
-                     break;
-                  case COMPONENT_Y:
-                     state_tokens[2] = STATE_TEXGEN_OBJECT_T;
-                     break;
-                  case COMPONENT_Z:
-                     state_tokens[2] = STATE_TEXGEN_OBJECT_R;
-                     break;
-                  case COMPONENT_W:
-                     state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
-                     break;
-               }
-            }
-         }
-         break;
-
-      case STATE_DEPTH:
-         switch (*(*inst)++) {
-            case DEPTH_RANGE:
-               state_tokens[0] = STATE_DEPTH_RANGE;
-               break;
-         }
-         break;
-
-      case STATE_CLIP_PLANE:
-         state_tokens[0] = STATE_CLIPPLANE;
-         state_tokens[1] = parse_integer (inst, Program);
-         if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
-            return 1;
-         break;
-
-      case STATE_POINT:
-         switch (*(*inst++)) {
-            case POINT_SIZE:
-               state_tokens[0] = STATE_POINT_SIZE;
-               break;
-
-            case POINT_ATTENUATION:
-               state_tokens[0] = STATE_POINT_ATTENUATION;
-               break;
-         }
-         break;
-
-         /* XXX: I think this is the correct format for a matrix row */
-      case STATE_MATRIX_ROWS:
-         state_tokens[0] = STATE_MATRIX;
-         if (parse_matrix
-             (ctx, inst, Program, &state_tokens[1], &state_tokens[2],
-              &state_tokens[5]))
-            return 1;
-
-         state_tokens[3] = parse_integer (inst, Program);       /* The first row to grab */
-
-         if ((**inst) != 0) {                                   /* Either the last row, 0 */
-            state_tokens[4] = parse_integer (inst, Program);
-            if (state_tokens[4] < state_tokens[3]) {
-               _mesa_set_program_error (ctx, Program->Position,
-                     "Second matrix index less than the first");
-               _mesa_error (ctx, GL_INVALID_OPERATION,
-                     "Second matrix index (%d) less than the first (%d)",
-                     state_tokens[4], state_tokens[3]);
-               return 1;
-            }
-         }
-         else {
-            state_tokens[4] = state_tokens[3];
-            (*inst)++;
-         }
-         break;
-   }
-
-   return 0;
-}
-
-/**
- * This parses a state string (rather, the binary version of it) into
- * a 6-token similar for the state fetching code in program.c
- *
- * One might ask, why fetch these parameters into just like  you fetch
- * state when they are already stored in other places?
- *
- * Because of array offsets -> We can stick env/local parameters in the
- * middle of a parameter array and then index someplace into the array
- * when we execute.
- *
- * One optimization might be to only do this for the cases where the
- * env/local parameters end up inside of an array, and leave the
- * single parameters (or arrays of pure env/local pareameters) in their
- * respective register files.
- *
- * For ENV parameters, the format is:
- *    state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
- *    state_tokens[1] = STATE_ENV
- *    state_tokens[2] = the parameter index
- *
- * for LOCAL parameters, the format is:
- *    state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
- *    state_tokens[1] = STATE_LOCAL
- *    state_tokens[2] = the parameter index
- *
- * \param inst         - the start in the binary arry to start working from
- * \param state_tokens - the storage for the 6-token state description
- * \return             - 0 on sucess, 1 on failure
- */
-static GLuint
-parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
-                           struct arb_program *Program, GLint * state_tokens)
-{
-   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
-      state_tokens[0] = STATE_FRAGMENT_PROGRAM;
-   else
-      state_tokens[0] = STATE_VERTEX_PROGRAM;
-
-
-   switch (*(*inst)++) {
-      case PROGRAM_PARAM_ENV:
-         state_tokens[1] = STATE_ENV;
-         state_tokens[2] = parse_integer (inst, Program);
-
-         /* Check state_tokens[2] against the number of ENV parameters available */
-         if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
-              (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramEnvParams))
-             ||
-             ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
-              (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {
-            _mesa_set_program_error (ctx, Program->Position,
-                                     "Invalid Program Env Parameter");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-                         "Invalid Program Env Parameter: %d",
-                         state_tokens[2]);
-            return 1;
-         }
-
-         break;
-
-      case PROGRAM_PARAM_LOCAL:
-         state_tokens[1] = STATE_LOCAL;
-         state_tokens[2] = parse_integer (inst, Program);
-
-         /* Check state_tokens[2] against the number of LOCAL parameters available */
-         if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
-              (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramLocalParams))
-             ||
-             ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
-              (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {
-            _mesa_set_program_error (ctx, Program->Position,
-                                     "Invalid Program Local Parameter");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-                         "Invalid Program Local Parameter: %d",
-                         state_tokens[2]);
-            return 1;
-         }
-         break;
-   }
-
-   return 0;
-}
-
-/**
- * For ARB_vertex_program, programs are not allowed to use both an explicit
- * vertex attribute and a generic vertex attribute corresponding to the same
- * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
- *
- * This will walk our var_cache and make sure that nobody does anything fishy.
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-generic_attrib_check(struct var_cache *vc_head)
-{
-   int a;
-   struct var_cache *curr;
-   GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],
-      genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];
-
-   for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
-      explicitAttrib[a] = GL_FALSE;
-      genericAttrib[a] = GL_FALSE;
-   }
-
-   curr = vc_head;
-   while (curr) {
-      if (curr->type == vt_attrib) {
-         if (curr->attrib_is_generic)
-            genericAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
-         else
-            explicitAttrib[ curr->attrib_binding_idx ] = GL_TRUE;
-      }
-
-      curr = curr->next;
-   }
-
-   for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
-      if ((explicitAttrib[a]) && (genericAttrib[a]))
-         return 1;
-   }
-
-   return 0;
-}
-
-/**
- * This will handle the binding side of an ATTRIB var declaration
- *
- * \param binding     - the fragment input register state, defined in nvfragprog.h
- * \param binding_idx - the index in the attrib register file that binding is associated with
- * \return returns 0 on sucess, 1 on error
- *
- * See nvfragparse.c for attrib register file layout
- */
-static GLuint
-parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,
-                      struct arb_program *Program, GLuint * binding,
-                      GLuint * binding_idx, GLuint *is_generic)
-{
-   GLuint texcoord;
-   GLint coord;
-   GLint err = 0;
-
-   *is_generic = 0;
-   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
-      switch (*(*inst)++) {
-         case FRAGMENT_ATTRIB_COLOR:
-            err = parse_color_type (ctx, inst, Program, &coord);
-            *binding = FRAG_ATTRIB_COL0 + coord;
-            *binding_idx = 1 + coord;
-            break;
-
-         case FRAGMENT_ATTRIB_TEXCOORD:
-            err = parse_texcoord_num (ctx, inst, Program, &texcoord);
-            *binding = FRAG_ATTRIB_TEX0 + texcoord;
-            *binding_idx = 4 + texcoord;
-            break;
-
-         case FRAGMENT_ATTRIB_FOGCOORD:
-            *binding = FRAG_ATTRIB_FOGC;
-            *binding_idx = 3;
-            break;
-
-         case FRAGMENT_ATTRIB_POSITION:
-            *binding = FRAG_ATTRIB_WPOS;
-            *binding_idx = 0;
-            break;
-
-         default:
-            err = 1;
-            break;
-      }
-   }
-   else {
-      switch (*(*inst)++) {
-         case VERTEX_ATTRIB_POSITION:
-            *binding = VERT_ATTRIB_POS;
-            *binding_idx = 0;
-            break;
-
-         case VERTEX_ATTRIB_WEIGHT:
-            {
-               GLint weight;
-
-               err = parse_weight_num (ctx, inst, Program, &weight);
-               *binding = VERT_ATTRIB_WEIGHT;
-               *binding_idx = 1;
-            }
-            _mesa_set_program_error (ctx, Program->Position,
-                 "ARB_vertex_blend not supported\n");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-                 "ARB_vertex_blend not supported\n");
-            return 1;
-            break;
-
-         case VERTEX_ATTRIB_NORMAL:
-            *binding = VERT_ATTRIB_NORMAL;
-            *binding_idx = 2;
-            break;
-
-         case VERTEX_ATTRIB_COLOR:
-            {
-               GLint color;
-
-               err = parse_color_type (ctx, inst, Program, &color);
-               if (color) {
-                  *binding = VERT_ATTRIB_COLOR1;
-                  *binding_idx = 4;
-               }
-               else {
-                  *binding = VERT_ATTRIB_COLOR0;
-                  *binding_idx = 3;
-               }
-            }
-            break;
-
-         case VERTEX_ATTRIB_FOGCOORD:
-            *binding = VERT_ATTRIB_FOG;
-            *binding_idx = 5;
-            break;
-
-         case VERTEX_ATTRIB_TEXCOORD:
-            {
-               GLuint unit;
-
-               err = parse_texcoord_num (ctx, inst, Program, &unit);
-               *binding = VERT_ATTRIB_TEX0 + unit;
-               *binding_idx = 8 + unit;
-            }
-            break;
-
-            /* It looks like we don't support this at all, atm */
-         case VERTEX_ATTRIB_MATRIXINDEX:
-            parse_integer (inst, Program);
-            _mesa_set_program_error (ctx, Program->Position,
-                  "ARB_palette_matrix not supported");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-                  "ARB_palette_matrix not supported");
-            return 1;
-            break;
-
-         case VERTEX_ATTRIB_GENERIC:
-            {
-               GLuint attrib;
-
-               if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
-                  *is_generic = 1;
-                  switch (attrib) {
-                     case 0:
-                        *binding = VERT_ATTRIB_POS;
-                        break;
-                     case 1:
-                        *binding = VERT_ATTRIB_WEIGHT;
-                        break;
-                     case 2:
-                        *binding = VERT_ATTRIB_NORMAL;
-                        break;
-                     case 3:
-                        *binding = VERT_ATTRIB_COLOR0;
-                        break;
-                     case 4:
-                        *binding = VERT_ATTRIB_COLOR1;
-                        break;
-                     case 5:
-                        *binding = VERT_ATTRIB_FOG;
-                        break;
-                     case 6:
-                        break;
-                     case 7:
-                        break;
-                     default:
-                        *binding = VERT_ATTRIB_TEX0 + (attrib-8);
-                        break;
-                  }
-                  *binding_idx = attrib;
-               }
-            }
-            break;
-
-         default:
-            err = 1;
-            break;
-      }
-   }
-
-   /* Can this even happen? */
-   if (err) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Bad attribute binding");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Bad attribute binding");
-   }
-
-   Program->InputsRead |= (1 << *binding_idx);
-
-   return err;
-}
-
-/**
- * This translates between a binary token for an output variable type
- * and the mesa token for the same thing.
- *
- *
- * XXX: What is the 'name' for vertex program state? -> do we need it?
- *         I don't think we do;
- *
- * See nvfragprog.h for definitions
- *
- * \param inst        - The parsed tokens
- * \param binding     - The name of the state we are binding too
- * \param binding_idx - The index into the result register file that this is bound too
- *
- * See nvfragparse.c for the register file layout for fragment programs
- * See nvvertparse.c for the register file layout for vertex programs
- */
-static GLuint
-parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,
-                      GLuint * binding_idx, struct arb_program *Program)
-{
-   GLuint b;
-
-   switch (*(*inst)++) {
-      case FRAGMENT_RESULT_COLOR:
-         /* for frag programs, this is FRAGMENT_RESULT_COLOR */
-         if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
-            *binding = FRAG_OUTPUT_COLR;
-            *binding_idx = 0;
-         }
-         /* for vtx programs, this is VERTEX_RESULT_POSITION */
-         else {
-            *binding_idx = 0;
-         }
-         break;
-
-      case FRAGMENT_RESULT_DEPTH:
-         /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
-         if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
-            *binding = FRAG_OUTPUT_DEPR;
-            *binding_idx = 2;
-         }
-         /* for vtx programs, this is VERTEX_RESULT_COLOR */
-         else {
-            GLint color_type;
-            GLuint face_type = parse_face_type(inst);
-	    GLint color_type_ret = parse_color_type(ctx, inst, Program, &color_type);
-
-            /* back face */
-            if (face_type) {
-               if (color_type_ret) return 1;
-
-               /* secondary color */
-               if (color_type) {
-                  *binding_idx = 4;
-               }
-               /*  primary color */
-               else {
-                  *binding_idx = 3;
-               }
-            }
-            /* front face */
-            else {
-               /* secondary color */
-               if (color_type) {
-                  *binding_idx = 2;
-               }
-               /* primary color */
-               else {
-                  *binding_idx = 1;
-               }
-            }
-         }
-         break;
-
-      case VERTEX_RESULT_FOGCOORD:
-         *binding_idx = 5;
-         break;
-
-      case VERTEX_RESULT_POINTSIZE:
-         *binding_idx = 6;
-         break;
-
-      case VERTEX_RESULT_TEXCOORD:
-         if (parse_texcoord_num (ctx, inst, Program, &b))
-            return 1;
-         *binding_idx = 7 + b;
-         break;
-   }
-
-   Program->OutputsWritten |= (1 << *binding_idx);
-
-   return 0;
-}
-
-/**
- * This handles the declaration of ATTRIB variables
- *
- * XXX: Still needs
- *      parse_vert_attrib_binding(), or something like that
- *
- * \return 0 on sucess, 1 on error
- */
-static GLint
-parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-              struct arb_program *Program)
-{
-   GLuint found;
-   char *error_msg;
-   struct var_cache *attrib_var;
-
-   attrib_var = parse_string (inst, vc_head, Program, &found);
-   Program->Position = parse_position (inst);
-   if (found) {
-      error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
-      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                     attrib_var->name);
-
-      _mesa_set_program_error (ctx, Program->Position, error_msg);
-      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
-
-      _mesa_free (error_msg);
-      return 1;
-   }
-
-   attrib_var->type = vt_attrib;
-
-   /* I think this is ok now - karl */
-   /* XXX: */
-   /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
-   {
-      if (parse_attrib_binding
-          (ctx, inst, Program, &attrib_var->attrib_binding,
-           &attrib_var->attrib_binding_idx, &attrib_var->attrib_is_generic))
-         return 1;
-      if (generic_attrib_check(*vc_head)) {
-         _mesa_set_program_error (ctx, Program->Position,
-   "Cannot use both a generic vertex attribute and a specific attribute of the same type");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-   "Cannot use both a generic vertex attribute and a specific attribute of the same type");
-         return 1;
-      }
-
-   }
-
-   Program->Base.NumAttributes++;
-   return 0;
-}
-
-/**
- * \param use -- TRUE if we're called when declaring implicit parameters,
- *               FALSE if we're declaraing variables. This has to do with
- *               if we get a signed or unsigned float for scalar constants
- */
-static GLuint
-parse_param_elements (GLcontext * ctx, GLubyte ** inst,
-                      struct var_cache *param_var,
-                      struct arb_program *Program, GLboolean use)
-{
-   GLint idx;
-   GLuint err;
-   GLint state_tokens[6];
-   GLfloat const_values[4];
-
-   err = 0;
-
-   switch (*(*inst)++) {
-      case PARAM_STATE_ELEMENT:
-
-         if (parse_state_single_item (ctx, inst, Program, state_tokens))
-            return 1;
-
-         /* If we adding STATE_MATRIX that has multiple rows, we need to
-          * unroll it and call _mesa_add_state_reference() for each row
-          */
-         if ((state_tokens[0] == STATE_MATRIX)
-             && (state_tokens[3] != state_tokens[4])) {
-            GLint row;
-            GLint first_row = state_tokens[3];
-            GLint last_row = state_tokens[4];
-
-            for (row = first_row; row <= last_row; row++) {
-               state_tokens[3] = state_tokens[4] = row;
-
-               idx =
-                  _mesa_add_state_reference (Program->Parameters,
-                                             state_tokens);
-               if (param_var->param_binding_begin == ~0U)
-                  param_var->param_binding_begin = idx;
-               param_var->param_binding_length++;
-               Program->Base.NumParameters++;
-            }
-         }
-         else {
-            idx =
-               _mesa_add_state_reference (Program->Parameters, state_tokens);
-            if (param_var->param_binding_begin == ~0U)
-               param_var->param_binding_begin = idx;
-            param_var->param_binding_length++;
-            Program->Base.NumParameters++;
-         }
-         break;
-
-      case PARAM_PROGRAM_ELEMENT:
-
-         if (parse_program_single_item (ctx, inst, Program, state_tokens))
-            return 1;
-         idx = _mesa_add_state_reference (Program->Parameters, state_tokens);
-         if (param_var->param_binding_begin == ~0U)
-            param_var->param_binding_begin = idx;
-         param_var->param_binding_length++;
-         Program->Base.NumParameters++;
-
-         /* Check if there is more: 0 -> we're done, else its an integer */
-         if (**inst) {
-            GLuint out_of_range, new_idx;
-            GLuint start_idx = state_tokens[2] + 1;
-            GLuint end_idx = parse_integer (inst, Program);
-
-            out_of_range = 0;
-            if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
-               if (((state_tokens[1] == STATE_ENV)
-                    && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
-                   || ((state_tokens[1] == STATE_LOCAL)
-                       && (end_idx >=
-                           ctx->Const.MaxFragmentProgramLocalParams)))
-                  out_of_range = 1;
-            }
-            else {
-               if (((state_tokens[1] == STATE_ENV)
-                    && (end_idx >= ctx->Const.MaxVertexProgramEnvParams))
-                   || ((state_tokens[1] == STATE_LOCAL)
-                       && (end_idx >=
-                           ctx->Const.MaxVertexProgramLocalParams)))
-                  out_of_range = 1;
-            }
-            if (out_of_range) {
-               _mesa_set_program_error (ctx, Program->Position,
-                                        "Invalid Program Parameter");
-               _mesa_error (ctx, GL_INVALID_OPERATION,
-                            "Invalid Program Parameter: %d", end_idx);
-               return 1;
-            }
-
-            for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
-               state_tokens[2] = new_idx;
-               idx =
-                  _mesa_add_state_reference (Program->Parameters,
-                                             state_tokens);
-               param_var->param_binding_length++;
-               Program->Base.NumParameters++;
-            }
-         }
-			else
-			{
-				(*inst)++;
-			}
-         break;
-
-      case PARAM_CONSTANT:
-         parse_constant (inst, const_values, Program, use);
-         idx =
-            _mesa_add_named_constant (Program->Parameters,
-                                      (char *) param_var->name, const_values);
-         if (param_var->param_binding_begin == ~0U)
-            param_var->param_binding_begin = idx;
-         param_var->param_binding_length++;
-         Program->Base.NumParameters++;
-         break;
-
-      default:
-         _mesa_set_program_error (ctx, Program->Position,
-                                  "Unexpected token in parse_param_elements()");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Unexpected token in parse_param_elements()");
-         return 1;
-   }
-
-   /* Make sure we haven't blown past our parameter limits */
-   if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
-        (Program->Base.NumParameters >=
-         ctx->Const.MaxVertexProgramLocalParams))
-       || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
-           && (Program->Base.NumParameters >=
-               ctx->Const.MaxFragmentProgramLocalParams))) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Too many parameter variables");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
-      return 1;
-   }
-
-   return err;
-}
-
-/**
- * This picks out PARAM program parameter bindings.
- *
- * XXX: This needs to be stressed & tested
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-             struct arb_program *Program)
-{
-   GLuint found, specified_length, err;
-   char *error_msg;
-   struct var_cache *param_var;
-
-   err = 0;
-   param_var = parse_string (inst, vc_head, Program, &found);
-   Program->Position = parse_position (inst);
-
-   if (found) {
-      error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
-      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                     param_var->name);
-
-      _mesa_set_program_error (ctx, Program->Position, error_msg);
-      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
-
-      _mesa_free (error_msg);
-      return 1;
-   }
-
-   specified_length = parse_integer (inst, Program);
-
-   if (specified_length < 0) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Negative parameter array length");
-      _mesa_error (ctx, GL_INVALID_OPERATION,
-                   "Negative parameter array length: %d", specified_length);
-      return 1;
-   }
-
-   param_var->type = vt_param;
-   param_var->param_binding_length = 0;
-
-   /* Right now, everything is shoved into the main state register file.
-    *
-    * In the future, it would be nice to leave things ENV/LOCAL params
-    * in their respective register files, if possible
-    */
-   param_var->param_binding_type = PROGRAM_STATE_VAR;
-
-   /* Remember to:
-    * *   - add each guy to the parameter list
-    * *   - increment the param_var->param_binding_len
-    * *   - store the param_var->param_binding_begin for the first one
-    * *   - compare the actual len to the specified len at the end
-    */
-   while (**inst != PARAM_NULL) {
-      if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
-         return 1;
-   }
-
-   /* Test array length here! */
-   if (specified_length) {
-      if (specified_length != param_var->param_binding_length) {
-         _mesa_set_program_error (ctx, Program->Position,
-                                  "Declared parameter array lenght does not match parameter list");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Declared parameter array lenght does not match parameter list");
-      }
-   }
-
-   (*inst)++;
-
-   return 0;
-}
-
-/**
- *
- */
-static GLuint
-parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-                 struct arb_program *Program, struct var_cache **new_var)
-{
-   struct var_cache *param_var;
-
-   /* First, insert a dummy entry into the var_cache */
-   var_cache_create (&param_var);
-   param_var->name = (GLubyte *) _mesa_strdup (" ");
-   param_var->type = vt_param;
-
-   param_var->param_binding_length = 0;
-   /* Don't fill in binding_begin; We use the default value of -1
-    * to tell if its already initialized, elsewhere.
-    *
-    * param_var->param_binding_begin  = 0;
-    */
-   param_var->param_binding_type = PROGRAM_STATE_VAR;
-
-   var_cache_append (vc_head, param_var);
-
-   /* Then fill it with juicy parameter goodness */
-   if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
-      return 1;
-
-   *new_var = param_var;
-
-   return 0;
-}
-
-
-/**
- * This handles the declaration of TEMP variables
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-            struct arb_program *Program)
-{
-   GLuint found;
-   struct var_cache *temp_var;
-   char *error_msg;
-
-   while (**inst != 0) {
-      temp_var = parse_string (inst, vc_head, Program, &found);
-      Program->Position = parse_position (inst);
-      if (found) {
-         error_msg = (char *)
-            _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
-         _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                        temp_var->name);
-
-         _mesa_set_program_error (ctx, Program->Position, error_msg);
-         _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
-
-         _mesa_free (error_msg);
-         return 1;
-      }
-
-      temp_var->type = vt_temp;
-
-      if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&
-           (Program->Base.NumTemporaries >=
-            ctx->Const.MaxFragmentProgramTemps))
-          || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
-              && (Program->Base.NumTemporaries >=
-                  ctx->Const.MaxVertexProgramTemps))) {
-         _mesa_set_program_error (ctx, Program->Position,
-                                  "Too many TEMP variables declared");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Too many TEMP variables declared");
-         return 1;
-      }
-
-      temp_var->temp_binding = Program->Base.NumTemporaries;
-      Program->Base.NumTemporaries++;
-   }
-   (*inst)++;
-
-   return 0;
-}
-
-/**
- * This handles variables of the OUTPUT variety
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-              struct arb_program *Program)
-{
-   GLuint found;
-   struct var_cache *output_var;
-
-   output_var = parse_string (inst, vc_head, Program, &found);
-   Program->Position = parse_position (inst);
-   if (found) {
-      char *error_msg;
-      error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
-      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                     output_var->name);
-
-      _mesa_set_program_error (ctx, Program->Position, error_msg);
-      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
-
-      _mesa_free (error_msg);
-      return 1;
-   }
-
-   output_var->type = vt_output;
-   return parse_result_binding (ctx, inst, &output_var->output_binding,
-                                &output_var->output_binding_idx, Program);
-}
-
-/**
- * This handles variables of the ALIAS kind
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-             struct arb_program *Program)
-{
-   GLuint found;
-   struct var_cache *temp_var;
-   char *error_msg;
-
-
-   temp_var = parse_string (inst, vc_head, Program, &found);
-   Program->Position = parse_position (inst);
-
-   if (found) {
-      error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
-      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                     temp_var->name);
-
-      _mesa_set_program_error (ctx, Program->Position, error_msg);
-      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
-
-      _mesa_free (error_msg);
-      return 1;
-   }
-
-   temp_var->type = vt_alias;
-   temp_var->alias_binding =  parse_string (inst, vc_head, Program, &found);
-   Program->Position = parse_position (inst);
-
-   if (!found)
-   {
-      error_msg = (char *)
-         _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
-      _mesa_sprintf (error_msg, "Alias value %s is not defined",
-                     temp_var->alias_binding->name);
-
-      _mesa_set_program_error (ctx, Program->Position, error_msg);
-      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
-
-      _mesa_free (error_msg);
-      return 1;
-   }
-
-   return 0;
-}
-
-/**
- * This handles variables of the ADDRESS kind
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-               struct arb_program *Program)
-{
-   GLuint found;
-   struct var_cache *temp_var;
-   char *error_msg;
-
-   while (**inst != 0) {
-      temp_var = parse_string (inst, vc_head, Program, &found);
-      Program->Position = parse_position (inst);
-      if (found) {
-         error_msg = (char *)
-            _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
-         _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
-                        temp_var->name);
-
-         _mesa_set_program_error (ctx, Program->Position, error_msg);
-         _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
-
-         _mesa_free (error_msg);
-         return 1;
-      }
-
-      temp_var->type = vt_address;
-
-      if (Program->Base.NumAddressRegs >=
-          ctx->Const.MaxVertexProgramAddressRegs) {
-         _mesa_set_program_error (ctx, Program->Position,
-                                  "Too many ADDRESS variables declared");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Too many ADDRESS variables declared");
-         return 1;
-      }
-
-      temp_var->address_binding = Program->Base.NumAddressRegs;
-      Program->Base.NumAddressRegs++;
-   }
-   (*inst)++;
-
-   return 0;
-}
-
-/**
- * Parse a program declaration
- *
- * \return 0 on sucess, 1 on error
- */
-static GLint
-parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-                   struct arb_program *Program)
-{
-   GLint err = 0;
-
-   switch (*(*inst)++) {
-      case ADDRESS:
-         err = parse_address (ctx, inst, vc_head, Program);
-         break;
-
-      case ALIAS:
-         err = parse_alias (ctx, inst, vc_head, Program);
-         break;
-
-      case ATTRIB:
-         err = parse_attrib (ctx, inst, vc_head, Program);
-         break;
-
-      case OUTPUT:
-         err = parse_output (ctx, inst, vc_head, Program);
-         break;
-
-      case PARAM:
-         err = parse_param (ctx, inst, vc_head, Program);
-         break;
-
-      case TEMP:
-         err = parse_temp (ctx, inst, vc_head, Program);
-         break;
-   }
-
-   return err;
-}
-
-/**
- * Handle the parsing out of a masked destination register
- *
- * If we are a vertex program, make sure we don't write to
- * result.position of we have specified that the program is
- * position invariant
- *
- * \param File      - The register file we write to
- * \param Index     - The register index we write to
- * \param WriteMask - The mask controlling which components we write (1->write)
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
-                      struct var_cache **vc_head, struct arb_program *Program,
-                      GLint * File, GLint * Index, GLboolean * WriteMask)
-{
-   GLuint result;
-   GLubyte mask;
-   struct var_cache *dst;
-
-   /* We either have a result register specified, or a
-    * variable that may or may not be writable
-    */
-   switch (*(*inst)++) {
-      case REGISTER_RESULT:
-         if (parse_result_binding
-             (ctx, inst, &result, (GLuint *) Index, Program))
-            return 1;
-         *File = PROGRAM_OUTPUT;
-         break;
-
-      case REGISTER_ESTABLISHED_NAME:
-         dst = parse_string (inst, vc_head, Program, &result);
-         Program->Position = parse_position (inst);
-
-         /* If the name has never been added to our symbol table, we're hosed */
-         if (!result) {
-            _mesa_set_program_error (ctx, Program->Position,
-                                     "0: Undefined variable");
-            _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
-                         dst->name);
-            return 1;
-         }
-
-         switch (dst->type) {
-            case vt_output:
-               *File = PROGRAM_OUTPUT;
-               *Index = dst->output_binding_idx;
-               break;
-
-            case vt_temp:
-               *File = PROGRAM_TEMPORARY;
-               *Index = dst->temp_binding;
-               break;
-
-               /* If the var type is not vt_output or vt_temp, no go */
-            default:
-               _mesa_set_program_error (ctx, Program->Position,
-                                        "Destination register is read only");
-               _mesa_error (ctx, GL_INVALID_OPERATION,
-                            "Destination register is read only: %s",
-                            dst->name);
-               return 1;
-         }
-         break;
-
-      default:
-         _mesa_set_program_error (ctx, Program->Position,
-                                  "Unexpected opcode in parse_masked_dst_reg()");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Unexpected opcode in parse_masked_dst_reg()");
-         return 1;
-   }
-
-
-   /* Position invariance test */
-   /* This test is done now in syntax portion - when position invariance OPTION
-      is specified, "result.position" rule is disabled so there is no way
-      to write the position
-   */
-   /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&
-      (*Index == 0))   {
-      _mesa_set_program_error (ctx, Program->Position,
-                  "Vertex program specified position invariance and wrote vertex position");
-      _mesa_error (ctx, GL_INVALID_OPERATION,
-                  "Vertex program specified position invariance and wrote vertex position");
-   }*/
-
-   /* And then the mask.
-    *  w,a -> bit 0
-    *  z,b -> bit 1
-    *  y,g -> bit 2
-    *  x,r -> bit 3
-    */
-   mask = *(*inst)++;
-
-   WriteMask[0] = (GLboolean) (mask & (1 << 3)) >> 3;
-   WriteMask[1] = (GLboolean) (mask & (1 << 2)) >> 2;
-   WriteMask[2] = (GLboolean) (mask & (1 << 1)) >> 1;
-   WriteMask[3] = (GLboolean) (mask & (1));
-
-   return 0;
-}
-
-
-/**
- * Handle the parsing of a address register
- *
- * \param Index     - The register index we write to
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_address_reg (GLcontext * ctx, GLubyte ** inst,
-                          struct var_cache **vc_head,
-                          struct arb_program *Program, GLint * Index)
-{
-   struct var_cache *dst;
-   GLuint result;
-
-   dst = parse_string (inst, vc_head, Program, &result);
-   Program->Position = parse_position (inst);
-
-   /* If the name has never been added to our symbol table, we're hosed */
-   if (!result) {
-      _mesa_set_program_error (ctx, Program->Position, "Undefined variable");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",
-                   dst->name);
-      return 1;
-   }
-
-   if (dst->type != vt_address) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Variable is not of type ADDRESS");
-      _mesa_error (ctx, GL_INVALID_OPERATION,
-                   "Variable: %s is not of type ADDRESS", dst->name);
-      return 1;
-   }
-
-   return 0;
-}
-
-/**
- * Handle the parsing out of a masked address register
- *
- * \param Index     - The register index we write to
- * \param WriteMask - The mask controlling which components we write (1->write)
- *
- * \return 0 on sucess, 1 on error
- */
-static GLuint
-parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
-                          struct var_cache **vc_head,
-                          struct arb_program *Program, GLint * Index,
-                          GLboolean * WriteMask)
-{
-   if (parse_address_reg (ctx, inst, vc_head, Program, Index))
-      return 1;
-
-   /* This should be 0x8 */
-   (*inst)++;
-
-   /* Writemask of .x is implied */
-   WriteMask[0] = 1;
-   WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
-
-   return 0;
-}
-
-
-/**
- * Parse out a swizzle mask.
- *
- * The values in the input stream are:
- *   COMPONENT_X -> x/r
- *   COMPONENT_Y -> y/g
- *   COMPONENT_Z-> z/b
- *   COMPONENT_W-> w/a
- *
- * The values in the output mask are:
- *   0 -> x/r
- *   1 -> y/g
- *   2 -> z/b
- *   3 -> w/a
- *
- * The len parameter allows us to grab 4 components for a vector
- * swizzle, or just 1 component for a scalar src register selection
- */
-static GLuint
-parse_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLint len)
-{
-   GLint a;
-
-   for (a = 0; a < 4; a++)
-      mask[a] = a;
-
-   for (a = 0; a < len; a++) {
-      switch (*(*inst)++) {
-         case COMPONENT_X:
-            mask[a] = 0;
-            break;
-
-         case COMPONENT_Y:
-            mask[a] = 1;
-            break;
-
-         case COMPONENT_Z:
-            mask[a] = 2;
-            break;
-
-         case COMPONENT_W:
-            mask[a] = 3;
-            break;
-      }
-   }
-
-   return 0;
-}
-
-/**
- */
-static GLuint
-parse_extended_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLboolean * Negate)
-{
-   GLint a;
-   GLubyte swz;
-
-   *Negate = GL_FALSE;
-   for (a = 0; a < 4; a++) {
-      if (parse_sign (inst))
-         *Negate = GL_TRUE;
-
-      swz = *(*inst)++;
-
-      switch (swz) {
-         case COMPONENT_0:
-            mask[a] = SWIZZLE_ZERO;
-            break;
-         case COMPONENT_1:
-            mask[a] = SWIZZLE_ONE;
-            break;
-         case COMPONENT_X:
-            mask[a] = SWIZZLE_X;
-            break;
-         case COMPONENT_Y:
-            mask[a] = SWIZZLE_Y;
-            break;
-         case COMPONENT_Z:
-            mask[a] = SWIZZLE_Z;
-            break;
-         case COMPONENT_W:
-            mask[a] = SWIZZLE_W;
-            break;
-
-      }
-#if 0
-      if (swz == 0)
-         mask[a] = SWIZZLE_ZERO;
-      else if (swz == 1)
-         mask[a] = SWIZZLE_ONE;
-      else
-         mask[a] = swz - 2;
-#endif
-
-   }
-
-   return 0;
-}
-
-
-static GLuint
-parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
-               struct arb_program *Program, GLint * File, GLint * Index,
-               GLboolean *IsRelOffset )
-{
-   struct var_cache *src;
-   GLuint binding_state, binding_idx, is_generic, found, offset;
-
-   /* And the binding for the src */
-   switch (*(*inst)++) {
-      case REGISTER_ATTRIB:
-         if (parse_attrib_binding
-             (ctx, inst, Program, &binding_state, &binding_idx, &is_generic))
-            return 1;
-         *File = PROGRAM_INPUT;
-         *Index = binding_idx;
-
-         /* We need to insert a dummy variable into the var_cache so we can
-          * catch generic vertex attrib aliasing errors
-          */
-         var_cache_create(&src);
-         src->type = vt_attrib;
-         src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
-         src->attrib_binding     = binding_state;
-         src->attrib_binding_idx = binding_idx;
-         src->attrib_is_generic  = is_generic;
-         var_cache_append(vc_head, src);
-         if (generic_attrib_check(*vc_head)) {
-            _mesa_set_program_error (ctx, Program->Position,
-   "Cannot use both a generic vertex attribute and a specific attribute of the same type");
-            _mesa_error (ctx, GL_INVALID_OPERATION,
-   "Cannot use both a generic vertex attribute and a specific attribute of the same type");
-            return 1;
-         }
-         break;
-
-      case REGISTER_PARAM:
-         switch (**inst) {
-            case PARAM_ARRAY_ELEMENT:
-               (*inst)++;
-               src = parse_string (inst, vc_head, Program, &found);
-               Program->Position = parse_position (inst);
-
-               if (!found) {
-                  _mesa_set_program_error (ctx, Program->Position,
-                                           "2: Undefined variable");
-                  _mesa_error (ctx, GL_INVALID_OPERATION,
-                               "2: Undefined variable: %s", src->name);
-                  return 1;
-               }
-
-               *File = src->param_binding_type;
-
-               switch (*(*inst)++) {
-                  case ARRAY_INDEX_ABSOLUTE:
-                     offset = parse_integer (inst, Program);
-
-                     if ((offset < 0)
-                         || (offset >= src->param_binding_length)) {
-                        _mesa_set_program_error (ctx, Program->Position,
-                                                 "Index out of range");
-                        _mesa_error (ctx, GL_INVALID_OPERATION,
-                                     "Index %d out of range for %s", offset,
-                                     src->name);
-                        return 1;
-                     }
-
-                     *Index = src->param_binding_begin + offset;
-                     break;
-
-                  case ARRAY_INDEX_RELATIVE:
-                     {
-                        GLint addr_reg_idx, rel_off;
-
-                        /* First, grab the address regiseter */
-                        if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))
-                           return 1;
-
-                        /* And the .x */
-                        ((*inst)++);
-                        ((*inst)++);
-                        ((*inst)++);
-                        ((*inst)++);
-
-                        /* Then the relative offset */
-                        if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;
-
-                        /* And store it properly */
-                        *Index = src->param_binding_begin + rel_off;
-                        *IsRelOffset = 1;
-                     }
-                     break;
-               }
-               break;
-
-            default:
-
-               if (parse_param_use (ctx, inst, vc_head, Program, &src))
-                  return 1;
-
-               *File = src->param_binding_type;
-               *Index = src->param_binding_begin;
-               break;
-         }
-         break;
-
-      case REGISTER_ESTABLISHED_NAME:
-
-         src = parse_string (inst, vc_head, Program, &found);
-         Program->Position = parse_position (inst);
-
-         /* If the name has never been added to our symbol table, we're hosed */
-         if (!found) {
-            _mesa_set_program_error (ctx, Program->Position,
-                                     "3: Undefined variable");
-            _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
-                         src->name);
-            return 1;
-         }
-
-         switch (src->type) {
-            case vt_attrib:
-               *File = PROGRAM_INPUT;
-               *Index = src->attrib_binding_idx;
-               break;
-
-               /* XXX: We have to handle offsets someplace in here!  -- or are those above? */
-            case vt_param:
-               *File = src->param_binding_type;
-               *Index = src->param_binding_begin;
-               break;
-
-            case vt_temp:
-               *File = PROGRAM_TEMPORARY;
-               *Index = src->temp_binding;
-               break;
-
-               /* If the var type is vt_output no go */
-            default:
-               _mesa_set_program_error (ctx, Program->Position,
-                                        "destination register is read only");
-               _mesa_error (ctx, GL_INVALID_OPERATION,
-                            "destination register is read only: %s",
-                            src->name);
-               return 1;
-         }
-         break;
-
-      default:
-         _mesa_set_program_error (ctx, Program->Position,
-                                  "Unknown token in parse_src_reg");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Unknown token in parse_src_reg");
-         return 1;
-   }
-
-   return 0;
-}
-
-/**
- */
-static GLuint
-parse_vector_src_reg (GLcontext * ctx, GLubyte ** inst,
-                      struct var_cache **vc_head, struct arb_program *Program,
-                      GLint * File, GLint * Index, GLboolean * Negate,
-                      GLubyte * Swizzle, GLboolean *IsRelOffset)
-{
-   /* Grab the sign */
-   *Negate = parse_sign (inst);
-
-   /* And the src reg */
-   if (parse_src_reg (ctx, inst, vc_head, Program, File, Index, IsRelOffset))
-      return 1;
-
-   /* finally, the swizzle */
-   parse_swizzle_mask (inst, Swizzle, 4);
-
-   return 0;
-}
-
-/**
- */
-static GLuint
-parse_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
-                      struct var_cache **vc_head, struct arb_program *Program,
-                      GLint * File, GLint * Index, GLboolean * Negate,
-                      GLubyte * Swizzle, GLboolean *IsRelOffset)
-{
-   /* Grab the sign */
-   *Negate = parse_sign (inst);
-
-   /* And the src reg */
-   if (parse_src_reg (ctx, inst, vc_head, Program, File, Index, IsRelOffset))
-      return 1;
-
-   /* Now, get the component and shove it into all the swizzle slots  */
-   parse_swizzle_mask (inst, Swizzle, 1);
-
-   return 0;
-}
-
-/**
- * This is a big mother that handles getting opcodes into the instruction
- * and handling the src & dst registers for fragment program instructions
- */
-static GLuint
-parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
-                      struct var_cache **vc_head, struct arb_program *Program,
-                      struct fp_instruction *fp)
-{
-   GLint a, b;
-   GLubyte swz[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
-   GLuint texcoord;
-   GLubyte instClass, type, code;
-   GLboolean rel;
-
-   /* No condition codes in ARB_fp */
-   fp->UpdateCondRegister = 0;
-
-   /* Record the position in the program string for debugging */
-   fp->StringPos = Program->Position;
-
-   /* OP_ALU_INST or OP_TEX_INST */
-   instClass = *(*inst)++;
-
-   /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
-    * OP_TEX_{SAMPLE, KIL}
-    */
-   type = *(*inst)++;
-
-   /* The actual opcode name */
-   code = *(*inst)++;
-
-   /* Increment the correct count */
-   switch (instClass) {
-      case OP_ALU_INST:
-         Program->NumAluInstructions++;
-         break;
-      case OP_TEX_INST:
-         Program->NumTexInstructions++;
-         break;
-   }
-
-   fp->Saturate = 0;
-   fp->Precision = FLOAT32;
-
-   fp->DstReg.CondMask = COND_TR;
-
-   switch (type) {
-      case OP_ALU_VECTOR:
-         switch (code) {
-            case OP_ABS_SAT:
-               fp->Saturate = 1;
-            case OP_ABS:
-               fp->Opcode = FP_OPCODE_ABS;
-               break;
-
-            case OP_FLR_SAT:
-               fp->Saturate = 1;
-            case OP_FLR:
-               fp->Opcode = FP_OPCODE_FLR;
-               break;
-
-            case OP_FRC_SAT:
-               fp->Saturate = 1;
-            case OP_FRC:
-               fp->Opcode = FP_OPCODE_FRC;
-               break;
-
-            case OP_LIT_SAT:
-               fp->Saturate = 1;
-            case OP_LIT:
-               fp->Opcode = FP_OPCODE_LIT;
-               break;
-
-            case OP_MOV_SAT:
-               fp->Saturate = 1;
-            case OP_MOV:
-               fp->Opcode = FP_OPCODE_MOV;
-               break;
-         }
-
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
-              &fp->DstReg.Index, fp->DstReg.WriteMask))
-            return 1;
-
-         fp->SrcReg[0].Abs = GL_FALSE;
-         fp->SrcReg[0].NegateAbs = GL_FALSE;
-         if (parse_vector_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
-              &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
-              swz, &rel))
-            return 1;
-         for (b=0; b<4; b++)
-            fp->SrcReg[0].Swizzle[b] = swz[b];
-         break;
-
-      case OP_ALU_SCALAR:
-         switch (code) {
-            case OP_COS_SAT:
-               fp->Saturate = 1;
-            case OP_COS:
-               fp->Opcode = FP_OPCODE_COS;
-               break;
-
-            case OP_EX2_SAT:
-               fp->Saturate = 1;
-            case OP_EX2:
-               fp->Opcode = FP_OPCODE_EX2;
-               break;
-
-            case OP_LG2_SAT:
-               fp->Saturate = 1;
-            case OP_LG2:
-               fp->Opcode = FP_OPCODE_LG2;
-               break;
-
-            case OP_RCP_SAT:
-               fp->Saturate = 1;
-            case OP_RCP:
-               fp->Opcode = FP_OPCODE_RCP;
-               break;
-
-            case OP_RSQ_SAT:
-               fp->Saturate = 1;
-            case OP_RSQ:
-               fp->Opcode = FP_OPCODE_RSQ;
-               break;
-
-            case OP_SIN_SAT:
-               fp->Saturate = 1;
-            case OP_SIN:
-               fp->Opcode = FP_OPCODE_SIN;
-               break;
-
-            case OP_SCS_SAT:
-               fp->Saturate = 1;
-            case OP_SCS:
-
-               fp->Opcode = FP_OPCODE_SCS;
-               break;
-         }
-
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
-              &fp->DstReg.Index, fp->DstReg.WriteMask))
-            return 1;
-         fp->SrcReg[0].Abs = GL_FALSE;
-         fp->SrcReg[0].NegateAbs = GL_FALSE;
-         if (parse_scalar_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
-              &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
-              swz, &rel))
-            return 1;
-         for (b=0; b<4; b++)
-            fp->SrcReg[0].Swizzle[b] = swz[b];
-         break;
-
-      case OP_ALU_BINSC:
-         switch (code) {
-            case OP_POW_SAT:
-               fp->Saturate = 1;
-            case OP_POW:
-               fp->Opcode = FP_OPCODE_POW;
-               break;
-         }
-
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
-              &fp->DstReg.Index, fp->DstReg.WriteMask))
-            return 1;
-         for (a = 0; a < 2; a++) {
-            fp->SrcReg[a].Abs = GL_FALSE;
-            fp->SrcReg[a].NegateAbs = GL_FALSE;
-            if (parse_scalar_src_reg
-                (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
-                 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
-                 swz, &rel))
-               return 1;
-            for (b=0; b<4; b++)
-               fp->SrcReg[a].Swizzle[b] = swz[b];
-         }
-         break;
-
-
-      case OP_ALU_BIN:
-         switch (code) {
-            case OP_ADD_SAT:
-               fp->Saturate = 1;
-            case OP_ADD:
-               fp->Opcode = FP_OPCODE_ADD;
-               break;
-
-            case OP_DP3_SAT:
-               fp->Saturate = 1;
-            case OP_DP3:
-               fp->Opcode = FP_OPCODE_DP3;
-               break;
-
-            case OP_DP4_SAT:
-               fp->Saturate = 1;
-            case OP_DP4:
-               fp->Opcode = FP_OPCODE_DP4;
-               break;
-
-            case OP_DPH_SAT:
-               fp->Saturate = 1;
-            case OP_DPH:
-               fp->Opcode = FP_OPCODE_DPH;
-               break;
-
-            case OP_DST_SAT:
-               fp->Saturate = 1;
-            case OP_DST:
-               fp->Opcode = FP_OPCODE_DST;
-               break;
-
-            case OP_MAX_SAT:
-               fp->Saturate = 1;
-            case OP_MAX:
-               fp->Opcode = FP_OPCODE_MAX;
-               break;
-
-            case OP_MIN_SAT:
-               fp->Saturate = 1;
-            case OP_MIN:
-               fp->Opcode = FP_OPCODE_MIN;
-               break;
-
-            case OP_MUL_SAT:
-               fp->Saturate = 1;
-            case OP_MUL:
-               fp->Opcode = FP_OPCODE_MUL;
-               break;
-
-            case OP_SGE_SAT:
-               fp->Saturate = 1;
-            case OP_SGE:
-               fp->Opcode = FP_OPCODE_SGE;
-               break;
-
-            case OP_SLT_SAT:
-               fp->Saturate = 1;
-            case OP_SLT:
-               fp->Opcode = FP_OPCODE_SLT;
-               break;
-
-            case OP_SUB_SAT:
-               fp->Saturate = 1;
-            case OP_SUB:
-               fp->Opcode = FP_OPCODE_SUB;
-               break;
-
-            case OP_XPD_SAT:
-               fp->Saturate = 1;
-            case OP_XPD:
-               fp->Opcode = FP_OPCODE_XPD;
-               break;
-         }
-
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
-              &fp->DstReg.Index, fp->DstReg.WriteMask))
-            return 1;
-         for (a = 0; a < 2; a++) {
-            fp->SrcReg[a].Abs = GL_FALSE;
-            fp->SrcReg[a].NegateAbs = GL_FALSE;
-            if (parse_vector_src_reg
-                (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
-                 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
-                 swz, &rel))
-               return 1;
-            for (b=0; b<4; b++)
-               fp->SrcReg[a].Swizzle[b] = swz[b];
-         }
-         break;
-
-      case OP_ALU_TRI:
-         switch (code) {
-            case OP_CMP_SAT:
-               fp->Saturate = 1;
-            case OP_CMP:
-               fp->Opcode = FP_OPCODE_CMP;
-               break;
-
-            case OP_LRP_SAT:
-               fp->Saturate = 1;
-            case OP_LRP:
-               fp->Opcode = FP_OPCODE_LRP;
-               break;
-
-            case OP_MAD_SAT:
-               fp->Saturate = 1;
-            case OP_MAD:
-               fp->Opcode = FP_OPCODE_MAD;
-               break;
-         }
-
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
-              &fp->DstReg.Index, fp->DstReg.WriteMask))
-            return 1;
-         for (a = 0; a < 3; a++) {
-            fp->SrcReg[a].Abs = GL_FALSE;
-            fp->SrcReg[a].NegateAbs = GL_FALSE;
-            if (parse_vector_src_reg
-                (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
-                 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
-                 swz, &rel))
-               return 1;
-            for (b=0; b<4; b++)
-               fp->SrcReg[a].Swizzle[b] = swz[b];
-         }
-         break;
-
-      case OP_ALU_SWZ:
-         switch (code) {
-            case OP_SWZ_SAT:
-               fp->Saturate = 1;
-            case OP_SWZ:
-               fp->Opcode = FP_OPCODE_SWZ;
-               break;
-         }
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
-              &fp->DstReg.Index, fp->DstReg.WriteMask))
-            return 1;
-
-         if (parse_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
-              &fp->SrcReg[0].Index, &rel))
-            return 1;
-         parse_extended_swizzle_mask (inst, swz,
-                                      &fp->SrcReg[0].NegateBase);
-         for (b=0; b<4; b++)
-            fp->SrcReg[0].Swizzle[b] = swz[b];
-         break;
-
-      case OP_TEX_SAMPLE:
-         switch (code) {
-            case OP_TEX_SAT:
-               fp->Saturate = 1;
-            case OP_TEX:
-               fp->Opcode = FP_OPCODE_TEX;
-               break;
-
-            case OP_TXP_SAT:
-               fp->Saturate = 1;
-            case OP_TXP:
-               fp->Opcode = FP_OPCODE_TXP;
-               break;
-
-            case OP_TXB_SAT:
-
-               fp->Saturate = 1;
-            case OP_TXB:
-               fp->Opcode = FP_OPCODE_TXB;
-               break;
-         }
-
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
-              &fp->DstReg.Index, fp->DstReg.WriteMask))
-            return 1;
-         fp->SrcReg[0].Abs = GL_FALSE;
-         fp->SrcReg[0].NegateAbs = GL_FALSE;
-         if (parse_vector_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
-              &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
-              swz, &rel))
-            return 1;
-         for (b=0; b<4; b++)
-            fp->SrcReg[0].Swizzle[b] = swz[b];
-
-         /* texImageUnit */
-         if (parse_texcoord_num (ctx, inst, Program, &texcoord))
-            return 1;
-         fp->TexSrcUnit = texcoord;
-
-         /* texTarget */
-         switch (*(*inst)++) {
-            case TEXTARGET_1D:
-               fp->TexSrcBit = TEXTURE_1D_BIT;
-               break;
-            case TEXTARGET_2D:
-               fp->TexSrcBit = TEXTURE_2D_BIT;
-               break;
-            case TEXTARGET_3D:
-               fp->TexSrcBit = TEXTURE_3D_BIT;
-               break;
-            case TEXTARGET_RECT:
-               fp->TexSrcBit = TEXTURE_RECT_BIT;
-               break;
-            case TEXTARGET_CUBE:
-               fp->TexSrcBit = TEXTURE_CUBE_BIT;
-               break;
-	    case TEXTARGET_SHADOW1D:
-	    case TEXTARGET_SHADOW2D:
-	    case TEXTARGET_SHADOWRECT:
-	       /* TODO ARB_fragment_program_shadow code */
-	       break;
-         }
-         Program->TexturesUsed[texcoord] |= fp->TexSrcBit;
-         break;
-
-      case OP_TEX_KIL:
-         fp->Opcode = FP_OPCODE_KIL;
-         fp->SrcReg[0].Abs = GL_FALSE;
-         fp->SrcReg[0].NegateAbs = GL_FALSE;
-         if (parse_vector_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
-              &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
-              swz, &rel))
-            return 1;
-         for (b=0; b<4; b++)
-            fp->SrcReg[0].Swizzle[b] = swz[b];
-         break;
-   }
-
-   return 0;
-}
-
-/**
- * This is a big mother that handles getting opcodes into the instruction
- * and handling the src & dst registers for vertex program instructions
- */
-static GLuint
-parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
-                      struct var_cache **vc_head, struct arb_program *Program,
-                      struct vp_instruction *vp)
-{
-   GLint a;
-   GLubyte type, code;
-
-   /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
-   type = *(*inst)++;
-
-   /* The actual opcode name */
-   code = *(*inst)++;
-
-   /* Record the position in the program string for debugging */
-   vp->StringPos = Program->Position;
-
-   vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0;
-
-   for (a = 0; a < 4; a++) {
-      vp->SrcReg[0].Swizzle[a] = a;
-      vp->SrcReg[1].Swizzle[a] = a;
-      vp->SrcReg[2].Swizzle[a] = a;
-      vp->DstReg.WriteMask[a] = 1;
-   }
-
-   switch (type) {
-         /* XXX: */
-      case OP_ALU_ARL:
-         vp->Opcode = VP_OPCODE_ARL;
-
-         /* Remember to set SrcReg.RelAddr; */
-
-         /* Get the masked address register [dst] */
-         if (parse_masked_address_reg
-             (ctx, inst, vc_head, Program, &vp->DstReg.Index,
-              vp->DstReg.WriteMask))
-            return 1;
-         vp->DstReg.File = PROGRAM_ADDRESS;
-
-         /* Get a scalar src register */
-         if (parse_scalar_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
-              &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
-              vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))
-            return 1;
-
-         break;
-
-      case OP_ALU_VECTOR:
-         switch (code) {
-            case OP_ABS:
-               vp->Opcode = VP_OPCODE_ABS;
-               break;
-            case OP_FLR:
-               vp->Opcode = VP_OPCODE_FLR;
-               break;
-            case OP_FRC:
-               vp->Opcode = VP_OPCODE_FRC;
-               break;
-            case OP_LIT:
-               vp->Opcode = VP_OPCODE_LIT;
-               break;
-            case OP_MOV:
-               vp->Opcode = VP_OPCODE_MOV;
-               break;
-         }
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
-              &vp->DstReg.Index, vp->DstReg.WriteMask))
-            return 1;
-         if (parse_vector_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
-              &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
-              vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))
-            return 1;
-         break;
-
-      case OP_ALU_SCALAR:
-         switch (code) {
-            case OP_EX2:
-               vp->Opcode = VP_OPCODE_EX2;
-               break;
-            case OP_EXP:
-               vp->Opcode = VP_OPCODE_EXP;
-               break;
-            case OP_LG2:
-               vp->Opcode = VP_OPCODE_LG2;
-               break;
-            case OP_LOG:
-               vp->Opcode = VP_OPCODE_LOG;
-               break;
-            case OP_RCP:
-               vp->Opcode = VP_OPCODE_RCP;
-               break;
-            case OP_RSQ:
-               vp->Opcode = VP_OPCODE_RSQ;
-               break;
-         }
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
-              &vp->DstReg.Index, vp->DstReg.WriteMask))
-            return 1;
-         if (parse_scalar_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
-              &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
-              vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))
-            return 1;
-         break;
-
-      case OP_ALU_BINSC:
-         switch (code) {
-            case OP_POW:
-               vp->Opcode = VP_OPCODE_POW;
-               break;
-         }
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
-              &vp->DstReg.Index, vp->DstReg.WriteMask))
-            return 1;
-         for (a = 0; a < 2; a++) {
-            if (parse_scalar_src_reg
-                (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
-                 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
-                 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))
-               return 1;
-         }
-         break;
-
-      case OP_ALU_BIN:
-         switch (code) {
-            case OP_ADD:
-               vp->Opcode = VP_OPCODE_ADD;
-               break;
-            case OP_DP3:
-               vp->Opcode = VP_OPCODE_DP3;
-               break;
-            case OP_DP4:
-               vp->Opcode = VP_OPCODE_DP4;
-               break;
-            case OP_DPH:
-               vp->Opcode = VP_OPCODE_DPH;
-               break;
-            case OP_DST:
-               vp->Opcode = VP_OPCODE_DST;
-               break;
-            case OP_MAX:
-               vp->Opcode = VP_OPCODE_MAX;
-               break;
-            case OP_MIN:
-               vp->Opcode = VP_OPCODE_MIN;
-               break;
-            case OP_MUL:
-               vp->Opcode = VP_OPCODE_MUL;
-               break;
-            case OP_SGE:
-               vp->Opcode = VP_OPCODE_SGE;
-               break;
-            case OP_SLT:
-               vp->Opcode = VP_OPCODE_SLT;
-               break;
-            case OP_SUB:
-               vp->Opcode = VP_OPCODE_SUB;
-               break;
-            case OP_XPD:
-               vp->Opcode = VP_OPCODE_XPD;
-               break;
-         }
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
-              &vp->DstReg.Index, vp->DstReg.WriteMask))
-            return 1;
-         for (a = 0; a < 2; a++) {
-            if (parse_vector_src_reg
-                (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
-                 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
-                 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))
-               return 1;
-         }
-         break;
-
-      case OP_ALU_TRI:
-         switch (code) {
-            case OP_MAD:
-               vp->Opcode = VP_OPCODE_MAD;
-               break;
-         }
-
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
-              &vp->DstReg.Index, vp->DstReg.WriteMask))
-            return 1;
-         for (a = 0; a < 3; a++) {
-            if (parse_vector_src_reg
-                (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
-                 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
-                 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))
-               return 1;
-         }
-         break;
-
-      case OP_ALU_SWZ:
-         switch (code) {
-            case OP_SWZ:
-               vp->Opcode = VP_OPCODE_SWZ;
-               break;
-         }
-         if (parse_masked_dst_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
-              &vp->DstReg.Index, vp->DstReg.WriteMask))
-            return 1;
-
-         if (parse_src_reg
-             (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
-              &vp->SrcReg[0].Index, &vp->SrcReg[0].RelAddr))
-            return 1;
-         parse_extended_swizzle_mask (inst, vp->SrcReg[0].Swizzle,
-                                      &vp->SrcReg[0].Negate);
-         break;
-   }
-   return 0;
-}
-
-#if DEBUG_PARSING
-
-static GLvoid
-print_state_token (GLint token)
-{
-   switch (token) {
-      case STATE_MATERIAL:
-         fprintf (stderr, "STATE_MATERIAL ");
-         break;
-      case STATE_LIGHT:
-         fprintf (stderr, "STATE_LIGHT ");
-         break;
-
-      case STATE_LIGHTMODEL_AMBIENT:
-         fprintf (stderr, "STATE_AMBIENT ");
-         break;
-
-      case STATE_LIGHTMODEL_SCENECOLOR:
-         fprintf (stderr, "STATE_SCENECOLOR ");
-         break;
-
-      case STATE_LIGHTPROD:
-         fprintf (stderr, "STATE_LIGHTPROD ");
-         break;
-
-      case STATE_TEXGEN:
-         fprintf (stderr, "STATE_TEXGEN ");
-         break;
-
-      case STATE_FOG_COLOR:
-         fprintf (stderr, "STATE_FOG_COLOR ");
-         break;
-
-      case STATE_FOG_PARAMS:
-         fprintf (stderr, "STATE_FOG_PARAMS ");
-         break;
-
-      case STATE_CLIPPLANE:
-         fprintf (stderr, "STATE_CLIPPLANE ");
-         break;
-
-      case STATE_POINT_SIZE:
-         fprintf (stderr, "STATE_POINT_SIZE ");
-         break;
-
-      case STATE_POINT_ATTENUATION:
-         fprintf (stderr, "STATE_ATTENUATION ");
-         break;
-
-      case STATE_MATRIX:
-         fprintf (stderr, "STATE_MATRIX ");
-         break;
-
-      case STATE_MODELVIEW:
-         fprintf (stderr, "STATE_MODELVIEW ");
-         break;
-
-      case STATE_PROJECTION:
-         fprintf (stderr, "STATE_PROJECTION ");
-         break;
-
-      case STATE_MVP:
-         fprintf (stderr, "STATE_MVP ");
-         break;
-
-      case STATE_TEXTURE:
-         fprintf (stderr, "STATE_TEXTURE ");
-         break;
-
-      case STATE_PROGRAM:
-         fprintf (stderr, "STATE_PROGRAM ");
-         break;
-
-      case STATE_MATRIX_INVERSE:
-         fprintf (stderr, "STATE_INVERSE ");
-         break;
-
-      case STATE_MATRIX_TRANSPOSE:
-         fprintf (stderr, "STATE_TRANSPOSE ");
-         break;
-
-      case STATE_MATRIX_INVTRANS:
-         fprintf (stderr, "STATE_INVTRANS ");
-         break;
-
-      case STATE_AMBIENT:
-         fprintf (stderr, "STATE_AMBIENT ");
-         break;
-
-      case STATE_DIFFUSE:
-         fprintf (stderr, "STATE_DIFFUSE ");
-         break;
-
-      case STATE_SPECULAR:
-         fprintf (stderr, "STATE_SPECULAR ");
-         break;
-
-      case STATE_EMISSION:
-         fprintf (stderr, "STATE_EMISSION ");
-         break;
-
-      case STATE_SHININESS:
-         fprintf (stderr, "STATE_SHININESS ");
-         break;
-
-      case STATE_HALF:
-         fprintf (stderr, "STATE_HALF ");
-         break;
-
-      case STATE_POSITION:
-         fprintf (stderr, "STATE_POSITION ");
-         break;
-
-      case STATE_ATTENUATION:
-         fprintf (stderr, "STATE_ATTENUATION ");
-         break;
-
-      case STATE_SPOT_DIRECTION:
-         fprintf (stderr, "STATE_DIRECTION ");
-         break;
-
-      case STATE_TEXGEN_EYE_S:
-         fprintf (stderr, "STATE_TEXGEN_EYE_S ");
-         break;
-
-      case STATE_TEXGEN_EYE_T:
-         fprintf (stderr, "STATE_TEXGEN_EYE_T ");
-         break;
-
-      case STATE_TEXGEN_EYE_R:
-         fprintf (stderr, "STATE_TEXGEN_EYE_R ");
-         break;
-
-      case STATE_TEXGEN_EYE_Q:
-         fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
-         break;
-
-      case STATE_TEXGEN_OBJECT_S:
-         fprintf (stderr, "STATE_TEXGEN_EYE_S ");
-         break;
-
-      case STATE_TEXGEN_OBJECT_T:
-         fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
-         break;
-
-      case STATE_TEXGEN_OBJECT_R:
-         fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
-         break;
-
-      case STATE_TEXGEN_OBJECT_Q:
-         fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
-         break;
-
-      case STATE_TEXENV_COLOR:
-         fprintf (stderr, "STATE_TEXENV_COLOR ");
-         break;
-
-      case STATE_DEPTH_RANGE:
-         fprintf (stderr, "STATE_DEPTH_RANGE ");
-         break;
-
-      case STATE_VERTEX_PROGRAM:
-         fprintf (stderr, "STATE_VERTEX_PROGRAM ");
-         break;
-
-      case STATE_FRAGMENT_PROGRAM:
-         fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
-         break;
-
-      case STATE_ENV:
-         fprintf (stderr, "STATE_ENV ");
-         break;
-
-      case STATE_LOCAL:
-         fprintf (stderr, "STATE_LOCAL ");
-         break;
-
-   }
-   fprintf (stderr, "[%d] ", token);
-}
-
-
-static GLvoid
-debug_variables (GLcontext * ctx, struct var_cache *vc_head,
-                 struct arb_program *Program)
-{
-   struct var_cache *vc;
-   GLint a, b;
-
-   fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
-
-   /* First of all, print out the contents of the var_cache */
-   vc = vc_head;
-   while (vc) {
-      fprintf (stderr, "[%x]\n", vc);
-      switch (vc->type) {
-         case vt_none:
-            fprintf (stderr, "UNDEFINED %s\n", vc->name);
-            break;
-         case vt_attrib:
-            fprintf (stderr, "ATTRIB    %s\n", vc->name);
-            fprintf (stderr, "          binding: 0x%x\n", vc->attrib_binding);
-            break;
-         case vt_param:
-            fprintf (stderr, "PARAM     %s  begin: %d len: %d\n", vc->name,
-                     vc->param_binding_begin, vc->param_binding_length);
-            b = vc->param_binding_begin;
-            for (a = 0; a < vc->param_binding_length; a++) {
-               fprintf (stderr, "%s\n",
-                        Program->Parameters->Parameters[a + b].Name);
-               if (Program->Parameters->Parameters[a + b].Type == STATE) {
-                  print_state_token (Program->Parameters->Parameters[a + b].
-                                     StateIndexes[0]);
-                  print_state_token (Program->Parameters->Parameters[a + b].
-                                     StateIndexes[1]);
-                  print_state_token (Program->Parameters->Parameters[a + b].
-                                     StateIndexes[2]);
-                  print_state_token (Program->Parameters->Parameters[a + b].
-                                     StateIndexes[3]);
-                  print_state_token (Program->Parameters->Parameters[a + b].
-                                     StateIndexes[4]);
-                  print_state_token (Program->Parameters->Parameters[a + b].
-                                     StateIndexes[5]);
-               }
-               else
-                  fprintf (stderr, "%f %f %f %f\n",
-                           Program->Parameters->Parameters[a + b].Values[0],
-                           Program->Parameters->Parameters[a + b].Values[1],
-                           Program->Parameters->Parameters[a + b].Values[2],
-                           Program->Parameters->Parameters[a + b].Values[3]);
-            }
-            break;
-         case vt_temp:
-            fprintf (stderr, "TEMP      %s\n", vc->name);
-            fprintf (stderr, "          binding: 0x%x\n", vc->temp_binding);
-            break;
-         case vt_output:
-            fprintf (stderr, "OUTPUT    %s\n", vc->name);
-            fprintf (stderr, "          binding: 0x%x\n", vc->output_binding);
-            break;
-         case vt_alias:
-            fprintf (stderr, "ALIAS     %s\n", vc->name);
-            fprintf (stderr, "          binding: 0x%x (%s)\n",
-                     vc->alias_binding, vc->alias_binding->name);
-            break;
-      }
-      vc = vc->next;
-   }
-}
-
-#endif
-
-
-/**
- * The main loop for parsing a fragment or vertex program
- *
- * \return 0 on sucess, 1 on error
- */
-static GLint
-parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
-                   struct arb_program *Program)
-{
-   GLint err = 0;
-
-   Program->MajorVersion = (GLuint) * inst++;
-   Program->MinorVersion = (GLuint) * inst++;
-
-   while (*inst != END) {
-      switch (*inst++) {
-
-         case OPTION:
-            switch (*inst++) {
-               case ARB_PRECISION_HINT_FASTEST:
-                  Program->PrecisionOption = GL_FASTEST;
-                  break;
-
-               case ARB_PRECISION_HINT_NICEST:
-                  Program->PrecisionOption = GL_NICEST;
-                  break;
-
-               case ARB_FOG_EXP:
-                  Program->FogOption = GL_EXP;
-                  break;
-
-               case ARB_FOG_EXP2:
-                  Program->FogOption = GL_EXP2;
-                  break;
-
-               case ARB_FOG_LINEAR:
-                  Program->FogOption = GL_LINEAR;
-                  break;
-
-               case ARB_POSITION_INVARIANT:
-                  if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
-                     Program->HintPositionInvariant = 1;
-                  break;
-
-               case ARB_FRAGMENT_PROGRAM_SHADOW:
-	          if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
-	             /* TODO ARB_fragment_program_shadow code */
-		  }
-		  break;
-            }
-            break;
-
-         case INSTRUCTION:
-            Program->Position = parse_position (&inst);
-
-            if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
-
-               /* Check the instruction count
-                * XXX: Does END count as an instruction?
-                */
-               if (Program->Base.NumInstructions+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {
-                  _mesa_set_program_error (ctx, Program->Position,
-                      "Max instruction count exceeded!");
-                  _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Max instruction count exceeded!");
-               }
-
-               /* Realloc Program->FPInstructions */
-               Program->FPInstructions =
-                  (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
-                                                           Program->Base.NumInstructions*sizeof(struct fp_instruction),
-                                                           (Program->Base.NumInstructions+1)*sizeof (struct fp_instruction));
-
-               /* parse the current instruction   */
-               err = parse_fp_instruction (ctx, &inst, vc_head, Program,
-                                           &Program->FPInstructions[Program->Base.NumInstructions]);
-
-            }
-            else {
-               /* Check the instruction count
-                * XXX: Does END count as an instruction?
-                */
-               if (Program->Base.NumInstructions+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {
-                  _mesa_set_program_error (ctx, Program->Position,
-                      "Max instruction count exceeded!");
-                  _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Max instruction count exceeded!");
-               }
-
-               /* Realloc Program->VPInstructions */
-               Program->VPInstructions =
-                  (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
-                                                           Program->Base.NumInstructions*sizeof(struct vp_instruction),
-                                                           (Program->Base.NumInstructions +1)*sizeof(struct vp_instruction));
-
-               /* parse the current instruction   */
-               err = parse_vp_instruction (ctx, &inst, vc_head, Program,
-                                           &Program->VPInstructions[Program->Base.NumInstructions]);
-            }
-
-            /* increment Program->Base.NumInstructions */
-            Program->Base.NumInstructions++;
-            break;
-
-         case DECLARATION:
-            err = parse_declaration (ctx, &inst, vc_head, Program);
-            break;
-
-         default:
-            break;
-      }
-
-      if (err)
-         break;
-   }
-
-   /* Finally, tag on an OPCODE_END instruction */
-   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
-      Program->FPInstructions =
-         (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
-						  Program->Base.NumInstructions*sizeof(struct fp_instruction),
-                                                  (Program->Base.NumInstructions+1)*sizeof(struct fp_instruction));
-
-      Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END;
-      /* YYY Wrong Position in program, whatever, at least not random -> crash
-	 Program->Position = parse_position (&inst);
-      */
-      Program->FPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
-   }
-   else {
-      Program->VPInstructions =
-         (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
-                                                  Program->Base.NumInstructions*sizeof(struct vp_instruction),
-                                                  (Program->Base.NumInstructions+1)*sizeof(struct vp_instruction));
-
-      Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END;
-      /* YYY Wrong Position in program, whatever, at least not random -> crash
-	 Program->Position = parse_position (&inst);
-      */
-      Program->VPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;
-   }
-
-   /* increment Program->Base.NumInstructions */
-   Program->Base.NumInstructions++;
-
-   return err;
-}
-
-/* XXX temporary */
-static char core_grammar_text[] =
-#include "grammar_syn.h"
-;
-
-static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
-{
-   char error_msg[300];
-   GLint error_pos;
-
-   if (grammar_set_reg8 (id, name, value))
-      return 0;
-
-   grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
-   _mesa_set_program_error (ctx, error_pos, error_msg);
-   _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");
-   return 1;
-}
-
-static int extension_is_supported (const GLubyte *ext)
-{
-   const GLubyte *extensions = glGetString (GL_EXTENSIONS);
-   const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
-   const GLint ext_len = _mesa_strlen ((const char *) ext);
-
+/*

+ * Mesa 3-D graphics library

+ * Version:  6.1

+ *

+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.

+ *

+ * Permission is hereby granted, free of charge, to any person obtaining a

+ * copy of this software and associated documentation files (the "Software"),

+ * to deal in the Software without restriction, including without limitation

+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,

+ * and/or sell copies of the Software, and to permit persons to whom the

+ * Software is furnished to do so, subject to the following conditions:

+ *

+ * The above copyright notice and this permission notice shall be included

+ * in all copies or substantial portions of the Software.

+ *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS

+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL

+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN

+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN

+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ */

+

+#define DEBUG_PARSING 0

+

+/**

+ * \file arbprogparse.c

+ * ARB_*_program parser core

+ * \author Karl Rasche

+ */

+

+#include "mtypes.h"

+#include "glheader.h"

+#include "context.h"

+#include "hash.h"

+#include "imports.h"

+#include "macros.h"

+#include "program.h"

+#include "nvvertprog.h"

+#include "nvfragprog.h"

+#include "arbprogparse.h"

+#include "grammar_mesa.h"

+

+/* TODO:

+ *    Fragment Program Stuff:

+ *    -----------------------------------------------------

+ *

+ *    - things from Michal's email

+ *       + overflow on atoi

+ *       + not-overflowing floats (don't use parse_integer..)

+ *       + can remove range checking in arbparse.c

+ *

+ *    - check all limits of number of various variables

+ *      + parameters

+ *

+ *    - test! test! test!

+ *

+ *    Vertex Program Stuff:

+ *    -----------------------------------------------------

+ *    - Optimize param array usage and count limits correctly, see spec,

+ *         section 2.14.3.7

+ *       + Record if an array is reference absolutly or relatively (or both)

+ *       + For absolute arrays, store a bitmap of accesses

+ *       + For single parameters, store an access flag

+ *       + After parsing, make a parameter cleanup and merging pass, where

+ *           relative arrays are layed out first, followed by abs arrays, and

+ *           finally single state.

+ *       + Remap offsets for param src and dst registers

+ *       + Now we can properly count parameter usage

+ *

+ *    - Multiple state binding errors in param arrays (see spec, just before

+ *         section 2.14.3.3)

+ *    - grep for XXX

+ *

+ *    Mesa Stuff

+ *    -----------------------------------------------------

+ *    - User clipping planes vs. PositionInvariant

+ *    - Is it sufficient to just multiply by the mvp to transform in the

+ *        PositionInvariant case? Or do we need something more involved?

+ *

+ *    - vp_src swizzle is GLubyte, fp_src swizzle is GLuint

+ *    - fetch state listed in program_parameters list

+ *       + WTF should this go???

+ *       + currently in nvvertexec.c and s_nvfragprog.c

+ *

+ *    - allow for multiple address registers (and fetch address regs properly)

+ *

+ *    Cosmetic Stuff

+ *    -----------------------------------------------------

+ * 	- remove any leftover unused grammer.c stuff (dict_ ?)

+ * 	- fix grammer.c error handling so its not static

+ * 	- #ifdef around stuff pertaining to extentions

+ *

+ *    Outstanding Questions:

+ *    -----------------------------------------------------

+ *    - ARB_matrix_palette / ARB_vertex_blend -- not supported

+ *      what gets hacked off because of this:

+ *       + VERTEX_ATTRIB_MATRIXINDEX

+ *       + VERTEX_ATTRIB_WEIGHT

+ *       + MATRIX_MODELVIEW

+ *       + MATRIX_PALETTE

+ *

+ *    - When can we fetch env/local params from their own register files, and

+ *      when to we have to fetch them into the main state register file?

+ *      (think arrays)

+ *

+ *    Grammar Changes:

+ *    -----------------------------------------------------

+ */

+

+/* Changes since moving the file to shader directory

+

+2004-III-4 ------------------------------------------------------------

+- added #include "grammar_mesa.h"

+- removed grammar specific code part (it resides now in grammar.c)

+- added GL_ARB_fragment_program_shadow tokens

+- modified #include "arbparse_syn.h"

+- major changes inside _mesa_parse_arb_program()

+- check the program string for '\0' characters

+- copy the program string to a one-byte-longer location to have

+  it null-terminated

+- position invariance test (not writing to result.position) moved

+  to syntax part

+*/

+

+typedef GLubyte *production;

+

+/**

+ * This is the text describing the rules to parse the grammar

+ */

+static char arb_grammar_text[] =

+#include "arbprogram_syn.h"

+;

+

+/**

+ * These should match up with the values defined in arbprogram.syn

+ */

+

+/*

+    Changes:

+    - changed and merged V_* and F_* opcode values to OP_*.

+    - added GL_ARB_fragment_program_shadow specific tokens (michal)

+*/

+#define  REVISION                                   0x07

+

+/* program type */

+#define  FRAGMENT_PROGRAM                           0x01

+#define  VERTEX_PROGRAM                             0x02

+

+/* program section */

+#define  OPTION                                     0x01

+#define  INSTRUCTION                                0x02

+#define  DECLARATION                                0x03

+#define  END                                        0x04

+

+/* GL_ARB_fragment_program option flags */

+#define  ARB_PRECISION_HINT_FASTEST                 0x01

+#define  ARB_PRECISION_HINT_NICEST                  0x02

+#define  ARB_FOG_EXP                                0x04

+#define  ARB_FOG_EXP2                               0x08

+#define  ARB_FOG_LINEAR                             0x10

+

+/* GL_ARB_vertex_program option flags */

+#define  ARB_POSITION_INVARIANT                     0x20

+

+/* GL_ARB_fragment_program_shadow option flags */

+#define  ARB_FRAGMENT_PROGRAM_SHADOW                0x40

+

+/* GL_ARB_fragment_program instruction class */

+#define  OP_ALU_INST                                0x00

+#define  OP_TEX_INST                                0x01

+

+/* GL_ARB_vertex_program instruction class */

+/*       OP_ALU_INST */

+

+/* GL_ARB_fragment_program instruction type */

+#define  OP_ALU_VECTOR                               0x00

+#define  OP_ALU_SCALAR                               0x01

+#define  OP_ALU_BINSC                                0x02

+#define  OP_ALU_BIN                                  0x03

+#define  OP_ALU_TRI                                  0x04

+#define  OP_ALU_SWZ                                  0x05

+#define  OP_TEX_SAMPLE                               0x06

+#define  OP_TEX_KIL                                  0x07

+

+/* GL_ARB_vertex_program instruction type */

+#define  OP_ALU_ARL                                  0x08

+/*       OP_ALU_VECTOR */

+/*       OP_ALU_SCALAR */

+/*       OP_ALU_BINSC */

+/*       OP_ALU_BIN */

+/*       OP_ALU_TRI */

+/*       OP_ALU_SWZ */

+

+/* GL_ARB_fragment_program instruction code */

+#define  OP_ABS                                     0x00

+#define  OP_ABS_SAT                                 0x1B

+#define  OP_FLR                                     0x09

+#define  OP_FLR_SAT                                 0x26

+#define  OP_FRC                                     0x0A

+#define  OP_FRC_SAT                                 0x27

+#define  OP_LIT                                     0x0C

+#define  OP_LIT_SAT                                 0x2A

+#define  OP_MOV                                     0x11

+#define  OP_MOV_SAT                                 0x30

+#define  OP_COS                                     0x1F

+#define  OP_COS_SAT                                 0x20

+#define  OP_EX2                                     0x07

+#define  OP_EX2_SAT                                 0x25

+#define  OP_LG2                                     0x0B

+#define  OP_LG2_SAT                                 0x29

+#define  OP_RCP                                     0x14

+#define  OP_RCP_SAT                                 0x33

+#define  OP_RSQ                                     0x15

+#define  OP_RSQ_SAT                                 0x34

+#define  OP_SIN                                     0x38

+#define  OP_SIN_SAT                                 0x39

+#define  OP_SCS                                     0x35

+#define  OP_SCS_SAT                                 0x36

+#define  OP_POW                                     0x13

+#define  OP_POW_SAT                                 0x32

+#define  OP_ADD                                     0x01

+#define  OP_ADD_SAT                                 0x1C

+#define  OP_DP3                                     0x03

+#define  OP_DP3_SAT                                 0x21

+#define  OP_DP4                                     0x04

+#define  OP_DP4_SAT                                 0x22

+#define  OP_DPH                                     0x05

+#define  OP_DPH_SAT                                 0x23

+#define  OP_DST                                     0x06

+#define  OP_DST_SAT                                 0x24

+#define  OP_MAX                                     0x0F

+#define  OP_MAX_SAT                                 0x2E

+#define  OP_MIN                                     0x10

+#define  OP_MIN_SAT                                 0x2F

+#define  OP_MUL                                     0x12

+#define  OP_MUL_SAT                                 0x31

+#define  OP_SGE                                     0x16

+#define  OP_SGE_SAT                                 0x37

+#define  OP_SLT                                     0x17

+#define  OP_SLT_SAT                                 0x3A

+#define  OP_SUB                                     0x18

+#define  OP_SUB_SAT                                 0x3B

+#define  OP_XPD                                     0x1A

+#define  OP_XPD_SAT                                 0x43

+#define  OP_CMP                                     0x1D

+#define  OP_CMP_SAT                                 0x1E

+#define  OP_LRP                                     0x2B

+#define  OP_LRP_SAT                                 0x2C

+#define  OP_MAD                                     0x0E

+#define  OP_MAD_SAT                                 0x2D

+#define  OP_SWZ                                     0x19

+#define  OP_SWZ_SAT                                 0x3C

+#define  OP_TEX                                     0x3D

+#define  OP_TEX_SAT                                 0x3E

+#define  OP_TXB                                     0x3F

+#define  OP_TXB_SAT                                 0x40

+#define  OP_TXP                                     0x41

+#define  OP_TXP_SAT                                 0x42

+#define  OP_KIL                                     0x28

+

+/* GL_ARB_vertex_program instruction code */

+#define  OP_ARL                                     0x02

+/*       OP_ABS */

+/*       OP_FLR */

+/*       OP_FRC */

+/*       OP_LIT */

+/*       OP_MOV */

+/*       OP_EX2 */

+#define  OP_EXP                                     0x08

+/*       OP_LG2 */

+#define  OP_LOG                                     0x0D

+/*       OP_RCP */

+/*       OP_RSQ */

+/*       OP_POW */

+/*       OP_ADD */

+/*       OP_DP3 */

+/*       OP_DP4 */

+/*       OP_DPH */

+/*       OP_DST */

+/*       OP_MAX */

+/*       OP_MIN */

+/*       OP_MUL */

+/*       OP_SGE */

+/*       OP_SLT */

+/*       OP_SUB */

+/*       OP_XPD */

+/*       OP_MAD */

+/*       OP_SWZ */

+

+/* fragment attribute binding */

+#define  FRAGMENT_ATTRIB_COLOR                      0x01

+#define  FRAGMENT_ATTRIB_TEXCOORD                   0x02

+#define  FRAGMENT_ATTRIB_FOGCOORD                   0x03

+#define  FRAGMENT_ATTRIB_POSITION                   0x04

+

+/* vertex attribute binding */

+#define  VERTEX_ATTRIB_POSITION                     0x01

+#define  VERTEX_ATTRIB_WEIGHT                       0x02

+#define  VERTEX_ATTRIB_NORMAL                       0x03

+#define  VERTEX_ATTRIB_COLOR                        0x04

+#define  VERTEX_ATTRIB_FOGCOORD                     0x05

+#define  VERTEX_ATTRIB_TEXCOORD                     0x06

+#define  VERTEX_ATTRIB_MATRIXINDEX                  0x07

+#define  VERTEX_ATTRIB_GENERIC                      0x08

+

+/* fragment result binding */

+#define  FRAGMENT_RESULT_COLOR                      0x01

+#define  FRAGMENT_RESULT_DEPTH                      0x02

+

+/* vertex result binding */

+#define  VERTEX_RESULT_POSITION                     0x01

+#define  VERTEX_RESULT_COLOR                        0x02

+#define  VERTEX_RESULT_FOGCOORD                     0x03

+#define  VERTEX_RESULT_POINTSIZE                    0x04

+#define  VERTEX_RESULT_TEXCOORD                     0x05

+

+/* texture target */

+#define  TEXTARGET_1D                               0x01

+#define  TEXTARGET_2D                               0x02

+#define  TEXTARGET_3D                               0x03

+#define  TEXTARGET_RECT                             0x04

+#define  TEXTARGET_CUBE                             0x05

+/* GL_ARB_fragment_program_shadow */

+#define  TEXTARGET_SHADOW1D                         0x06

+#define  TEXTARGET_SHADOW2D                         0x07

+#define  TEXTARGET_SHADOWRECT                       0x08

+

+/* face type */

+#define  FACE_FRONT                                 0x00

+#define  FACE_BACK                                  0x01

+

+/* color type */

+#define  COLOR_PRIMARY                              0x00

+#define  COLOR_SECONDARY                            0x01

+

+/* component */

+#define  COMPONENT_X                                0x00

+#define  COMPONENT_Y                                0x01

+#define  COMPONENT_Z                                0x02

+#define  COMPONENT_W                                0x03

+#define  COMPONENT_0                                0x04

+#define  COMPONENT_1                                0x05

+

+/* array index type */

+#define  ARRAY_INDEX_ABSOLUTE                       0x00

+#define  ARRAY_INDEX_RELATIVE                       0x01

+

+/* matrix name */

+#define  MATRIX_MODELVIEW                           0x01

+#define  MATRIX_PROJECTION                          0x02

+#define  MATRIX_MVP                                 0x03

+#define  MATRIX_TEXTURE                             0x04

+#define  MATRIX_PALETTE                             0x05

+#define  MATRIX_PROGRAM                             0x06

+

+/* matrix modifier */

+#define  MATRIX_MODIFIER_IDENTITY                   0x00

+#define  MATRIX_MODIFIER_INVERSE                    0x01

+#define  MATRIX_MODIFIER_TRANSPOSE                  0x02

+#define  MATRIX_MODIFIER_INVTRANS                   0x03

+

+/* constant type */

+#define  CONSTANT_SCALAR                            0x01

+#define  CONSTANT_VECTOR                            0x02

+

+/* program param type */

+#define  PROGRAM_PARAM_ENV                          0x01

+#define  PROGRAM_PARAM_LOCAL                        0x02

+

+/* register type */

+#define  REGISTER_ATTRIB                            0x01

+#define  REGISTER_PARAM                             0x02

+#define  REGISTER_RESULT                            0x03

+#define  REGISTER_ESTABLISHED_NAME                  0x04

+

+/* param binding */

+#define  PARAM_NULL                                 0x00

+#define  PARAM_ARRAY_ELEMENT                        0x01

+#define  PARAM_STATE_ELEMENT                        0x02

+#define  PARAM_PROGRAM_ELEMENT                      0x03

+#define  PARAM_PROGRAM_ELEMENTS                     0x04

+#define  PARAM_CONSTANT                             0x05

+

+/* param state property */

+#define  STATE_MATERIAL_PARSER                      0x01

+#define  STATE_LIGHT_PARSER                         0x02

+#define  STATE_LIGHT_MODEL                          0x03

+#define  STATE_LIGHT_PROD                           0x04

+#define  STATE_FOG                                  0x05

+#define  STATE_MATRIX_ROWS                          0x06

+/* GL_ARB_fragment_program */

+#define  STATE_TEX_ENV                              0x07

+#define  STATE_DEPTH                                0x08

+/* GL_ARB_vertex_program */

+#define  STATE_TEX_GEN                              0x09

+#define  STATE_CLIP_PLANE                           0x0A

+#define  STATE_POINT                                0x0B

+

+/* state material property */

+#define  MATERIAL_AMBIENT                           0x01

+#define  MATERIAL_DIFFUSE                           0x02

+#define  MATERIAL_SPECULAR                          0x03

+#define  MATERIAL_EMISSION                          0x04

+#define  MATERIAL_SHININESS                         0x05

+

+/* state light property */

+#define  LIGHT_AMBIENT                              0x01

+#define  LIGHT_DIFFUSE                              0x02

+#define  LIGHT_SPECULAR                             0x03

+#define  LIGHT_POSITION                             0x04

+#define  LIGHT_ATTENUATION                          0x05

+#define  LIGHT_HALF                                 0x06

+#define  LIGHT_SPOT_DIRECTION                       0x07

+

+/* state light model property */

+#define  LIGHT_MODEL_AMBIENT                        0x01

+#define  LIGHT_MODEL_SCENECOLOR                     0x02

+

+/* state light product property */

+#define  LIGHT_PROD_AMBIENT                         0x01

+#define  LIGHT_PROD_DIFFUSE                         0x02

+#define  LIGHT_PROD_SPECULAR                        0x03

+

+/* state texture environment property */

+#define  TEX_ENV_COLOR                              0x01

+

+/* state texture generation coord property */

+#define  TEX_GEN_EYE                                0x01

+#define  TEX_GEN_OBJECT                             0x02

+

+/* state fog property */

+#define  FOG_COLOR                                  0x01

+#define  FOG_PARAMS                                 0x02

+

+/* state depth property */

+#define  DEPTH_RANGE                                0x01

+

+/* state point parameters property */

+#define  POINT_SIZE                                 0x01

+#define  POINT_ATTENUATION                          0x02

+

+/* declaration */

+#define  ATTRIB                                     0x01

+#define  PARAM                                      0x02

+#define  TEMP                                       0x03

+#define  OUTPUT                                     0x04

+#define  ALIAS                                      0x05

+/* GL_ARB_vertex_program */

+#define  ADDRESS                                    0x06

+

+/*-----------------------------------------------------------------------

+ * From here on down is the semantic checking portion

+ *

+ */

+

+/**

+ * Variable Table Handling functions

+ */

+typedef enum

+{

+   vt_none,

+   vt_address,

+   vt_attrib,

+   vt_param,

+   vt_temp,

+   vt_output,

+   vt_alias

+} var_type;

+

+

+/*

+ * Setting an explicit field for each of the binding properties is a bit wasteful

+ * of space, but it should be much more clear when reading later on..

+ */

+struct var_cache

+{

+   GLubyte *name;

+   var_type type;

+   GLuint address_binding;      /* The index of the address register we should

+                                 * be using                                        */

+   GLuint attrib_binding;       /* For type vt_attrib, see nvfragprog.h for values */

+   GLuint attrib_binding_idx;   /* The index into the attrib register file corresponding

+                                 * to the state in attrib_binding                  */

+   GLuint attrib_is_generic;    /* If the attrib was specified through a generic

+                                 * vertex attrib                                   */

+   GLuint temp_binding;         /* The index of the temp register we are to use    */

+   GLuint output_binding;       /* For type vt_output, see nvfragprog.h for values */

+   GLuint output_binding_idx;   /* This is the index into the result register file

+                                 * corresponding to the bound result state         */

+   struct var_cache *alias_binding;     /* For type vt_alias, points to the var_cache entry

+                                         * that this is aliased to                         */

+   GLuint param_binding_type;   /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,

+                                 *    PROGRAM_ENV_PARAM}                           */

+   GLuint param_binding_begin;  /* This is the offset into the program_parameter_list where

+                                 * the tokens representing our bound state (or constants)

+                                 * start */

+   GLuint param_binding_length; /* This is how many entries in the the program_parameter_list

+                                 * we take up with our state tokens or constants. Note that

+                                 * this is _not_ the same as the number of param registers

+                                 * we eventually use */

+   struct var_cache *next;

+};

+

+static GLvoid

+var_cache_create (struct var_cache **va)

+{

+   *va = (struct var_cache *) _mesa_malloc (sizeof (struct var_cache));

+   if (*va) {

+      (**va).name = NULL;

+      (**va).type = vt_none;

+      (**va).attrib_binding = ~0;

+      (**va).attrib_is_generic = 0;

+      (**va).temp_binding = ~0;

+      (**va).output_binding = ~0;

+      (**va).output_binding_idx = ~0;

+      (**va).param_binding_type = ~0;

+      (**va).param_binding_begin = ~0;

+      (**va).param_binding_length = ~0;

+      (**va).alias_binding = NULL;

+      (**va).next = NULL;

+   }

+}

+

+static GLvoid

+var_cache_destroy (struct var_cache **va)

+{

+   if (*va) {

+      var_cache_destroy (&(**va).next);

+      _mesa_free (*va);

+      *va = NULL;

+   }

+}

+

+static GLvoid

+var_cache_append (struct var_cache **va, struct var_cache *nv)

+{

+   if (*va)

+      var_cache_append (&(**va).next, nv);

+   else

+      *va = nv;

+}

+

+static struct var_cache *

+var_cache_find (struct var_cache *va, GLubyte * name)

+{

+   struct var_cache *first = va;

+

+   while (va) {

+      if (!strcmp ( (const char*) name, (const char*) va->name)) {

+         if (va->type == vt_alias)

+            return var_cache_find (first, va->name);

+         return va;

+      }

+

+      va = va->next;

+   }

+

+   return NULL;

+}

+

+/**

+ * constructs an integer from 4 GLubytes in LE format

+ */

+static GLuint

+parse_position (GLubyte ** inst)

+{

+   GLuint value;

+

+   value =  (GLuint) (*(*inst)++);

+   value += (GLuint) (*(*inst)++) * 0x100;

+   value += (GLuint) (*(*inst)++) * 0x10000;

+   value += (GLuint) (*(*inst)++) * 0x1000000;

+

+   return value;

+}

+

+/**

+ * This will, given a string, lookup the string as a variable name in the

+ * var cache. If the name is found, the var cache node corresponding to the

+ * var name is returned. If it is not found, a new entry is allocated

+ *

+ * \param  I     Points into the binary array where the string identifier begins

+ * \param  found 1 if the string was found in the var_cache, 0 if it was allocated

+ * \return       The location on the var_cache corresponding the the string starting at I

+ */

+static struct var_cache *

+parse_string (GLubyte ** inst, struct var_cache **vc_head,

+              struct arb_program *Program, GLuint * found)

+{

+   GLubyte *i = *inst;

+   struct var_cache *va = NULL;

+

+   *inst += _mesa_strlen ((char *) i) + 1;

+

+   va = var_cache_find (*vc_head, i);

+

+   if (va) {

+      *found = 1;

+      return va;

+   }

+

+   *found = 0;

+   var_cache_create (&va);

+   va->name = i;

+

+   var_cache_append (vc_head, va);

+

+   return va;

+}

+

+static char *

+parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)

+{

+   GLubyte *i = *inst;

+

+   *inst += _mesa_strlen ((char *) i) + 1;

+

+   return (char *) i;

+}

+

+/**

+ * \return 0 if sign is plus, 1 if sign is minus

+ */

+static GLuint

+parse_sign (GLubyte ** inst)

+{

+   /*return *(*inst)++ != '+'; */

+

+   if (**inst == '-') {

+      (*inst)++;

+      return 1;

+   }

+   else if (**inst == '+') {

+      (*inst)++;

+      return 0;

+   }

+

+   return 0;

+}

+

+/**

+ * parses and returns signed integer

+ */

+static GLint

+parse_integer (GLubyte ** inst, struct arb_program *Program)

+{

+   GLint sign;

+   GLint value;

+

+   /* check if *inst points to '+' or '-'

+    * if yes, grab the sign and increment *inst

+    */

+   sign = parse_sign (inst);

+

+   /* now check if *inst points to 0

+    * if yes, increment the *inst and return the default value

+    */

+   if (**inst == 0) {

+      (*inst)++;

+      return 0;

+   }

+

+   /* parse the integer as you normally would do it */

+   value = _mesa_atoi (parse_string_without_adding (inst, Program));

+

+   /* now, after terminating 0 there is a position

+    * to parse it - parse_position()

+    */

+   Program->Position = parse_position (inst);

+

+   if (sign)

+      value *= -1;

+

+   return value;

+}

+

+/**

+ */

+static GLfloat

+parse_float (GLubyte ** inst, struct arb_program *Program)

+{

+   GLint tmp[5], denom;

+   GLuint leading_zeros =0;

+   GLfloat value = 0;

+

+#if 0

+   tmp[0] = parse_sign (inst);  /* This is the sign of the number + - >0, - -> 1 */

+#endif

+   tmp[1] = parse_integer (inst, Program);   /* This is the integer portion of the number */

+

+   /* Now we grab the fractional portion of the number (the digits after

+	* the .). We can have leading 0's here, which parse_integer will ignore,

+	* so we'll check for those first

+	*/

+   while ((**inst == '0') && ( *(*inst+1) != 0))

+   {

+	  leading_zeros++;

+	  (*inst)++;

+   }

+   tmp[2] = parse_integer (inst, Program);   /* This is the fractional portion of the number */

+   tmp[3] = parse_sign (inst);               /* This is the sign of the exponent */

+   tmp[4] = parse_integer (inst, Program);   /* This is the exponent */

+

+   value = (GLfloat) tmp[1];

+   denom = 1;

+   while (denom < tmp[2])

+      denom *= 10;

+   denom *= (GLint) _mesa_pow( 10, leading_zeros );

+   value += (GLfloat) tmp[2] / (GLfloat) denom;

+#if 0

+   if (tmp[0])

+      value *= -1;

+#endif

+   value *= (GLfloat) _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);

+

+   return value;

+}

+

+

+/**

+ */

+static GLfloat

+parse_signed_float (GLubyte ** inst, struct arb_program *Program)

+{

+   GLint negate;

+   GLfloat value;

+

+   negate = parse_sign (inst);

+

+   value = parse_float (inst, Program);

+

+   if (negate)

+      value *= -1;

+

+   return value;

+}

+

+/**

+ * This picks out a constant value from the parsed array. The constant vector is r

+ * returned in the *values array, which should be of length 4.

+ *

+ * \param values - The 4 component vector with the constant value in it

+ */

+static GLvoid

+parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,

+                GLboolean use)

+{

+   GLuint components, i;

+

+

+   switch (*(*inst)++) {

+      case CONSTANT_SCALAR:

+         if (use == GL_TRUE) {

+            values[0] =

+               values[1] =

+               values[2] = values[3] = parse_float (inst, Program);

+         }

+         else {

+            values[0] =

+               values[1] =

+               values[2] = values[3] = parse_signed_float (inst, Program);

+         }

+

+         break;

+      case CONSTANT_VECTOR:

+         values[0] = values[1] = values[2] = 0;

+         values[3] = 1;

+         components = *(*inst)++;

+         for (i = 0; i < components; i++) {

+            values[i] = parse_signed_float (inst, Program);

+         }

+         break;

+   }

+}

+

+/**

+ * \param offset The offset from the address register that we should

+ *                address

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,

+                        GLint *offset)

+{

+   *offset = parse_integer(inst, Program);

+   if ((*offset > 63) || (*offset < -64)) {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Relative offset out of range");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Relative offset %d out of range",

+                                                *offset);

+      return 1;

+   }

+

+   return 0;

+}

+

+/**

+ * \param  color 0 if color type is primary, 1 if color type is secondary

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,

+                  GLint * color)

+{

+   *color = *(*inst)++ != COLOR_PRIMARY;

+   return 0;

+}

+

+/**

+ * Get an integer corresponding to a generic vertex attribute.

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,

+                       struct arb_program *Program, GLuint *attrib)

+{

+   *attrib = parse_integer(inst, Program);

+

+   if ((*attrib < 0) || (*attrib > MAX_VERTEX_PROGRAM_ATTRIBS))

+   {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Invalid generic vertex attribute index");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");

+

+      return 1;

+   }

+

+   return 0;

+}

+

+

+/**

+ * \param coord The texture unit index

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,

+                    struct arb_program *Program, GLuint * coord)

+{

+   *coord = parse_integer (inst, Program);

+

+   if ((*coord < 0) || (*coord >= ctx->Const.MaxTextureUnits)) {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Invalid texture unit index");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");

+      return 1;

+   }

+

+   return 0;

+}

+

+/**

+ * \param coord The weight index

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,

+                  GLint * coord)

+{

+   *coord = parse_integer (inst, Program);

+

+   if ((*coord < 0) || (*coord >= 1)) {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Invalid weight index");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");

+      return 1;

+   }

+

+   return 0;

+}

+

+/**

+ * \param coord The clip plane index

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,

+                     struct arb_program *Program, GLint * coord)

+{

+   *coord = parse_integer (inst, Program);

+

+   if ((*coord < 0) || (*coord >= (GLint) ctx->Const.MaxClipPlanes)) {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Invalid clip plane index");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");

+      return 1;

+   }

+

+   return 0;

+}

+

+

+/**

+ * \return 0 on front face, 1 on back face

+ */

+static GLuint

+parse_face_type (GLubyte ** inst)

+{

+   switch (*(*inst)++) {

+      case FACE_FRONT:

+         return 0;

+

+      case FACE_BACK:

+         return 1;

+   }

+   return 0;

+}

+

+

+/**

+ * Given a matrix and a modifier token on the binary array, return tokens

+ * that _mesa_fetch_state() [program.c] can understand.

+ *

+ * \param matrix - the matrix we are talking about

+ * \param matrix_idx - the index of the matrix we have (for texture & program matricies)

+ * \param matrix_modifier - the matrix modifier (trans, inv, etc)

+ * \return 0 on sucess, 1 on failure

+ */

+static GLuint

+parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,

+              GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)

+{

+   GLubyte mat = *(*inst)++;

+

+   *matrix_idx = 0;

+

+   switch (mat) {

+      case MATRIX_MODELVIEW:

+         *matrix = STATE_MODELVIEW;

+         *matrix_idx = parse_integer (inst, Program);

+         if (*matrix_idx > 0) {

+            _mesa_set_program_error (ctx, Program->Position,

+               "ARB_vertex_blend not supported\n");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+               "ARB_vertex_blend not supported\n");

+            return 1;

+         }

+         break;

+

+      case MATRIX_PROJECTION:

+         *matrix = STATE_PROJECTION;

+         break;

+

+      case MATRIX_MVP:

+         *matrix = STATE_MVP;

+         break;

+

+      case MATRIX_TEXTURE:

+         *matrix = STATE_TEXTURE;

+         *matrix_idx = parse_integer (inst, Program);

+         if (*matrix_idx >= (GLint) ctx->Const.MaxTextureUnits) {

+            _mesa_set_program_error (ctx, Program->Position,

+                                     "Invalid Texture Unit");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+                         "Invalid Texture Unit: %d", *matrix_idx);

+            return 1;

+         }

+         break;

+

+         /* This is not currently supported (ARB_matrix_palette) */

+      case MATRIX_PALETTE:

+         *matrix_idx = parse_integer (inst, Program);

+         _mesa_set_program_error (ctx, Program->Position,

+              "ARB_matrix_palette not supported\n");

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+              "ARB_matrix_palette not supported\n");

+         return 1;

+         break;

+

+      case MATRIX_PROGRAM:

+         *matrix = STATE_PROGRAM;

+         *matrix_idx = parse_integer (inst, Program);

+         if (*matrix_idx >= (GLint) ctx->Const.MaxProgramMatrices) {

+            _mesa_set_program_error (ctx, Program->Position,

+                                     "Invalid Program Matrix");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+                         "Invalid Program Matrix: %d", *matrix_idx);

+            return 1;

+         }

+         break;

+   }

+

+   switch (*(*inst)++) {

+      case MATRIX_MODIFIER_IDENTITY:

+         *matrix_modifier = 0;

+         break;

+      case MATRIX_MODIFIER_INVERSE:

+         *matrix_modifier = STATE_MATRIX_INVERSE;

+         break;

+      case MATRIX_MODIFIER_TRANSPOSE:

+         *matrix_modifier = STATE_MATRIX_TRANSPOSE;

+         break;

+      case MATRIX_MODIFIER_INVTRANS:

+         *matrix_modifier = STATE_MATRIX_INVTRANS;

+         break;

+   }

+

+   return 0;

+}

+

+

+/**

+ * This parses a state string (rather, the binary version of it) into

+ * a 6-token sequence as described in _mesa_fetch_state() [program.c]

+ *

+ * \param inst         - the start in the binary arry to start working from

+ * \param state_tokens - the storage for the 6-token state description

+ * \return             - 0 on sucess, 1 on error

+ */

+static GLuint

+parse_state_single_item (GLcontext * ctx, GLubyte ** inst,

+                         struct arb_program *Program, GLint * state_tokens)

+{

+   switch (*(*inst)++) {

+      case STATE_MATERIAL_PARSER:

+         state_tokens[0] = STATE_MATERIAL;

+         state_tokens[1] = parse_face_type (inst);

+         switch (*(*inst)++) {

+            case MATERIAL_AMBIENT:

+               state_tokens[2] = STATE_AMBIENT;

+               break;

+            case MATERIAL_DIFFUSE:

+               state_tokens[2] = STATE_DIFFUSE;

+               break;

+            case MATERIAL_SPECULAR:

+               state_tokens[2] = STATE_SPECULAR;

+               break;

+            case MATERIAL_EMISSION:

+               state_tokens[2] = STATE_EMISSION;

+	       break;

+            case MATERIAL_SHININESS:

+               state_tokens[2] = STATE_SHININESS;

+               break;

+         }

+         break;

+

+      case STATE_LIGHT_PARSER:

+         state_tokens[0] = STATE_LIGHT;

+         state_tokens[1] = parse_integer (inst, Program);

+

+         /* Check the value of state_tokens[1] against the # of lights */

+         if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {

+            _mesa_set_program_error (ctx, Program->Position,

+                                     "Invalid Light Number");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+                         "Invalid Light Number: %d", state_tokens[1]);

+            return 1;

+         }

+

+         switch (*(*inst)++) {

+            case LIGHT_AMBIENT:

+               state_tokens[2] = STATE_AMBIENT;

+               break;

+            case LIGHT_DIFFUSE:

+               state_tokens[2] = STATE_DIFFUSE;

+               break;

+            case LIGHT_SPECULAR:

+               state_tokens[2] = STATE_SPECULAR;

+               break;

+            case LIGHT_POSITION:

+               state_tokens[2] = STATE_POSITION;

+               break;

+            case LIGHT_ATTENUATION:

+               state_tokens[2] = STATE_ATTENUATION;

+               break;

+            case LIGHT_HALF:

+               state_tokens[2] = STATE_HALF;

+               break;

+            case LIGHT_SPOT_DIRECTION:

+               state_tokens[2] = STATE_SPOT_DIRECTION;

+               break;

+         }

+         break;

+

+      case STATE_LIGHT_MODEL:

+         switch (*(*inst)++) {

+            case LIGHT_MODEL_AMBIENT:

+               state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;

+               break;

+            case LIGHT_MODEL_SCENECOLOR:

+               state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;

+               state_tokens[1] = parse_face_type (inst);

+               break;

+         }

+         break;

+

+      case STATE_LIGHT_PROD:

+         state_tokens[0] = STATE_LIGHTPROD;

+         state_tokens[1] = parse_integer (inst, Program);

+

+         /* Check the value of state_tokens[1] against the # of lights */

+         if (state_tokens[1] >= (GLint) ctx->Const.MaxLights) {

+            _mesa_set_program_error (ctx, Program->Position,

+                                     "Invalid Light Number");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+                         "Invalid Light Number: %d", state_tokens[1]);

+            return 1;

+         }

+

+         state_tokens[2] = parse_face_type (inst);

+         switch (*(*inst)++) {

+            case LIGHT_PROD_AMBIENT:

+               state_tokens[3] = STATE_AMBIENT;

+               break;

+            case LIGHT_PROD_DIFFUSE:

+               state_tokens[3] = STATE_DIFFUSE;

+               break;

+            case LIGHT_PROD_SPECULAR:

+               state_tokens[3] = STATE_SPECULAR;

+               break;

+         }

+         break;

+

+

+      case STATE_FOG:

+         switch (*(*inst)++) {

+            case FOG_COLOR:

+               state_tokens[0] = STATE_FOG_COLOR;

+               break;

+            case FOG_PARAMS:

+               state_tokens[0] = STATE_FOG_PARAMS;

+               break;

+         }

+         break;

+

+      case STATE_TEX_ENV:

+         state_tokens[1] = parse_integer (inst, Program);

+         switch (*(*inst)++) {

+            case TEX_ENV_COLOR:

+               state_tokens[0] = STATE_TEXENV_COLOR;

+               break;

+         }

+         break;

+

+      case STATE_TEX_GEN:

+         {

+            GLuint type, coord;

+

+            state_tokens[0] = STATE_TEXGEN;

+            /*state_tokens[1] = parse_integer (inst, Program);*/    /* Texture Unit */

+

+            if (parse_texcoord_num (ctx, inst, Program, &coord))

+               return 1;

+	    state_tokens[1] = coord;

+

+            /* EYE or OBJECT */

+            type = *(*inst++);

+

+            /* 0 - s, 1 - t, 2 - r, 3 - q */

+            coord = *(*inst++);

+

+            if (type == TEX_GEN_EYE) {

+               switch (coord) {

+                  case COMPONENT_X:

+                     state_tokens[2] = STATE_TEXGEN_EYE_S;

+                     break;

+                  case COMPONENT_Y:

+                     state_tokens[2] = STATE_TEXGEN_EYE_T;

+                     break;

+                  case COMPONENT_Z:

+                     state_tokens[2] = STATE_TEXGEN_EYE_R;

+                     break;

+                  case COMPONENT_W:

+                     state_tokens[2] = STATE_TEXGEN_EYE_Q;

+                     break;

+               }

+            }

+            else {

+               switch (coord) {

+                  case COMPONENT_X:

+                     state_tokens[2] = STATE_TEXGEN_OBJECT_S;

+                     break;

+                  case COMPONENT_Y:

+                     state_tokens[2] = STATE_TEXGEN_OBJECT_T;

+                     break;

+                  case COMPONENT_Z:

+                     state_tokens[2] = STATE_TEXGEN_OBJECT_R;

+                     break;

+                  case COMPONENT_W:

+                     state_tokens[2] = STATE_TEXGEN_OBJECT_Q;

+                     break;

+               }

+            }

+         }

+         break;

+

+      case STATE_DEPTH:

+         switch (*(*inst)++) {

+            case DEPTH_RANGE:

+               state_tokens[0] = STATE_DEPTH_RANGE;

+               break;

+         }

+         break;

+

+      case STATE_CLIP_PLANE:

+         state_tokens[0] = STATE_CLIPPLANE;

+         state_tokens[1] = parse_integer (inst, Program);

+         if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))

+            return 1;

+         break;

+

+      case STATE_POINT:

+         switch (*(*inst++)) {

+            case POINT_SIZE:

+               state_tokens[0] = STATE_POINT_SIZE;

+               break;

+

+            case POINT_ATTENUATION:

+               state_tokens[0] = STATE_POINT_ATTENUATION;

+               break;

+         }

+         break;

+

+         /* XXX: I think this is the correct format for a matrix row */

+      case STATE_MATRIX_ROWS:

+         state_tokens[0] = STATE_MATRIX;

+         if (parse_matrix

+             (ctx, inst, Program, &state_tokens[1], &state_tokens[2],

+              &state_tokens[5]))

+            return 1;

+

+         state_tokens[3] = parse_integer (inst, Program);       /* The first row to grab */

+

+         if ((**inst) != 0) {                                   /* Either the last row, 0 */

+            state_tokens[4] = parse_integer (inst, Program);

+            if (state_tokens[4] < state_tokens[3]) {

+               _mesa_set_program_error (ctx, Program->Position,

+                     "Second matrix index less than the first");

+               _mesa_error (ctx, GL_INVALID_OPERATION,

+                     "Second matrix index (%d) less than the first (%d)",

+                     state_tokens[4], state_tokens[3]);

+               return 1;

+            }

+         }

+         else {

+            state_tokens[4] = state_tokens[3];

+            (*inst)++;

+         }

+         break;

+   }

+

+   return 0;

+}

+

+/**

+ * This parses a state string (rather, the binary version of it) into

+ * a 6-token similar for the state fetching code in program.c

+ *

+ * One might ask, why fetch these parameters into just like  you fetch

+ * state when they are already stored in other places?

+ *

+ * Because of array offsets -> We can stick env/local parameters in the

+ * middle of a parameter array and then index someplace into the array

+ * when we execute.

+ *

+ * One optimization might be to only do this for the cases where the

+ * env/local parameters end up inside of an array, and leave the

+ * single parameters (or arrays of pure env/local pareameters) in their

+ * respective register files.

+ *

+ * For ENV parameters, the format is:

+ *    state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM

+ *    state_tokens[1] = STATE_ENV

+ *    state_tokens[2] = the parameter index

+ *

+ * for LOCAL parameters, the format is:

+ *    state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM

+ *    state_tokens[1] = STATE_LOCAL

+ *    state_tokens[2] = the parameter index

+ *

+ * \param inst         - the start in the binary arry to start working from

+ * \param state_tokens - the storage for the 6-token state description

+ * \return             - 0 on sucess, 1 on failure

+ */

+static GLuint

+parse_program_single_item (GLcontext * ctx, GLubyte ** inst,

+                           struct arb_program *Program, GLint * state_tokens)

+{

+   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)

+      state_tokens[0] = STATE_FRAGMENT_PROGRAM;

+   else

+      state_tokens[0] = STATE_VERTEX_PROGRAM;

+

+

+   switch (*(*inst)++) {

+      case PROGRAM_PARAM_ENV:

+         state_tokens[1] = STATE_ENV;

+         state_tokens[2] = parse_integer (inst, Program);

+

+         /* Check state_tokens[2] against the number of ENV parameters available */

+         if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&

+              (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramEnvParams))

+             ||

+             ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&

+              (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramEnvParams))) {

+            _mesa_set_program_error (ctx, Program->Position,

+                                     "Invalid Program Env Parameter");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+                         "Invalid Program Env Parameter: %d",

+                         state_tokens[2]);

+            return 1;

+         }

+

+         break;

+

+      case PROGRAM_PARAM_LOCAL:

+         state_tokens[1] = STATE_LOCAL;

+         state_tokens[2] = parse_integer (inst, Program);

+

+         /* Check state_tokens[2] against the number of LOCAL parameters available */

+         if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&

+              (state_tokens[2] >= (GLint) ctx->Const.MaxFragmentProgramLocalParams))

+             ||

+             ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&

+              (state_tokens[2] >= (GLint) ctx->Const.MaxVertexProgramLocalParams))) {

+            _mesa_set_program_error (ctx, Program->Position,

+                                     "Invalid Program Local Parameter");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+                         "Invalid Program Local Parameter: %d",

+                         state_tokens[2]);

+            return 1;

+         }

+         break;

+   }

+

+   return 0;

+}

+

+/**

+ * For ARB_vertex_program, programs are not allowed to use both an explicit

+ * vertex attribute and a generic vertex attribute corresponding to the same

+ * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.

+ *

+ * This will walk our var_cache and make sure that nobody does anything fishy.

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+generic_attrib_check(struct var_cache *vc_head)

+{

+   int a;

+   struct var_cache *curr;

+   GLboolean explicitAttrib[MAX_VERTEX_PROGRAM_ATTRIBS],

+      genericAttrib[MAX_VERTEX_PROGRAM_ATTRIBS];

+

+   for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {

+      explicitAttrib[a] = GL_FALSE;

+      genericAttrib[a] = GL_FALSE;

+   }

+

+   curr = vc_head;

+   while (curr) {

+      if (curr->type == vt_attrib) {

+         if (curr->attrib_is_generic)

+            genericAttrib[ curr->attrib_binding_idx ] = GL_TRUE;

+         else

+            explicitAttrib[ curr->attrib_binding_idx ] = GL_TRUE;

+      }

+

+      curr = curr->next;

+   }

+

+   for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {

+      if ((explicitAttrib[a]) && (genericAttrib[a]))

+         return 1;

+   }

+

+   return 0;

+}

+

+/**

+ * This will handle the binding side of an ATTRIB var declaration

+ *

+ * \param binding     - the fragment input register state, defined in nvfragprog.h

+ * \param binding_idx - the index in the attrib register file that binding is associated with

+ * \return returns 0 on sucess, 1 on error

+ *

+ * See nvfragparse.c for attrib register file layout

+ */

+static GLuint

+parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,

+                      struct arb_program *Program, GLuint * binding,

+                      GLuint * binding_idx, GLuint *is_generic)

+{

+   GLuint texcoord;

+   GLint coord;

+   GLint err = 0;

+

+   *is_generic = 0;

+   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {

+      switch (*(*inst)++) {

+         case FRAGMENT_ATTRIB_COLOR:

+            err = parse_color_type (ctx, inst, Program, &coord);

+            *binding = FRAG_ATTRIB_COL0 + coord;

+            *binding_idx = 1 + coord;

+            break;

+

+         case FRAGMENT_ATTRIB_TEXCOORD:

+            err = parse_texcoord_num (ctx, inst, Program, &texcoord);

+            *binding = FRAG_ATTRIB_TEX0 + texcoord;

+            *binding_idx = 4 + texcoord;

+            break;

+

+         case FRAGMENT_ATTRIB_FOGCOORD:

+            *binding = FRAG_ATTRIB_FOGC;

+            *binding_idx = 3;

+            break;

+

+         case FRAGMENT_ATTRIB_POSITION:

+            *binding = FRAG_ATTRIB_WPOS;

+            *binding_idx = 0;

+            break;

+

+         default:

+            err = 1;

+            break;

+      }

+   }

+   else {

+      switch (*(*inst)++) {

+         case VERTEX_ATTRIB_POSITION:

+            *binding = VERT_ATTRIB_POS;

+            *binding_idx = 0;

+            break;

+

+         case VERTEX_ATTRIB_WEIGHT:

+            {

+               GLint weight;

+

+               err = parse_weight_num (ctx, inst, Program, &weight);

+               *binding = VERT_ATTRIB_WEIGHT;

+               *binding_idx = 1;

+            }

+            _mesa_set_program_error (ctx, Program->Position,

+                 "ARB_vertex_blend not supported\n");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+                 "ARB_vertex_blend not supported\n");

+            return 1;

+            break;

+

+         case VERTEX_ATTRIB_NORMAL:

+            *binding = VERT_ATTRIB_NORMAL;

+            *binding_idx = 2;

+            break;

+

+         case VERTEX_ATTRIB_COLOR:

+            {

+               GLint color;

+

+               err = parse_color_type (ctx, inst, Program, &color);

+               if (color) {

+                  *binding = VERT_ATTRIB_COLOR1;

+                  *binding_idx = 4;

+               }

+               else {

+                  *binding = VERT_ATTRIB_COLOR0;

+                  *binding_idx = 3;

+               }

+            }

+            break;

+

+         case VERTEX_ATTRIB_FOGCOORD:

+            *binding = VERT_ATTRIB_FOG;

+            *binding_idx = 5;

+            break;

+

+         case VERTEX_ATTRIB_TEXCOORD:

+            {

+               GLuint unit;

+

+               err = parse_texcoord_num (ctx, inst, Program, &unit);

+               *binding = VERT_ATTRIB_TEX0 + unit;

+               *binding_idx = 8 + unit;

+            }

+            break;

+

+            /* It looks like we don't support this at all, atm */

+         case VERTEX_ATTRIB_MATRIXINDEX:

+            parse_integer (inst, Program);

+            _mesa_set_program_error (ctx, Program->Position,

+                  "ARB_palette_matrix not supported");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+                  "ARB_palette_matrix not supported");

+            return 1;

+            break;

+

+         case VERTEX_ATTRIB_GENERIC:

+            {

+               GLuint attrib;

+

+               if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {

+                  *is_generic = 1;

+                  switch (attrib) {

+                     case 0:

+                        *binding = VERT_ATTRIB_POS;

+                        break;

+                     case 1:

+                        *binding = VERT_ATTRIB_WEIGHT;

+                        break;

+                     case 2:

+                        *binding = VERT_ATTRIB_NORMAL;

+                        break;

+                     case 3:

+                        *binding = VERT_ATTRIB_COLOR0;

+                        break;

+                     case 4:

+                        *binding = VERT_ATTRIB_COLOR1;

+                        break;

+                     case 5:

+                        *binding = VERT_ATTRIB_FOG;

+                        break;

+                     case 6:

+                        break;

+                     case 7:

+                        break;

+                     default:

+                        *binding = VERT_ATTRIB_TEX0 + (attrib-8);

+                        break;

+                  }

+                  *binding_idx = attrib;

+               }

+            }

+            break;

+

+         default:

+            err = 1;

+            break;

+      }

+   }

+

+   /* Can this even happen? */

+   if (err) {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Bad attribute binding");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Bad attribute binding");

+   }

+

+   Program->InputsRead |= (1 << *binding_idx);

+

+   return err;

+}

+

+/**

+ * This translates between a binary token for an output variable type

+ * and the mesa token for the same thing.

+ *

+ *

+ * XXX: What is the 'name' for vertex program state? -> do we need it?

+ *         I don't think we do;

+ *

+ * See nvfragprog.h for definitions

+ *

+ * \param inst        - The parsed tokens

+ * \param binding     - The name of the state we are binding too

+ * \param binding_idx - The index into the result register file that this is bound too

+ *

+ * See nvfragparse.c for the register file layout for fragment programs

+ * See nvvertparse.c for the register file layout for vertex programs

+ */

+static GLuint

+parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,

+                      GLuint * binding_idx, struct arb_program *Program)

+{

+   GLuint b;

+

+   switch (*(*inst)++) {

+      case FRAGMENT_RESULT_COLOR:

+         /* for frag programs, this is FRAGMENT_RESULT_COLOR */

+         if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {

+            *binding = FRAG_OUTPUT_COLR;

+            *binding_idx = 0;

+         }

+         /* for vtx programs, this is VERTEX_RESULT_POSITION */

+         else {

+            *binding_idx = 0;

+         }

+         break;

+

+      case FRAGMENT_RESULT_DEPTH:

+         /* for frag programs, this is FRAGMENT_RESULT_DEPTH */

+         if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {

+            *binding = FRAG_OUTPUT_DEPR;

+            *binding_idx = 2;

+         }

+         /* for vtx programs, this is VERTEX_RESULT_COLOR */

+         else {

+            GLint color_type;

+            GLuint face_type = parse_face_type(inst);

+	    GLint color_type_ret = parse_color_type(ctx, inst, Program, &color_type);

+

+            /* back face */

+            if (face_type) {

+               if (color_type_ret) return 1;

+

+               /* secondary color */

+               if (color_type) {

+                  *binding_idx = 4;

+               }

+               /*  primary color */

+               else {

+                  *binding_idx = 3;

+               }

+            }

+            /* front face */

+            else {

+               /* secondary color */

+               if (color_type) {

+                  *binding_idx = 2;

+               }

+               /* primary color */

+               else {

+                  *binding_idx = 1;

+               }

+            }

+         }

+         break;

+

+      case VERTEX_RESULT_FOGCOORD:

+         *binding_idx = 5;

+         break;

+

+      case VERTEX_RESULT_POINTSIZE:

+         *binding_idx = 6;

+         break;

+

+      case VERTEX_RESULT_TEXCOORD:

+         if (parse_texcoord_num (ctx, inst, Program, &b))

+            return 1;

+         *binding_idx = 7 + b;

+         break;

+   }

+

+   Program->OutputsWritten |= (1 << *binding_idx);

+

+   return 0;

+}

+

+/**

+ * This handles the declaration of ATTRIB variables

+ *

+ * XXX: Still needs

+ *      parse_vert_attrib_binding(), or something like that

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLint

+parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+              struct arb_program *Program)

+{

+   GLuint found;

+   char *error_msg;

+   struct var_cache *attrib_var;

+

+   attrib_var = parse_string (inst, vc_head, Program, &found);

+   Program->Position = parse_position (inst);

+   if (found) {

+      error_msg = (char *)

+         _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);

+      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",

+                     attrib_var->name);

+

+      _mesa_set_program_error (ctx, Program->Position, error_msg);

+      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);

+

+      _mesa_free (error_msg);

+      return 1;

+   }

+

+   attrib_var->type = vt_attrib;

+

+   /* I think this is ok now - karl */

+   /* XXX: */

+   /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */

+   {

+      if (parse_attrib_binding

+          (ctx, inst, Program, &attrib_var->attrib_binding,

+           &attrib_var->attrib_binding_idx, &attrib_var->attrib_is_generic))

+         return 1;

+      if (generic_attrib_check(*vc_head)) {

+         _mesa_set_program_error (ctx, Program->Position,

+   "Cannot use both a generic vertex attribute and a specific attribute of the same type");

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+   "Cannot use both a generic vertex attribute and a specific attribute of the same type");

+         return 1;

+      }

+

+   }

+

+   Program->Base.NumAttributes++;

+   return 0;

+}

+

+/**

+ * \param use -- TRUE if we're called when declaring implicit parameters,

+ *               FALSE if we're declaraing variables. This has to do with

+ *               if we get a signed or unsigned float for scalar constants

+ */

+static GLuint

+parse_param_elements (GLcontext * ctx, GLubyte ** inst,

+                      struct var_cache *param_var,

+                      struct arb_program *Program, GLboolean use)

+{

+   GLint idx;

+   GLuint err;

+   GLint state_tokens[6];

+   GLfloat const_values[4];

+

+   err = 0;

+

+   switch (*(*inst)++) {

+      case PARAM_STATE_ELEMENT:

+

+         if (parse_state_single_item (ctx, inst, Program, state_tokens))

+            return 1;

+

+         /* If we adding STATE_MATRIX that has multiple rows, we need to

+          * unroll it and call _mesa_add_state_reference() for each row

+          */

+         if ((state_tokens[0] == STATE_MATRIX)

+             && (state_tokens[3] != state_tokens[4])) {

+            GLint row;

+            GLint first_row = state_tokens[3];

+            GLint last_row = state_tokens[4];

+

+            for (row = first_row; row <= last_row; row++) {

+               state_tokens[3] = state_tokens[4] = row;

+

+               idx =

+                  _mesa_add_state_reference (Program->Parameters,

+                                             state_tokens);

+               if (param_var->param_binding_begin == ~0U)

+                  param_var->param_binding_begin = idx;

+               param_var->param_binding_length++;

+               Program->Base.NumParameters++;

+            }

+         }

+         else {

+            idx =

+               _mesa_add_state_reference (Program->Parameters, state_tokens);

+            if (param_var->param_binding_begin == ~0U)

+               param_var->param_binding_begin = idx;

+            param_var->param_binding_length++;

+            Program->Base.NumParameters++;

+         }

+         break;

+

+      case PARAM_PROGRAM_ELEMENT:

+

+         if (parse_program_single_item (ctx, inst, Program, state_tokens))

+            return 1;

+         idx = _mesa_add_state_reference (Program->Parameters, state_tokens);

+         if (param_var->param_binding_begin == ~0U)

+            param_var->param_binding_begin = idx;

+         param_var->param_binding_length++;

+         Program->Base.NumParameters++;

+

+         /* Check if there is more: 0 -> we're done, else its an integer */

+         if (**inst) {

+            GLuint out_of_range, new_idx;

+            GLuint start_idx = state_tokens[2] + 1;

+            GLuint end_idx = parse_integer (inst, Program);

+

+            out_of_range = 0;

+            if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {

+               if (((state_tokens[1] == STATE_ENV)

+                    && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))

+                   || ((state_tokens[1] == STATE_LOCAL)

+                       && (end_idx >=

+                           ctx->Const.MaxFragmentProgramLocalParams)))

+                  out_of_range = 1;

+            }

+            else {

+               if (((state_tokens[1] == STATE_ENV)

+                    && (end_idx >= ctx->Const.MaxVertexProgramEnvParams))

+                   || ((state_tokens[1] == STATE_LOCAL)

+                       && (end_idx >=

+                           ctx->Const.MaxVertexProgramLocalParams)))

+                  out_of_range = 1;

+            }

+            if (out_of_range) {

+               _mesa_set_program_error (ctx, Program->Position,

+                                        "Invalid Program Parameter");

+               _mesa_error (ctx, GL_INVALID_OPERATION,

+                            "Invalid Program Parameter: %d", end_idx);

+               return 1;

+            }

+

+            for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {

+               state_tokens[2] = new_idx;

+               idx =

+                  _mesa_add_state_reference (Program->Parameters,

+                                             state_tokens);

+               param_var->param_binding_length++;

+               Program->Base.NumParameters++;

+            }

+         }

+			else

+			{

+				(*inst)++;

+			}

+         break;

+

+      case PARAM_CONSTANT:

+         parse_constant (inst, const_values, Program, use);

+         idx =

+            _mesa_add_named_constant (Program->Parameters,

+                                      (char *) param_var->name, const_values);

+         if (param_var->param_binding_begin == ~0U)

+            param_var->param_binding_begin = idx;

+         param_var->param_binding_length++;

+         Program->Base.NumParameters++;

+         break;

+

+      default:

+         _mesa_set_program_error (ctx, Program->Position,

+                                  "Unexpected token in parse_param_elements()");

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Unexpected token in parse_param_elements()");

+         return 1;

+   }

+

+   /* Make sure we haven't blown past our parameter limits */

+   if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&

+        (Program->Base.NumParameters >=

+         ctx->Const.MaxVertexProgramLocalParams))

+       || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)

+           && (Program->Base.NumParameters >=

+               ctx->Const.MaxFragmentProgramLocalParams))) {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Too many parameter variables");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");

+      return 1;

+   }

+

+   return err;

+}

+

+/**

+ * This picks out PARAM program parameter bindings.

+ *

+ * XXX: This needs to be stressed & tested

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+             struct arb_program *Program)

+{

+   GLuint found, specified_length, err;

+   char *error_msg;

+   struct var_cache *param_var;

+

+   err = 0;

+   param_var = parse_string (inst, vc_head, Program, &found);

+   Program->Position = parse_position (inst);

+

+   if (found) {

+      error_msg = (char *) _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);

+      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",

+                     param_var->name);

+

+      _mesa_set_program_error (ctx, Program->Position, error_msg);

+      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);

+

+      _mesa_free (error_msg);

+      return 1;

+   }

+

+   specified_length = parse_integer (inst, Program);

+

+   if (specified_length < 0) {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Negative parameter array length");

+      _mesa_error (ctx, GL_INVALID_OPERATION,

+                   "Negative parameter array length: %d", specified_length);

+      return 1;

+   }

+

+   param_var->type = vt_param;

+   param_var->param_binding_length = 0;

+

+   /* Right now, everything is shoved into the main state register file.

+    *

+    * In the future, it would be nice to leave things ENV/LOCAL params

+    * in their respective register files, if possible

+    */

+   param_var->param_binding_type = PROGRAM_STATE_VAR;

+

+   /* Remember to:

+    * *   - add each guy to the parameter list

+    * *   - increment the param_var->param_binding_len

+    * *   - store the param_var->param_binding_begin for the first one

+    * *   - compare the actual len to the specified len at the end

+    */

+   while (**inst != PARAM_NULL) {

+      if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))

+         return 1;

+   }

+

+   /* Test array length here! */

+   if (specified_length) {

+      if (specified_length != param_var->param_binding_length) {

+         _mesa_set_program_error (ctx, Program->Position,

+                                  "Declared parameter array lenght does not match parameter list");

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Declared parameter array lenght does not match parameter list");

+      }

+   }

+

+   (*inst)++;

+

+   return 0;

+}

+

+/**

+ *

+ */

+static GLuint

+parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+                 struct arb_program *Program, struct var_cache **new_var)

+{

+   struct var_cache *param_var;

+

+   /* First, insert a dummy entry into the var_cache */

+   var_cache_create (&param_var);

+   param_var->name = (GLubyte *) _mesa_strdup (" ");

+   param_var->type = vt_param;

+

+   param_var->param_binding_length = 0;

+   /* Don't fill in binding_begin; We use the default value of -1

+    * to tell if its already initialized, elsewhere.

+    *

+    * param_var->param_binding_begin  = 0;

+    */

+   param_var->param_binding_type = PROGRAM_STATE_VAR;

+

+   var_cache_append (vc_head, param_var);

+

+   /* Then fill it with juicy parameter goodness */

+   if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))

+      return 1;

+

+   *new_var = param_var;

+

+   return 0;

+}

+

+

+/**

+ * This handles the declaration of TEMP variables

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+            struct arb_program *Program)

+{

+   GLuint found;

+   struct var_cache *temp_var;

+   char *error_msg;

+

+   while (**inst != 0) {

+      temp_var = parse_string (inst, vc_head, Program, &found);

+      Program->Position = parse_position (inst);

+      if (found) {

+         error_msg = (char *)

+            _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);

+         _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",

+                        temp_var->name);

+

+         _mesa_set_program_error (ctx, Program->Position, error_msg);

+         _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);

+

+         _mesa_free (error_msg);

+         return 1;

+      }

+

+      temp_var->type = vt_temp;

+

+      if (((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) &&

+           (Program->Base.NumTemporaries >=

+            ctx->Const.MaxFragmentProgramTemps))

+          || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)

+              && (Program->Base.NumTemporaries >=

+                  ctx->Const.MaxVertexProgramTemps))) {

+         _mesa_set_program_error (ctx, Program->Position,

+                                  "Too many TEMP variables declared");

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Too many TEMP variables declared");

+         return 1;

+      }

+

+      temp_var->temp_binding = Program->Base.NumTemporaries;

+      Program->Base.NumTemporaries++;

+   }

+   (*inst)++;

+

+   return 0;

+}

+

+/**

+ * This handles variables of the OUTPUT variety

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+              struct arb_program *Program)

+{

+   GLuint found;

+   struct var_cache *output_var;

+

+   output_var = parse_string (inst, vc_head, Program, &found);

+   Program->Position = parse_position (inst);

+   if (found) {

+      char *error_msg;

+      error_msg = (char *)

+         _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);

+      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",

+                     output_var->name);

+

+      _mesa_set_program_error (ctx, Program->Position, error_msg);

+      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);

+

+      _mesa_free (error_msg);

+      return 1;

+   }

+

+   output_var->type = vt_output;

+   return parse_result_binding (ctx, inst, &output_var->output_binding,

+                                &output_var->output_binding_idx, Program);

+}

+

+/**

+ * This handles variables of the ALIAS kind

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+             struct arb_program *Program)

+{

+   GLuint found;

+   struct var_cache *temp_var;

+   char *error_msg;

+

+

+   temp_var = parse_string (inst, vc_head, Program, &found);

+   Program->Position = parse_position (inst);

+

+   if (found) {

+      error_msg = (char *)

+         _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);

+      _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",

+                     temp_var->name);

+

+      _mesa_set_program_error (ctx, Program->Position, error_msg);

+      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);

+

+      _mesa_free (error_msg);

+      return 1;

+   }

+

+   temp_var->type = vt_alias;

+   temp_var->alias_binding =  parse_string (inst, vc_head, Program, &found);

+   Program->Position = parse_position (inst);

+

+   if (!found)

+   {

+      error_msg = (char *)

+         _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);

+      _mesa_sprintf (error_msg, "Alias value %s is not defined",

+                     temp_var->alias_binding->name);

+

+      _mesa_set_program_error (ctx, Program->Position, error_msg);

+      _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);

+

+      _mesa_free (error_msg);

+      return 1;

+   }

+

+   return 0;

+}

+

+/**

+ * This handles variables of the ADDRESS kind

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+               struct arb_program *Program)

+{

+   GLuint found;

+   struct var_cache *temp_var;

+   char *error_msg;

+

+   while (**inst != 0) {

+      temp_var = parse_string (inst, vc_head, Program, &found);

+      Program->Position = parse_position (inst);

+      if (found) {

+         error_msg = (char *)

+            _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);

+         _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",

+                        temp_var->name);

+

+         _mesa_set_program_error (ctx, Program->Position, error_msg);

+         _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);

+

+         _mesa_free (error_msg);

+         return 1;

+      }

+

+      temp_var->type = vt_address;

+

+      if (Program->Base.NumAddressRegs >=

+          ctx->Const.MaxVertexProgramAddressRegs) {

+         _mesa_set_program_error (ctx, Program->Position,

+                                  "Too many ADDRESS variables declared");

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Too many ADDRESS variables declared");

+         return 1;

+      }

+

+      temp_var->address_binding = Program->Base.NumAddressRegs;

+      Program->Base.NumAddressRegs++;

+   }

+   (*inst)++;

+

+   return 0;

+}

+

+/**

+ * Parse a program declaration

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLint

+parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+                   struct arb_program *Program)

+{

+   GLint err = 0;

+

+   switch (*(*inst)++) {

+      case ADDRESS:

+         err = parse_address (ctx, inst, vc_head, Program);

+         break;

+

+      case ALIAS:

+         err = parse_alias (ctx, inst, vc_head, Program);

+         break;

+

+      case ATTRIB:

+         err = parse_attrib (ctx, inst, vc_head, Program);

+         break;

+

+      case OUTPUT:

+         err = parse_output (ctx, inst, vc_head, Program);

+         break;

+

+      case PARAM:

+         err = parse_param (ctx, inst, vc_head, Program);

+         break;

+

+      case TEMP:

+         err = parse_temp (ctx, inst, vc_head, Program);

+         break;

+   }

+

+   return err;

+}

+

+/**

+ * Handle the parsing out of a masked destination register

+ *

+ * If we are a vertex program, make sure we don't write to

+ * result.position of we have specified that the program is

+ * position invariant

+ *

+ * \param File      - The register file we write to

+ * \param Index     - The register index we write to

+ * \param WriteMask - The mask controlling which components we write (1->write)

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,

+                      struct var_cache **vc_head, struct arb_program *Program,

+                      GLint * File, GLint * Index, GLboolean * WriteMask)

+{

+   GLuint result;

+   GLubyte mask;

+   struct var_cache *dst;

+

+   /* We either have a result register specified, or a

+    * variable that may or may not be writable

+    */

+   switch (*(*inst)++) {

+      case REGISTER_RESULT:

+         if (parse_result_binding

+             (ctx, inst, &result, (GLuint *) Index, Program))

+            return 1;

+         *File = PROGRAM_OUTPUT;

+         break;

+

+      case REGISTER_ESTABLISHED_NAME:

+         dst = parse_string (inst, vc_head, Program, &result);

+         Program->Position = parse_position (inst);

+

+         /* If the name has never been added to our symbol table, we're hosed */

+         if (!result) {

+            _mesa_set_program_error (ctx, Program->Position,

+                                     "0: Undefined variable");

+            _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",

+                         dst->name);

+            return 1;

+         }

+

+         switch (dst->type) {

+            case vt_output:

+               *File = PROGRAM_OUTPUT;

+               *Index = dst->output_binding_idx;

+               break;

+

+            case vt_temp:

+               *File = PROGRAM_TEMPORARY;

+               *Index = dst->temp_binding;

+               break;

+

+               /* If the var type is not vt_output or vt_temp, no go */

+            default:

+               _mesa_set_program_error (ctx, Program->Position,

+                                        "Destination register is read only");

+               _mesa_error (ctx, GL_INVALID_OPERATION,

+                            "Destination register is read only: %s",

+                            dst->name);

+               return 1;

+         }

+         break;

+

+      default:

+         _mesa_set_program_error (ctx, Program->Position,

+                                  "Unexpected opcode in parse_masked_dst_reg()");

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Unexpected opcode in parse_masked_dst_reg()");

+         return 1;

+   }

+

+

+   /* Position invariance test */

+   /* This test is done now in syntax portion - when position invariance OPTION

+      is specified, "result.position" rule is disabled so there is no way

+      to write the position

+   */

+   /*if ((Program->HintPositionInvariant) && (*File == PROGRAM_OUTPUT) &&

+      (*Index == 0))   {

+      _mesa_set_program_error (ctx, Program->Position,

+                  "Vertex program specified position invariance and wrote vertex position");

+      _mesa_error (ctx, GL_INVALID_OPERATION,

+                  "Vertex program specified position invariance and wrote vertex position");

+   }*/

+

+   /* And then the mask.

+    *  w,a -> bit 0

+    *  z,b -> bit 1

+    *  y,g -> bit 2

+    *  x,r -> bit 3

+    */

+   mask = *(*inst)++;

+

+   WriteMask[0] = (GLboolean) (mask & (1 << 3)) >> 3;

+   WriteMask[1] = (GLboolean) (mask & (1 << 2)) >> 2;

+   WriteMask[2] = (GLboolean) (mask & (1 << 1)) >> 1;

+   WriteMask[3] = (GLboolean) (mask & (1));

+

+   return 0;

+}

+

+

+/**

+ * Handle the parsing of a address register

+ *

+ * \param Index     - The register index we write to

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_address_reg (GLcontext * ctx, GLubyte ** inst,

+                          struct var_cache **vc_head,

+                          struct arb_program *Program, GLint * Index)

+{

+   struct var_cache *dst;

+   GLuint result;

+

+   dst = parse_string (inst, vc_head, Program, &result);

+   Program->Position = parse_position (inst);

+

+   /* If the name has never been added to our symbol table, we're hosed */

+   if (!result) {

+      _mesa_set_program_error (ctx, Program->Position, "Undefined variable");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Undefined variable: %s",

+                   dst->name);

+      return 1;

+   }

+

+   if (dst->type != vt_address) {

+      _mesa_set_program_error (ctx, Program->Position,

+                               "Variable is not of type ADDRESS");

+      _mesa_error (ctx, GL_INVALID_OPERATION,

+                   "Variable: %s is not of type ADDRESS", dst->name);

+      return 1;

+   }

+

+   return 0;

+}

+

+/**

+ * Handle the parsing out of a masked address register

+ *

+ * \param Index     - The register index we write to

+ * \param WriteMask - The mask controlling which components we write (1->write)

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLuint

+parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,

+                          struct var_cache **vc_head,

+                          struct arb_program *Program, GLint * Index,

+                          GLboolean * WriteMask)

+{

+   if (parse_address_reg (ctx, inst, vc_head, Program, Index))

+      return 1;

+

+   /* This should be 0x8 */

+   (*inst)++;

+

+   /* Writemask of .x is implied */

+   WriteMask[0] = 1;

+   WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;

+

+   return 0;

+}

+

+

+/**

+ * Parse out a swizzle mask.

+ *

+ * The values in the input stream are:

+ *   COMPONENT_X -> x/r

+ *   COMPONENT_Y -> y/g

+ *   COMPONENT_Z-> z/b

+ *   COMPONENT_W-> w/a

+ *

+ * The values in the output mask are:

+ *   0 -> x/r

+ *   1 -> y/g

+ *   2 -> z/b

+ *   3 -> w/a

+ *

+ * The len parameter allows us to grab 4 components for a vector

+ * swizzle, or just 1 component for a scalar src register selection

+ */

+static GLuint

+parse_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLint len)

+{

+   GLint a;

+

+   for (a = 0; a < 4; a++)

+      mask[a] = a;

+

+   for (a = 0; a < len; a++) {

+      switch (*(*inst)++) {

+         case COMPONENT_X:

+            mask[a] = 0;

+            break;

+

+         case COMPONENT_Y:

+            mask[a] = 1;

+            break;

+

+         case COMPONENT_Z:

+            mask[a] = 2;

+            break;

+

+         case COMPONENT_W:

+            mask[a] = 3;

+            break;

+      }

+   }

+

+   return 0;

+}

+

+/**

+ */

+static GLuint

+parse_extended_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLboolean * Negate)

+{

+   GLint a;

+   GLubyte swz;

+

+   *Negate = GL_FALSE;

+   for (a = 0; a < 4; a++) {

+      if (parse_sign (inst))

+         *Negate = GL_TRUE;

+

+      swz = *(*inst)++;

+

+      switch (swz) {

+         case COMPONENT_0:

+            mask[a] = SWIZZLE_ZERO;

+            break;

+         case COMPONENT_1:

+            mask[a] = SWIZZLE_ONE;

+            break;

+         case COMPONENT_X:

+            mask[a] = SWIZZLE_X;

+            break;

+         case COMPONENT_Y:

+            mask[a] = SWIZZLE_Y;

+            break;

+         case COMPONENT_Z:

+            mask[a] = SWIZZLE_Z;

+            break;

+         case COMPONENT_W:

+            mask[a] = SWIZZLE_W;

+            break;

+

+      }

+#if 0

+      if (swz == 0)

+         mask[a] = SWIZZLE_ZERO;

+      else if (swz == 1)

+         mask[a] = SWIZZLE_ONE;

+      else

+         mask[a] = swz - 2;

+#endif

+

+   }

+

+   return 0;

+}

+

+

+static GLuint

+parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,

+               struct arb_program *Program, GLint * File, GLint * Index,

+               GLboolean *IsRelOffset )

+{

+   struct var_cache *src;

+   GLuint binding_state, binding_idx, is_generic, found, offset;

+

+   /* And the binding for the src */

+   switch (*(*inst)++) {

+      case REGISTER_ATTRIB:

+         if (parse_attrib_binding

+             (ctx, inst, Program, &binding_state, &binding_idx, &is_generic))

+            return 1;

+         *File = PROGRAM_INPUT;

+         *Index = binding_idx;

+

+         /* We need to insert a dummy variable into the var_cache so we can

+          * catch generic vertex attrib aliasing errors

+          */

+         var_cache_create(&src);

+         src->type = vt_attrib;

+         src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");

+         src->attrib_binding     = binding_state;

+         src->attrib_binding_idx = binding_idx;

+         src->attrib_is_generic  = is_generic;

+         var_cache_append(vc_head, src);

+         if (generic_attrib_check(*vc_head)) {

+            _mesa_set_program_error (ctx, Program->Position,

+   "Cannot use both a generic vertex attribute and a specific attribute of the same type");

+            _mesa_error (ctx, GL_INVALID_OPERATION,

+   "Cannot use both a generic vertex attribute and a specific attribute of the same type");

+            return 1;

+         }

+         break;

+

+      case REGISTER_PARAM:

+         switch (**inst) {

+            case PARAM_ARRAY_ELEMENT:

+               (*inst)++;

+               src = parse_string (inst, vc_head, Program, &found);

+               Program->Position = parse_position (inst);

+

+               if (!found) {

+                  _mesa_set_program_error (ctx, Program->Position,

+                                           "2: Undefined variable");

+                  _mesa_error (ctx, GL_INVALID_OPERATION,

+                               "2: Undefined variable: %s", src->name);

+                  return 1;

+               }

+

+               *File = src->param_binding_type;

+

+               switch (*(*inst)++) {

+                  case ARRAY_INDEX_ABSOLUTE:

+                     offset = parse_integer (inst, Program);

+

+                     if ((offset < 0)

+                         || (offset >= src->param_binding_length)) {

+                        _mesa_set_program_error (ctx, Program->Position,

+                                                 "Index out of range");

+                        _mesa_error (ctx, GL_INVALID_OPERATION,

+                                     "Index %d out of range for %s", offset,

+                                     src->name);

+                        return 1;

+                     }

+

+                     *Index = src->param_binding_begin + offset;

+                     break;

+

+                  case ARRAY_INDEX_RELATIVE:

+                     {

+                        GLint addr_reg_idx, rel_off;

+

+                        /* First, grab the address regiseter */

+                        if (parse_address_reg (ctx, inst, vc_head, Program, &addr_reg_idx))

+                           return 1;

+

+                        /* And the .x */

+                        ((*inst)++);

+                        ((*inst)++);

+                        ((*inst)++);

+                        ((*inst)++);

+

+                        /* Then the relative offset */

+                        if (parse_relative_offset(ctx, inst, Program, &rel_off)) return 1;

+

+                        /* And store it properly */

+                        *Index = src->param_binding_begin + rel_off;

+                        *IsRelOffset = 1;

+                     }

+                     break;

+               }

+               break;

+

+            default:

+

+               if (parse_param_use (ctx, inst, vc_head, Program, &src))

+                  return 1;

+

+               *File = src->param_binding_type;

+               *Index = src->param_binding_begin;

+               break;

+         }

+         break;

+

+      case REGISTER_ESTABLISHED_NAME:

+

+         src = parse_string (inst, vc_head, Program, &found);

+         Program->Position = parse_position (inst);

+

+         /* If the name has never been added to our symbol table, we're hosed */

+         if (!found) {

+            _mesa_set_program_error (ctx, Program->Position,

+                                     "3: Undefined variable");

+            _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",

+                         src->name);

+            return 1;

+         }

+

+         switch (src->type) {

+            case vt_attrib:

+               *File = PROGRAM_INPUT;

+               *Index = src->attrib_binding_idx;

+               break;

+

+               /* XXX: We have to handle offsets someplace in here!  -- or are those above? */

+            case vt_param:

+               *File = src->param_binding_type;

+               *Index = src->param_binding_begin;

+               break;

+

+            case vt_temp:

+               *File = PROGRAM_TEMPORARY;

+               *Index = src->temp_binding;

+               break;

+

+               /* If the var type is vt_output no go */

+            default:

+               _mesa_set_program_error (ctx, Program->Position,

+                                        "destination register is read only");

+               _mesa_error (ctx, GL_INVALID_OPERATION,

+                            "destination register is read only: %s",

+                            src->name);

+               return 1;

+         }

+         break;

+

+      default:

+         _mesa_set_program_error (ctx, Program->Position,

+                                  "Unknown token in parse_src_reg");

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Unknown token in parse_src_reg");

+         return 1;

+   }

+

+   return 0;

+}

+

+/**

+ */

+static GLuint

+parse_vector_src_reg (GLcontext * ctx, GLubyte ** inst,

+                      struct var_cache **vc_head, struct arb_program *Program,

+                      GLint * File, GLint * Index, GLboolean * Negate,

+                      GLubyte * Swizzle, GLboolean *IsRelOffset)

+{

+   /* Grab the sign */

+   *Negate = parse_sign (inst);

+

+   /* And the src reg */

+   if (parse_src_reg (ctx, inst, vc_head, Program, File, Index, IsRelOffset))

+      return 1;

+

+   /* finally, the swizzle */

+   parse_swizzle_mask (inst, Swizzle, 4);

+

+   return 0;

+}

+

+/**

+ */

+static GLuint

+parse_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,

+                      struct var_cache **vc_head, struct arb_program *Program,

+                      GLint * File, GLint * Index, GLboolean * Negate,

+                      GLubyte * Swizzle, GLboolean *IsRelOffset)

+{

+   /* Grab the sign */

+   *Negate = parse_sign (inst);

+

+   /* And the src reg */

+   if (parse_src_reg (ctx, inst, vc_head, Program, File, Index, IsRelOffset))

+      return 1;

+

+   /* Now, get the component and shove it into all the swizzle slots  */

+   parse_swizzle_mask (inst, Swizzle, 1);

+

+   return 0;

+}

+

+/**

+ * This is a big mother that handles getting opcodes into the instruction

+ * and handling the src & dst registers for fragment program instructions

+ */

+static GLuint

+parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,

+                      struct var_cache **vc_head, struct arb_program *Program,

+                      struct fp_instruction *fp)

+{

+   GLint a, b;

+   GLubyte swz[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */

+   GLuint texcoord;

+   GLubyte instClass, type, code;

+   GLboolean rel;

+

+   /* No condition codes in ARB_fp */

+   fp->UpdateCondRegister = 0;

+

+   /* Record the position in the program string for debugging */

+   fp->StringPos = Program->Position;

+

+   /* OP_ALU_INST or OP_TEX_INST */

+   instClass = *(*inst)++;

+

+   /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},

+    * OP_TEX_{SAMPLE, KIL}

+    */

+   type = *(*inst)++;

+

+   /* The actual opcode name */

+   code = *(*inst)++;

+

+   /* Increment the correct count */

+   switch (instClass) {

+      case OP_ALU_INST:

+         Program->NumAluInstructions++;

+         break;

+      case OP_TEX_INST:

+         Program->NumTexInstructions++;

+         break;

+   }

+

+   fp->Saturate = 0;

+   fp->Precision = FLOAT32;

+

+   fp->DstReg.CondMask = COND_TR;

+

+   switch (type) {

+      case OP_ALU_VECTOR:

+         switch (code) {

+            case OP_ABS_SAT:

+               fp->Saturate = 1;

+            case OP_ABS:

+               fp->Opcode = FP_OPCODE_ABS;

+               break;

+

+            case OP_FLR_SAT:

+               fp->Saturate = 1;

+            case OP_FLR:

+               fp->Opcode = FP_OPCODE_FLR;

+               break;

+

+            case OP_FRC_SAT:

+               fp->Saturate = 1;

+            case OP_FRC:

+               fp->Opcode = FP_OPCODE_FRC;

+               break;

+

+            case OP_LIT_SAT:

+               fp->Saturate = 1;

+            case OP_LIT:

+               fp->Opcode = FP_OPCODE_LIT;

+               break;

+

+            case OP_MOV_SAT:

+               fp->Saturate = 1;

+            case OP_MOV:

+               fp->Opcode = FP_OPCODE_MOV;

+               break;

+         }

+

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,

+              &fp->DstReg.Index, fp->DstReg.WriteMask))

+            return 1;

+

+         fp->SrcReg[0].Abs = GL_FALSE;

+         fp->SrcReg[0].NegateAbs = GL_FALSE;

+         if (parse_vector_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,

+              &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,

+              swz, &rel))

+            return 1;

+         for (b=0; b<4; b++)

+            fp->SrcReg[0].Swizzle[b] = swz[b];

+         break;

+

+      case OP_ALU_SCALAR:

+         switch (code) {

+            case OP_COS_SAT:

+               fp->Saturate = 1;

+            case OP_COS:

+               fp->Opcode = FP_OPCODE_COS;

+               break;

+

+            case OP_EX2_SAT:

+               fp->Saturate = 1;

+            case OP_EX2:

+               fp->Opcode = FP_OPCODE_EX2;

+               break;

+

+            case OP_LG2_SAT:

+               fp->Saturate = 1;

+            case OP_LG2:

+               fp->Opcode = FP_OPCODE_LG2;

+               break;

+

+            case OP_RCP_SAT:

+               fp->Saturate = 1;

+            case OP_RCP:

+               fp->Opcode = FP_OPCODE_RCP;

+               break;

+

+            case OP_RSQ_SAT:

+               fp->Saturate = 1;

+            case OP_RSQ:

+               fp->Opcode = FP_OPCODE_RSQ;

+               break;

+

+            case OP_SIN_SAT:

+               fp->Saturate = 1;

+            case OP_SIN:

+               fp->Opcode = FP_OPCODE_SIN;

+               break;

+

+            case OP_SCS_SAT:

+               fp->Saturate = 1;

+            case OP_SCS:

+

+               fp->Opcode = FP_OPCODE_SCS;

+               break;

+         }

+

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,

+              &fp->DstReg.Index, fp->DstReg.WriteMask))

+            return 1;

+         fp->SrcReg[0].Abs = GL_FALSE;

+         fp->SrcReg[0].NegateAbs = GL_FALSE;

+         if (parse_scalar_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,

+              &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,

+              swz, &rel))

+            return 1;

+         for (b=0; b<4; b++)

+            fp->SrcReg[0].Swizzle[b] = swz[b];

+         break;

+

+      case OP_ALU_BINSC:

+         switch (code) {

+            case OP_POW_SAT:

+               fp->Saturate = 1;

+            case OP_POW:

+               fp->Opcode = FP_OPCODE_POW;

+               break;

+         }

+

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,

+              &fp->DstReg.Index, fp->DstReg.WriteMask))

+            return 1;

+         for (a = 0; a < 2; a++) {

+            fp->SrcReg[a].Abs = GL_FALSE;

+            fp->SrcReg[a].NegateAbs = GL_FALSE;

+            if (parse_scalar_src_reg

+                (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,

+                 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,

+                 swz, &rel))

+               return 1;

+            for (b=0; b<4; b++)

+               fp->SrcReg[a].Swizzle[b] = swz[b];

+         }

+         break;

+

+

+      case OP_ALU_BIN:

+         switch (code) {

+            case OP_ADD_SAT:

+               fp->Saturate = 1;

+            case OP_ADD:

+               fp->Opcode = FP_OPCODE_ADD;

+               break;

+

+            case OP_DP3_SAT:

+               fp->Saturate = 1;

+            case OP_DP3:

+               fp->Opcode = FP_OPCODE_DP3;

+               break;

+

+            case OP_DP4_SAT:

+               fp->Saturate = 1;

+            case OP_DP4:

+               fp->Opcode = FP_OPCODE_DP4;

+               break;

+

+            case OP_DPH_SAT:

+               fp->Saturate = 1;

+            case OP_DPH:

+               fp->Opcode = FP_OPCODE_DPH;

+               break;

+

+            case OP_DST_SAT:

+               fp->Saturate = 1;

+            case OP_DST:

+               fp->Opcode = FP_OPCODE_DST;

+               break;

+

+            case OP_MAX_SAT:

+               fp->Saturate = 1;

+            case OP_MAX:

+               fp->Opcode = FP_OPCODE_MAX;

+               break;

+

+            case OP_MIN_SAT:

+               fp->Saturate = 1;

+            case OP_MIN:

+               fp->Opcode = FP_OPCODE_MIN;

+               break;

+

+            case OP_MUL_SAT:

+               fp->Saturate = 1;

+            case OP_MUL:

+               fp->Opcode = FP_OPCODE_MUL;

+               break;

+

+            case OP_SGE_SAT:

+               fp->Saturate = 1;

+            case OP_SGE:

+               fp->Opcode = FP_OPCODE_SGE;

+               break;

+

+            case OP_SLT_SAT:

+               fp->Saturate = 1;

+            case OP_SLT:

+               fp->Opcode = FP_OPCODE_SLT;

+               break;

+

+            case OP_SUB_SAT:

+               fp->Saturate = 1;

+            case OP_SUB:

+               fp->Opcode = FP_OPCODE_SUB;

+               break;

+

+            case OP_XPD_SAT:

+               fp->Saturate = 1;

+            case OP_XPD:

+               fp->Opcode = FP_OPCODE_XPD;

+               break;

+         }

+

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,

+              &fp->DstReg.Index, fp->DstReg.WriteMask))

+            return 1;

+         for (a = 0; a < 2; a++) {

+            fp->SrcReg[a].Abs = GL_FALSE;

+            fp->SrcReg[a].NegateAbs = GL_FALSE;

+            if (parse_vector_src_reg

+                (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,

+                 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,

+                 swz, &rel))

+               return 1;

+            for (b=0; b<4; b++)

+               fp->SrcReg[a].Swizzle[b] = swz[b];

+         }

+         break;

+

+      case OP_ALU_TRI:

+         switch (code) {

+            case OP_CMP_SAT:

+               fp->Saturate = 1;

+            case OP_CMP:

+               fp->Opcode = FP_OPCODE_CMP;

+               break;

+

+            case OP_LRP_SAT:

+               fp->Saturate = 1;

+            case OP_LRP:

+               fp->Opcode = FP_OPCODE_LRP;

+               break;

+

+            case OP_MAD_SAT:

+               fp->Saturate = 1;

+            case OP_MAD:

+               fp->Opcode = FP_OPCODE_MAD;

+               break;

+         }

+

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,

+              &fp->DstReg.Index, fp->DstReg.WriteMask))

+            return 1;

+         for (a = 0; a < 3; a++) {

+            fp->SrcReg[a].Abs = GL_FALSE;

+            fp->SrcReg[a].NegateAbs = GL_FALSE;

+            if (parse_vector_src_reg

+                (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,

+                 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,

+                 swz, &rel))

+               return 1;

+            for (b=0; b<4; b++)

+               fp->SrcReg[a].Swizzle[b] = swz[b];

+         }

+         break;

+

+      case OP_ALU_SWZ:

+         switch (code) {

+            case OP_SWZ_SAT:

+               fp->Saturate = 1;

+            case OP_SWZ:

+               fp->Opcode = FP_OPCODE_SWZ;

+               break;

+         }

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,

+              &fp->DstReg.Index, fp->DstReg.WriteMask))

+            return 1;

+

+         if (parse_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,

+              &fp->SrcReg[0].Index, &rel))

+            return 1;

+         parse_extended_swizzle_mask (inst, swz,

+                                      &fp->SrcReg[0].NegateBase);

+         for (b=0; b<4; b++)

+            fp->SrcReg[0].Swizzle[b] = swz[b];

+         break;

+

+      case OP_TEX_SAMPLE:

+         switch (code) {

+            case OP_TEX_SAT:

+               fp->Saturate = 1;

+            case OP_TEX:

+               fp->Opcode = FP_OPCODE_TEX;

+               break;

+

+            case OP_TXP_SAT:

+               fp->Saturate = 1;

+            case OP_TXP:

+               fp->Opcode = FP_OPCODE_TXP;

+               break;

+

+            case OP_TXB_SAT:

+

+               fp->Saturate = 1;

+            case OP_TXB:

+               fp->Opcode = FP_OPCODE_TXB;

+               break;

+         }

+

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,

+              &fp->DstReg.Index, fp->DstReg.WriteMask))

+            return 1;

+         fp->SrcReg[0].Abs = GL_FALSE;

+         fp->SrcReg[0].NegateAbs = GL_FALSE;

+         if (parse_vector_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,

+              &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,

+              swz, &rel))

+            return 1;

+         for (b=0; b<4; b++)

+            fp->SrcReg[0].Swizzle[b] = swz[b];

+

+         /* texImageUnit */

+         if (parse_texcoord_num (ctx, inst, Program, &texcoord))

+            return 1;

+         fp->TexSrcUnit = texcoord;

+

+         /* texTarget */

+         switch (*(*inst)++) {

+            case TEXTARGET_1D:

+               fp->TexSrcBit = TEXTURE_1D_BIT;

+               break;

+            case TEXTARGET_2D:

+               fp->TexSrcBit = TEXTURE_2D_BIT;

+               break;

+            case TEXTARGET_3D:

+               fp->TexSrcBit = TEXTURE_3D_BIT;

+               break;

+            case TEXTARGET_RECT:

+               fp->TexSrcBit = TEXTURE_RECT_BIT;

+               break;

+            case TEXTARGET_CUBE:

+               fp->TexSrcBit = TEXTURE_CUBE_BIT;

+               break;

+	    case TEXTARGET_SHADOW1D:

+	    case TEXTARGET_SHADOW2D:

+	    case TEXTARGET_SHADOWRECT:

+	       /* TODO ARB_fragment_program_shadow code */

+	       break;

+         }

+         Program->TexturesUsed[texcoord] |= fp->TexSrcBit;

+         break;

+

+      case OP_TEX_KIL:

+         fp->Opcode = FP_OPCODE_KIL;

+         fp->SrcReg[0].Abs = GL_FALSE;

+         fp->SrcReg[0].NegateAbs = GL_FALSE;

+         if (parse_vector_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,

+              &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,

+              swz, &rel))

+            return 1;

+         for (b=0; b<4; b++)

+            fp->SrcReg[0].Swizzle[b] = swz[b];

+         break;

+   }

+

+   return 0;

+}

+

+/**

+ * This is a big mother that handles getting opcodes into the instruction

+ * and handling the src & dst registers for vertex program instructions

+ */

+static GLuint

+parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,

+                      struct var_cache **vc_head, struct arb_program *Program,

+                      struct vp_instruction *vp)

+{

+   GLint a;

+   GLubyte type, code;

+

+   /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */

+   type = *(*inst)++;

+

+   /* The actual opcode name */

+   code = *(*inst)++;

+

+   /* Record the position in the program string for debugging */

+   vp->StringPos = Program->Position;

+

+   vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0;

+

+   for (a = 0; a < 4; a++) {

+      vp->SrcReg[0].Swizzle[a] = a;

+      vp->SrcReg[1].Swizzle[a] = a;

+      vp->SrcReg[2].Swizzle[a] = a;

+      vp->DstReg.WriteMask[a] = 1;

+   }

+

+   switch (type) {

+         /* XXX: */

+      case OP_ALU_ARL:

+         vp->Opcode = VP_OPCODE_ARL;

+

+         /* Remember to set SrcReg.RelAddr; */

+

+         /* Get the masked address register [dst] */

+         if (parse_masked_address_reg

+             (ctx, inst, vc_head, Program, &vp->DstReg.Index,

+              vp->DstReg.WriteMask))

+            return 1;

+         vp->DstReg.File = PROGRAM_ADDRESS;

+

+         /* Get a scalar src register */

+         if (parse_scalar_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,

+              &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,

+              vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))

+            return 1;

+

+         break;

+

+      case OP_ALU_VECTOR:

+         switch (code) {

+            case OP_ABS:

+               vp->Opcode = VP_OPCODE_ABS;

+               break;

+            case OP_FLR:

+               vp->Opcode = VP_OPCODE_FLR;

+               break;

+            case OP_FRC:

+               vp->Opcode = VP_OPCODE_FRC;

+               break;

+            case OP_LIT:

+               vp->Opcode = VP_OPCODE_LIT;

+               break;

+            case OP_MOV:

+               vp->Opcode = VP_OPCODE_MOV;

+               break;

+         }

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,

+              &vp->DstReg.Index, vp->DstReg.WriteMask))

+            return 1;

+         if (parse_vector_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,

+              &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,

+              vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))

+            return 1;

+         break;

+

+      case OP_ALU_SCALAR:

+         switch (code) {

+            case OP_EX2:

+               vp->Opcode = VP_OPCODE_EX2;

+               break;

+            case OP_EXP:

+               vp->Opcode = VP_OPCODE_EXP;

+               break;

+            case OP_LG2:

+               vp->Opcode = VP_OPCODE_LG2;

+               break;

+            case OP_LOG:

+               vp->Opcode = VP_OPCODE_LOG;

+               break;

+            case OP_RCP:

+               vp->Opcode = VP_OPCODE_RCP;

+               break;

+            case OP_RSQ:

+               vp->Opcode = VP_OPCODE_RSQ;

+               break;

+         }

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,

+              &vp->DstReg.Index, vp->DstReg.WriteMask))

+            return 1;

+         if (parse_scalar_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,

+              &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,

+              vp->SrcReg[0].Swizzle, &vp->SrcReg[0].RelAddr))

+            return 1;

+         break;

+

+      case OP_ALU_BINSC:

+         switch (code) {

+            case OP_POW:

+               vp->Opcode = VP_OPCODE_POW;

+               break;

+         }

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,

+              &vp->DstReg.Index, vp->DstReg.WriteMask))

+            return 1;

+         for (a = 0; a < 2; a++) {

+            if (parse_scalar_src_reg

+                (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,

+                 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,

+                 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))

+               return 1;

+         }

+         break;

+

+      case OP_ALU_BIN:

+         switch (code) {

+            case OP_ADD:

+               vp->Opcode = VP_OPCODE_ADD;

+               break;

+            case OP_DP3:

+               vp->Opcode = VP_OPCODE_DP3;

+               break;

+            case OP_DP4:

+               vp->Opcode = VP_OPCODE_DP4;

+               break;

+            case OP_DPH:

+               vp->Opcode = VP_OPCODE_DPH;

+               break;

+            case OP_DST:

+               vp->Opcode = VP_OPCODE_DST;

+               break;

+            case OP_MAX:

+               vp->Opcode = VP_OPCODE_MAX;

+               break;

+            case OP_MIN:

+               vp->Opcode = VP_OPCODE_MIN;

+               break;

+            case OP_MUL:

+               vp->Opcode = VP_OPCODE_MUL;

+               break;

+            case OP_SGE:

+               vp->Opcode = VP_OPCODE_SGE;

+               break;

+            case OP_SLT:

+               vp->Opcode = VP_OPCODE_SLT;

+               break;

+            case OP_SUB:

+               vp->Opcode = VP_OPCODE_SUB;

+               break;

+            case OP_XPD:

+               vp->Opcode = VP_OPCODE_XPD;

+               break;

+         }

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,

+              &vp->DstReg.Index, vp->DstReg.WriteMask))

+            return 1;

+         for (a = 0; a < 2; a++) {

+            if (parse_vector_src_reg

+                (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,

+                 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,

+                 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))

+               return 1;

+         }

+         break;

+

+      case OP_ALU_TRI:

+         switch (code) {

+            case OP_MAD:

+               vp->Opcode = VP_OPCODE_MAD;

+               break;

+         }

+

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,

+              &vp->DstReg.Index, vp->DstReg.WriteMask))

+            return 1;

+         for (a = 0; a < 3; a++) {

+            if (parse_vector_src_reg

+                (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,

+                 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,

+                 vp->SrcReg[a].Swizzle, &vp->SrcReg[a].RelAddr))

+               return 1;

+         }

+         break;

+

+      case OP_ALU_SWZ:

+         switch (code) {

+            case OP_SWZ:

+               vp->Opcode = VP_OPCODE_SWZ;

+               break;

+         }

+         if (parse_masked_dst_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,

+              &vp->DstReg.Index, vp->DstReg.WriteMask))

+            return 1;

+

+         if (parse_src_reg

+             (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,

+              &vp->SrcReg[0].Index, &vp->SrcReg[0].RelAddr))

+            return 1;

+         parse_extended_swizzle_mask (inst, vp->SrcReg[0].Swizzle,

+                                      &vp->SrcReg[0].Negate);

+         break;

+   }

+   return 0;

+}

+

+#if DEBUG_PARSING

+

+static GLvoid

+print_state_token (GLint token)

+{

+   switch (token) {

+      case STATE_MATERIAL:

+         fprintf (stderr, "STATE_MATERIAL ");

+         break;

+      case STATE_LIGHT:

+         fprintf (stderr, "STATE_LIGHT ");

+         break;

+

+      case STATE_LIGHTMODEL_AMBIENT:

+         fprintf (stderr, "STATE_AMBIENT ");

+         break;

+

+      case STATE_LIGHTMODEL_SCENECOLOR:

+         fprintf (stderr, "STATE_SCENECOLOR ");

+         break;

+

+      case STATE_LIGHTPROD:

+         fprintf (stderr, "STATE_LIGHTPROD ");

+         break;

+

+      case STATE_TEXGEN:

+         fprintf (stderr, "STATE_TEXGEN ");

+         break;

+

+      case STATE_FOG_COLOR:

+         fprintf (stderr, "STATE_FOG_COLOR ");

+         break;

+

+      case STATE_FOG_PARAMS:

+         fprintf (stderr, "STATE_FOG_PARAMS ");

+         break;

+

+      case STATE_CLIPPLANE:

+         fprintf (stderr, "STATE_CLIPPLANE ");

+         break;

+

+      case STATE_POINT_SIZE:

+         fprintf (stderr, "STATE_POINT_SIZE ");

+         break;

+

+      case STATE_POINT_ATTENUATION:

+         fprintf (stderr, "STATE_ATTENUATION ");

+         break;

+

+      case STATE_MATRIX:

+         fprintf (stderr, "STATE_MATRIX ");

+         break;

+

+      case STATE_MODELVIEW:

+         fprintf (stderr, "STATE_MODELVIEW ");

+         break;

+

+      case STATE_PROJECTION:

+         fprintf (stderr, "STATE_PROJECTION ");

+         break;

+

+      case STATE_MVP:

+         fprintf (stderr, "STATE_MVP ");

+         break;

+

+      case STATE_TEXTURE:

+         fprintf (stderr, "STATE_TEXTURE ");

+         break;

+

+      case STATE_PROGRAM:

+         fprintf (stderr, "STATE_PROGRAM ");

+         break;

+

+      case STATE_MATRIX_INVERSE:

+         fprintf (stderr, "STATE_INVERSE ");

+         break;

+

+      case STATE_MATRIX_TRANSPOSE:

+         fprintf (stderr, "STATE_TRANSPOSE ");

+         break;

+

+      case STATE_MATRIX_INVTRANS:

+         fprintf (stderr, "STATE_INVTRANS ");

+         break;

+

+      case STATE_AMBIENT:

+         fprintf (stderr, "STATE_AMBIENT ");

+         break;

+

+      case STATE_DIFFUSE:

+         fprintf (stderr, "STATE_DIFFUSE ");

+         break;

+

+      case STATE_SPECULAR:

+         fprintf (stderr, "STATE_SPECULAR ");

+         break;

+

+      case STATE_EMISSION:

+         fprintf (stderr, "STATE_EMISSION ");

+         break;

+

+      case STATE_SHININESS:

+         fprintf (stderr, "STATE_SHININESS ");

+         break;

+

+      case STATE_HALF:

+         fprintf (stderr, "STATE_HALF ");

+         break;

+

+      case STATE_POSITION:

+         fprintf (stderr, "STATE_POSITION ");

+         break;

+

+      case STATE_ATTENUATION:

+         fprintf (stderr, "STATE_ATTENUATION ");

+         break;

+

+      case STATE_SPOT_DIRECTION:

+         fprintf (stderr, "STATE_DIRECTION ");

+         break;

+

+      case STATE_TEXGEN_EYE_S:

+         fprintf (stderr, "STATE_TEXGEN_EYE_S ");

+         break;

+

+      case STATE_TEXGEN_EYE_T:

+         fprintf (stderr, "STATE_TEXGEN_EYE_T ");

+         break;

+

+      case STATE_TEXGEN_EYE_R:

+         fprintf (stderr, "STATE_TEXGEN_EYE_R ");

+         break;

+

+      case STATE_TEXGEN_EYE_Q:

+         fprintf (stderr, "STATE_TEXGEN_EYE_Q ");

+         break;

+

+      case STATE_TEXGEN_OBJECT_S:

+         fprintf (stderr, "STATE_TEXGEN_EYE_S ");

+         break;

+

+      case STATE_TEXGEN_OBJECT_T:

+         fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");

+         break;

+

+      case STATE_TEXGEN_OBJECT_R:

+         fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");

+         break;

+

+      case STATE_TEXGEN_OBJECT_Q:

+         fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");

+         break;

+

+      case STATE_TEXENV_COLOR:

+         fprintf (stderr, "STATE_TEXENV_COLOR ");

+         break;

+

+      case STATE_DEPTH_RANGE:

+         fprintf (stderr, "STATE_DEPTH_RANGE ");

+         break;

+

+      case STATE_VERTEX_PROGRAM:

+         fprintf (stderr, "STATE_VERTEX_PROGRAM ");

+         break;

+

+      case STATE_FRAGMENT_PROGRAM:

+         fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");

+         break;

+

+      case STATE_ENV:

+         fprintf (stderr, "STATE_ENV ");

+         break;

+

+      case STATE_LOCAL:

+         fprintf (stderr, "STATE_LOCAL ");

+         break;

+

+   }

+   fprintf (stderr, "[%d] ", token);

+}

+

+

+static GLvoid

+debug_variables (GLcontext * ctx, struct var_cache *vc_head,

+                 struct arb_program *Program)

+{

+   struct var_cache *vc;

+   GLint a, b;

+

+   fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);

+

+   /* First of all, print out the contents of the var_cache */

+   vc = vc_head;

+   while (vc) {

+      fprintf (stderr, "[%x]\n", vc);

+      switch (vc->type) {

+         case vt_none:

+            fprintf (stderr, "UNDEFINED %s\n", vc->name);

+            break;

+         case vt_attrib:

+            fprintf (stderr, "ATTRIB    %s\n", vc->name);

+            fprintf (stderr, "          binding: 0x%x\n", vc->attrib_binding);

+            break;

+         case vt_param:

+            fprintf (stderr, "PARAM     %s  begin: %d len: %d\n", vc->name,

+                     vc->param_binding_begin, vc->param_binding_length);

+            b = vc->param_binding_begin;

+            for (a = 0; a < vc->param_binding_length; a++) {

+               fprintf (stderr, "%s\n",

+                        Program->Parameters->Parameters[a + b].Name);

+               if (Program->Parameters->Parameters[a + b].Type == STATE) {

+                  print_state_token (Program->Parameters->Parameters[a + b].

+                                     StateIndexes[0]);

+                  print_state_token (Program->Parameters->Parameters[a + b].

+                                     StateIndexes[1]);

+                  print_state_token (Program->Parameters->Parameters[a + b].

+                                     StateIndexes[2]);

+                  print_state_token (Program->Parameters->Parameters[a + b].

+                                     StateIndexes[3]);

+                  print_state_token (Program->Parameters->Parameters[a + b].

+                                     StateIndexes[4]);

+                  print_state_token (Program->Parameters->Parameters[a + b].

+                                     StateIndexes[5]);

+               }

+               else

+                  fprintf (stderr, "%f %f %f %f\n",

+                           Program->Parameters->Parameters[a + b].Values[0],

+                           Program->Parameters->Parameters[a + b].Values[1],

+                           Program->Parameters->Parameters[a + b].Values[2],

+                           Program->Parameters->Parameters[a + b].Values[3]);

+            }

+            break;

+         case vt_temp:

+            fprintf (stderr, "TEMP      %s\n", vc->name);

+            fprintf (stderr, "          binding: 0x%x\n", vc->temp_binding);

+            break;

+         case vt_output:

+            fprintf (stderr, "OUTPUT    %s\n", vc->name);

+            fprintf (stderr, "          binding: 0x%x\n", vc->output_binding);

+            break;

+         case vt_alias:

+            fprintf (stderr, "ALIAS     %s\n", vc->name);

+            fprintf (stderr, "          binding: 0x%x (%s)\n",

+                     vc->alias_binding, vc->alias_binding->name);

+            break;

+      }

+      vc = vc->next;

+   }

+}

+

+#endif

+

+

+/**

+ * The main loop for parsing a fragment or vertex program

+ *

+ * \return 0 on sucess, 1 on error

+ */

+static GLint

+parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,

+                   struct arb_program *Program)

+{

+   GLint err = 0;

+

+   Program->MajorVersion = (GLuint) * inst++;

+   Program->MinorVersion = (GLuint) * inst++;

+

+   while (*inst != END) {

+      switch (*inst++) {

+

+         case OPTION:

+            switch (*inst++) {

+               case ARB_PRECISION_HINT_FASTEST:

+                  Program->PrecisionOption = GL_FASTEST;

+                  break;

+

+               case ARB_PRECISION_HINT_NICEST:

+                  Program->PrecisionOption = GL_NICEST;

+                  break;

+

+               case ARB_FOG_EXP:

+                  Program->FogOption = GL_EXP;

+                  break;

+

+               case ARB_FOG_EXP2:

+                  Program->FogOption = GL_EXP2;

+                  break;

+

+               case ARB_FOG_LINEAR:

+                  Program->FogOption = GL_LINEAR;

+                  break;

+

+               case ARB_POSITION_INVARIANT:

+                  if (Program->Base.Target == GL_VERTEX_PROGRAM_ARB)

+                     Program->HintPositionInvariant = 1;

+                  break;

+

+               case ARB_FRAGMENT_PROGRAM_SHADOW:

+	          if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {

+	             /* TODO ARB_fragment_program_shadow code */

+		  }

+		  break;

+            }

+            break;

+

+         case INSTRUCTION:

+            Program->Position = parse_position (&inst);

+

+            if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {

+

+               /* Check the instruction count

+                * XXX: Does END count as an instruction?

+                */

+               if (Program->Base.NumInstructions+1 == MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS) {

+                  _mesa_set_program_error (ctx, Program->Position,

+                      "Max instruction count exceeded!");

+                  _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Max instruction count exceeded!");

+               }

+

+               /* Realloc Program->FPInstructions */

+               Program->FPInstructions =

+                  (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,

+                                                           Program->Base.NumInstructions*sizeof(struct fp_instruction),

+                                                           (Program->Base.NumInstructions+1)*sizeof (struct fp_instruction));

+

+               /* parse the current instruction   */

+               err = parse_fp_instruction (ctx, &inst, vc_head, Program,

+                                           &Program->FPInstructions[Program->Base.NumInstructions]);

+

+            }

+            else {

+               /* Check the instruction count

+                * XXX: Does END count as an instruction?

+                */

+               if (Program->Base.NumInstructions+1 == MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS) {

+                  _mesa_set_program_error (ctx, Program->Position,

+                      "Max instruction count exceeded!");

+                  _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Max instruction count exceeded!");

+               }

+

+               /* Realloc Program->VPInstructions */

+               Program->VPInstructions =

+                  (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,

+                                                           Program->Base.NumInstructions*sizeof(struct vp_instruction),

+                                                           (Program->Base.NumInstructions +1)*sizeof(struct vp_instruction));

+

+               /* parse the current instruction   */

+               err = parse_vp_instruction (ctx, &inst, vc_head, Program,

+                                           &Program->VPInstructions[Program->Base.NumInstructions]);

+            }

+

+            /* increment Program->Base.NumInstructions */

+            Program->Base.NumInstructions++;

+            break;

+

+         case DECLARATION:

+            err = parse_declaration (ctx, &inst, vc_head, Program);

+            break;

+

+         default:

+            break;

+      }

+

+      if (err)

+         break;

+   }

+

+   /* Finally, tag on an OPCODE_END instruction */

+   if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {

+      Program->FPInstructions =

+         (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,

+						  Program->Base.NumInstructions*sizeof(struct fp_instruction),

+                                                  (Program->Base.NumInstructions+1)*sizeof(struct fp_instruction));

+

+      Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END;

+      /* YYY Wrong Position in program, whatever, at least not random -> crash

+	 Program->Position = parse_position (&inst);

+      */

+      Program->FPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;

+   }

+   else {

+      Program->VPInstructions =

+         (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,

+                                                  Program->Base.NumInstructions*sizeof(struct vp_instruction),

+                                                  (Program->Base.NumInstructions+1)*sizeof(struct vp_instruction));

+

+      Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END;

+      /* YYY Wrong Position in program, whatever, at least not random -> crash

+	 Program->Position = parse_position (&inst);

+      */

+      Program->VPInstructions[Program->Base.NumInstructions].StringPos = Program->Position;

+   }

+

+   /* increment Program->Base.NumInstructions */

+   Program->Base.NumInstructions++;

+

+   return err;

+}

+

+/* XXX temporary */

+static char core_grammar_text[] =

+#include "grammar_syn.h"

+;

+

+static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)

+{

+   char error_msg[300];

+   GLint error_pos;

+

+   if (grammar_set_reg8 (id, name, value))

+      return 0;

+

+   grammar_get_last_error ((byte *) error_msg, 300, &error_pos);

+   _mesa_set_program_error (ctx, error_pos, error_msg);

+   _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar Register Error");

+   return 1;

+}

+

+static int extension_is_supported (const GLubyte *ext)

+{

+   const GLubyte *extensions = glGetString (GL_EXTENSIONS);

+   const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);

+   const GLint ext_len = _mesa_strlen ((const char *) ext);

+

    while (extensions < end)

    {

       const GLubyte *name_end = (const GLubyte *) strchr ((const char *) extensions, ' ');

@@ -3732,222 +3732,222 @@
          return 1;

       extensions = name_end + 1;

    }

-
-   return 0;
-}
-
-static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
-{
-   if (extension_is_supported (extname))
-      if (set_reg8 (ctx, id, name, 0x01))
-         return 1;
-   return 0;
-}
-
-/**
- * This kicks everything off.
- *
- * \param ctx - The GL Context
- * \param str - The program string
- * \param len - The program string length
- * \param Program - The arb_program struct to return all the parsed info in
- * \return 0 on sucess, 1 on error
- */
-GLuint
-_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
-                         struct arb_program * program)
-{
-   GLint a, err, error_pos;
-   char error_msg[300];
-   GLuint parsed_len;
-   struct var_cache *vc_head;
-   grammar arbprogram_syn_id;
-   GLubyte *parsed, *inst;
-   GLubyte *strz = NULL;
-   static int arbprogram_syn_is_ok = 0;		/* XXX temporary */
-
-#if DEBUG_PARSING
-   fprintf (stderr, "Loading grammar text!\n");
-#endif
-
-   /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
-   if (!arbprogram_syn_is_ok) {
-      grammar grammar_syn_id;
-      GLint err;
-      GLuint parsed_len;
-      byte *parsed;
-
-      grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
-      if (grammar_syn_id == 0) {
-         grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
-         _mesa_set_program_error (ctx, error_pos, error_msg);
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Error loading grammar rule set");
-         return 1;
-      }
-
-      err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
-
-      /* NOTE: we cant destroy grammar_syn_id right here because grammar_destroy() can
-         reset the last error
-      */
-
-      if (err == 0) {
-         grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
-         _mesa_set_program_error (ctx, error_pos, error_msg);
-         _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
-
-         grammar_destroy (grammar_syn_id);
-         return 1;
-      }
-
-      grammar_destroy (grammar_syn_id);
-
-      arbprogram_syn_is_ok = 1;
-   }
-
-   /* create the grammar object */
-   arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
-   if (arbprogram_syn_id == 0) {
-      grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
-      _mesa_set_program_error (ctx, error_pos, error_msg);
-      _mesa_error (ctx, GL_INVALID_OPERATION,
-                   "Error loading grammer rule set");
-      return 1;
-   }
-
-   /* Set program_target register value */
-   if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",
-      program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {
-      grammar_destroy (arbprogram_syn_id);
-      return 1;
-   }
-
-   /* Enable all active extensions */
-   if (enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
-       enable_ext (ctx, arbprogram_syn_id,
-          (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow")) {
-      grammar_destroy (arbprogram_syn_id);
-      return 1;
-   }
-
-   /* check for NULL character occurences */
-   {
-      int i;
-      for (i = 0; i < len; i++)
-         if (str[i] == '\0') {
-            _mesa_set_program_error (ctx, i, "invalid character");
-            _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
-
-            grammar_destroy (arbprogram_syn_id);
-            return 1;
-         }
-   }
-
-   /* copy the program string to a null-terminated string */
-   /* XXX should I check for NULL from malloc()? */
-   strz = _mesa_malloc (len + 1);
-   _mesa_memcpy (strz, str, len);
-   strz[len] = '\0';
-
-#if DEBUG_PARSING
-   printf ("Checking Grammar!\n");
-#endif
-   err = grammar_check (arbprogram_syn_id, strz, &parsed, &parsed_len);
-
-   /* Syntax parse error */
-   if (err == 0) {
-      _mesa_free (strz);
-      grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
-      _mesa_set_program_error (ctx, error_pos, error_msg);
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Parse Error");
-
-      grammar_destroy (arbprogram_syn_id);
-      return 1;
-   }
-
-#if DEBUG_PARSING
-   printf ("Destroying grammer dict [parse retval: %d]\n", err);
-#endif
-   grammar_destroy (arbprogram_syn_id);
-
-   /* Initialize the arb_program struct */
-   program->Base.String = strz;
-   program->Base.NumInstructions =
-   program->Base.NumTemporaries =
-   program->Base.NumParameters =
-   program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
-   program->Parameters = _mesa_new_parameter_list ();
-   program->InputsRead = 0;
-   program->OutputsWritten = 0;
-   program->Position = 0;
-   program->MajorVersion = program->MinorVersion = 0;
-   program->PrecisionOption = GL_DONT_CARE;
-   program->FogOption = GL_NONE;
-   program->HintPositionInvariant = GL_FALSE;
-   for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
-      program->TexturesUsed[a] = 0;
-   program->NumAluInstructions =
-   program->NumTexInstructions =
-   program->NumTexIndirections = 0;
-
-   program->FPInstructions = NULL;
-   program->VPInstructions = NULL;
-
-   vc_head = NULL;
-   err = 0;
-
-   /* Start examining the tokens in the array */
-   inst = parsed;
-
-   /* Check the grammer rev */
-   if (*inst++ != REVISION) {
-      _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar verison mismatch");
-      err = 1;
-   }
-   else {
-      switch (*inst++) {
-         case FRAGMENT_PROGRAM:
-            program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
-            break;
-
-         case VERTEX_PROGRAM:
-            program->Base.Target = GL_VERTEX_PROGRAM_ARB;
-            break;
-      }
-
-      err = parse_arb_program (ctx, inst, &vc_head, program);
-#if DEBUG_PARSING
-      fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
-#endif
-   }
-
-   /*debug_variables(ctx, vc_head, program); */
-
-   /* We're done with the parsed binary array */
-   var_cache_destroy (&vc_head);
-
-   _mesa_free (parsed);
-#if DEBUG_PARSING
-   printf ("_mesa_parse_arb_program() done\n");
-#endif
-   return err;
-}
+

+   return 0;

+}

+

+static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)

+{

+   if (extension_is_supported (extname))

+      if (set_reg8 (ctx, id, name, 0x01))

+         return 1;

+   return 0;

+}

+

+/**

+ * This kicks everything off.

+ *

+ * \param ctx - The GL Context

+ * \param str - The program string

+ * \param len - The program string length

+ * \param Program - The arb_program struct to return all the parsed info in

+ * \return 0 on sucess, 1 on error

+ */

+GLuint

+_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,

+                         struct arb_program * program)

+{

+   GLint a, err, error_pos;

+   char error_msg[300];

+   GLuint parsed_len;

+   struct var_cache *vc_head;

+   grammar arbprogram_syn_id;

+   GLubyte *parsed, *inst;

+   GLubyte *strz = NULL;

+   static int arbprogram_syn_is_ok = 0;		/* XXX temporary */

+

+#if DEBUG_PARSING

+   fprintf (stderr, "Loading grammar text!\n");

+#endif

+

+   /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */

+   if (!arbprogram_syn_is_ok) {

+      grammar grammar_syn_id;

+      GLint err;

+      GLuint parsed_len;

+      byte *parsed;

+

+      grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);

+      if (grammar_syn_id == 0) {

+         grammar_get_last_error ((byte *) error_msg, 300, &error_pos);

+         _mesa_set_program_error (ctx, error_pos, error_msg);

+         _mesa_error (ctx, GL_INVALID_OPERATION,

+                      "Error loading grammar rule set");

+         return 1;

+      }

+

+      err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);

+

+      /* NOTE: we cant destroy grammar_syn_id right here because grammar_destroy() can

+         reset the last error

+      */

+

+      if (err == 0) {

+         grammar_get_last_error ((byte *) error_msg, 300, &error_pos);

+         _mesa_set_program_error (ctx, error_pos, error_msg);

+         _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");

+

+         grammar_destroy (grammar_syn_id);

+         return 1;

+      }

+

+      grammar_destroy (grammar_syn_id);

+

+      arbprogram_syn_is_ok = 1;

+   }

+

+   /* create the grammar object */

+   arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);

+   if (arbprogram_syn_id == 0) {

+      grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);

+      _mesa_set_program_error (ctx, error_pos, error_msg);

+      _mesa_error (ctx, GL_INVALID_OPERATION,

+                   "Error loading grammer rule set");

+      return 1;

+   }

+

+   /* Set program_target register value */

+   if (set_reg8 (ctx, arbprogram_syn_id, (byte *) "program_target",

+      program->Base.Target == GL_FRAGMENT_PROGRAM_ARB ? 0x10 : 0x20)) {

+      grammar_destroy (arbprogram_syn_id);

+      return 1;

+   }

+

+   /* Enable all active extensions */

+   if (enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||

+       enable_ext (ctx, arbprogram_syn_id,

+          (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow")) {

+      grammar_destroy (arbprogram_syn_id);

+      return 1;

+   }

+

+   /* check for NULL character occurences */

+   {

+      int i;

+      for (i = 0; i < len; i++)

+         if (str[i] == '\0') {

+            _mesa_set_program_error (ctx, i, "invalid character");

+            _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");

+

+            grammar_destroy (arbprogram_syn_id);

+            return 1;

+         }

+   }

+

+   /* copy the program string to a null-terminated string */

+   /* XXX should I check for NULL from malloc()? */

+   strz = _mesa_malloc (len + 1);

+   _mesa_memcpy (strz, str, len);

+   strz[len] = '\0';

+

+#if DEBUG_PARSING

+   printf ("Checking Grammar!\n");

+#endif

+   err = grammar_check (arbprogram_syn_id, strz, &parsed, &parsed_len);

+

+   /* Syntax parse error */

+   if (err == 0) {

+      _mesa_free (strz);

+      grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);

+      _mesa_set_program_error (ctx, error_pos, error_msg);

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Parse Error");

+

+      grammar_destroy (arbprogram_syn_id);

+      return 1;

+   }

+

+#if DEBUG_PARSING

+   printf ("Destroying grammer dict [parse retval: %d]\n", err);

+#endif

+   grammar_destroy (arbprogram_syn_id);

+

+   /* Initialize the arb_program struct */

+   program->Base.String = strz;

+   program->Base.NumInstructions =

+   program->Base.NumTemporaries =

+   program->Base.NumParameters =

+   program->Base.NumAttributes = program->Base.NumAddressRegs = 0;

+   program->Parameters = _mesa_new_parameter_list ();

+   program->InputsRead = 0;

+   program->OutputsWritten = 0;

+   program->Position = 0;

+   program->MajorVersion = program->MinorVersion = 0;

+   program->PrecisionOption = GL_DONT_CARE;

+   program->FogOption = GL_NONE;

+   program->HintPositionInvariant = GL_FALSE;

+   for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)

+      program->TexturesUsed[a] = 0;

+   program->NumAluInstructions =

+   program->NumTexInstructions =

+   program->NumTexIndirections = 0;

+

+   program->FPInstructions = NULL;

+   program->VPInstructions = NULL;

+

+   vc_head = NULL;

+   err = 0;

+

+   /* Start examining the tokens in the array */

+   inst = parsed;

+

+   /* Check the grammer rev */

+   if (*inst++ != REVISION) {

+      _mesa_set_program_error (ctx, 0, "Grammar version mismatch");

+      _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar verison mismatch");

+      err = 1;

+   }

+   else {

+      switch (*inst++) {

+         case FRAGMENT_PROGRAM:

+            program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;

+            break;

+

+         case VERTEX_PROGRAM:

+            program->Base.Target = GL_VERTEX_PROGRAM_ARB;

+            break;

+      }

+

+      err = parse_arb_program (ctx, inst, &vc_head, program);

+#if DEBUG_PARSING

+      fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);

+#endif

+   }

+

+   /*debug_variables(ctx, vc_head, program); */

+

+   /* We're done with the parsed binary array */

+   var_cache_destroy (&vc_head);

+

+   _mesa_free (parsed);

+#if DEBUG_PARSING

+   printf ("_mesa_parse_arb_program() done\n");

+#endif

+   return err;

+}