diff options
| author | Jouk Jansen <joukj@hrem.stm.tudelft.nl> | 2004-04-05 08:50:36 +0000 | 
|---|---|---|
| committer | Jouk Jansen <joukj@hrem.stm.tudelft.nl> | 2004-04-05 08:50:36 +0000 | 
| commit | 40322e1dfa3366a779ba3f4a6ec4418ab9227715 (patch) | |
| tree | 1d8f57d59d38da61a48ded636bfca6ee095c0d26 /src/mesa | |
| parent | 8cc059ea6474c13bbba4f520ea1a63fd97a32450 (diff) | |
 Committing in .
 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
 ----------------------------------------------------------------------
Diffstat (limited to 'src/mesa')
| -rw-r--r-- | src/mesa/drivers/common/descrip.mms | 74 | ||||
| -rw-r--r-- | src/mesa/main/descrip.mms | 362 | ||||
| -rw-r--r-- | src/mesa/shader/arbprogparse.c | 7906 | ||||
| -rw-r--r-- | src/mesa/shader/descrip.mms | 138 | ||||
| -rw-r--r-- | src/mesa/swrast/descrip.mms | 158 | ||||
| -rw-r--r-- | src/mesa/tnl/descrip.mms | 136 | 
6 files changed, 4387 insertions, 4387 deletions
| diff --git a/src/mesa/drivers/common/descrip.mms b/src/mesa/drivers/common/descrip.mms index eedac1a3a9..aa4b8ae211 100644 --- a/src/mesa/drivers/common/descrip.mms +++ b/src/mesa/drivers/common/descrip.mms @@ -1,37 +1,37 @@ -# 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
 +# 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 diff --git a/src/mesa/main/descrip.mms b/src/mesa/main/descrip.mms index d4fa04fd97..475bed110b 100644 --- a/src/mesa/main/descrip.mms +++ b/src/mesa/main/descrip.mms @@ -1,181 +1,181 @@ -# 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
 +# 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 diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c index 6cbdd39d29..fb311f9f7f 100644 --- a/src/mesa/shader/arbprogparse.c +++ b/src/mesa/shader/arbprogparse.c @@ -1,3953 +1,3953 @@ -/*
 - * 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 (¶m_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;
 -}
 +/* + * 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 (¶m_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; +} diff --git a/src/mesa/shader/descrip.mms b/src/mesa/shader/descrip.mms index 887ffea69a..6f737db47d 100644 --- a/src/mesa/shader/descrip.mms +++ b/src/mesa/shader/descrip.mms @@ -1,69 +1,69 @@ -# 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
 +# 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 diff --git a/src/mesa/swrast/descrip.mms b/src/mesa/swrast/descrip.mms index c36e60d4fb..175f7f8c64 100644 --- a/src/mesa/swrast/descrip.mms +++ b/src/mesa/swrast/descrip.mms @@ -1,79 +1,79 @@ -# 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
 +# 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 diff --git a/src/mesa/tnl/descrip.mms b/src/mesa/tnl/descrip.mms index 9689622874..f5fd1fd57f 100644 --- a/src/mesa/tnl/descrip.mms +++ b/src/mesa/tnl/descrip.mms @@ -1,68 +1,68 @@ -# 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
 +# 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 | 
