Committing in .
authorJouk Jansen <joukj@hrem.stm.tudelft.nl>
Mon, 5 Apr 2004 08:50:36 +0000 (08:50 +0000)
committerJouk Jansen <joukj@hrem.stm.tudelft.nl>
Mon, 5 Apr 2004 08:50:36 +0000 (08:50 +0000)
 Correction on last commit (My FTP-server on linux is playing games with
<CR>'s)

 Modified Files:
  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
 ----------------------------------------------------------------------

src/mesa/drivers/common/descrip.mms
src/mesa/main/descrip.mms
src/mesa/shader/arbprogparse.c
src/mesa/shader/descrip.mms
src/mesa/swrast/descrip.mms
src/mesa/tnl/descrip.mms

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