Split the program.[ch] files into several new files.
diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c
new file mode 100644
index 0000000..7377c7d
--- /dev/null
+++ b/src/mesa/shader/prog_statevars.c
@@ -0,0 +1,783 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 1999-2006  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.
+ */
+
+/**
+ * \file prog_statevars.c
+ * Program state variable management.
+ * \author Brian Paul
+ */
+
+
+#include "glheader.h"
+#include "context.h"
+#include "hash.h"
+#include "imports.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "prog_statevars.h"
+#include "prog_parameter.h"
+#include "nvvertparse.h"
+
+
+/**
+ * Use the list of tokens in the state[] array to find global GL state
+ * and return it in <value>.  Usually, four values are returned in <value>
+ * but matrix queries may return as many as 16 values.
+ * This function is used for ARB vertex/fragment programs.
+ * The program parser will produce the state[] values.
+ */
+static void
+_mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
+                  GLfloat *value)
+{
+   switch (state[0]) {
+   case STATE_MATERIAL:
+      {
+         /* state[1] is either 0=front or 1=back side */
+         const GLuint face = (GLuint) state[1];
+         const struct gl_material *mat = &ctx->Light.Material;
+         ASSERT(face == 0 || face == 1);
+         /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */
+         ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT);
+         /* XXX we could get rid of this switch entirely with a little
+          * work in arbprogparse.c's parse_state_single_item().
+          */
+         /* state[2] is the material attribute */
+         switch (state[2]) {
+         case STATE_AMBIENT:
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]);
+            return;
+         case STATE_DIFFUSE:
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]);
+            return;
+         case STATE_SPECULAR:
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]);
+            return;
+         case STATE_EMISSION:
+            COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]);
+            return;
+         case STATE_SHININESS:
+            value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0];
+            value[1] = 0.0F;
+            value[2] = 0.0F;
+            value[3] = 1.0F;
+            return;
+         default:
+            _mesa_problem(ctx, "Invalid material state in fetch_state");
+            return;
+         }
+      }
+   case STATE_LIGHT:
+      {
+         /* state[1] is the light number */
+         const GLuint ln = (GLuint) state[1];
+         /* state[2] is the light attribute */
+         switch (state[2]) {
+         case STATE_AMBIENT:
+            COPY_4V(value, ctx->Light.Light[ln].Ambient);
+            return;
+         case STATE_DIFFUSE:
+            COPY_4V(value, ctx->Light.Light[ln].Diffuse);
+            return;
+         case STATE_SPECULAR:
+            COPY_4V(value, ctx->Light.Light[ln].Specular);
+            return;
+         case STATE_POSITION:
+            COPY_4V(value, ctx->Light.Light[ln].EyePosition);
+            return;
+         case STATE_ATTENUATION:
+            value[0] = ctx->Light.Light[ln].ConstantAttenuation;
+            value[1] = ctx->Light.Light[ln].LinearAttenuation;
+            value[2] = ctx->Light.Light[ln].QuadraticAttenuation;
+            value[3] = ctx->Light.Light[ln].SpotExponent;
+            return;
+         case STATE_SPOT_DIRECTION:
+            COPY_3V(value, ctx->Light.Light[ln].EyeDirection);
+            value[3] = ctx->Light.Light[ln]._CosCutoff;
+            return;
+         case STATE_HALF:
+            {
+               GLfloat eye_z[] = {0, 0, 1};
+					
+               /* Compute infinite half angle vector:
+                *   half-vector = light_position + (0, 0, 1) 
+                * and then normalize.  w = 0
+		*
+		* light.EyePosition.w should be 0 for infinite lights.
+                */
+	       ADD_3V(value, eye_z, ctx->Light.Light[ln].EyePosition);
+	       NORMALIZE_3FV(value);
+	       value[3] = 0;
+            }						  
+            return;
+	 case STATE_POSITION_NORMALIZED:
+            COPY_4V(value, ctx->Light.Light[ln].EyePosition);
+	    NORMALIZE_3FV( value );
+            return;
+         default:
+            _mesa_problem(ctx, "Invalid light state in fetch_state");
+            return;
+         }
+      }
+   case STATE_LIGHTMODEL_AMBIENT:
+      COPY_4V(value, ctx->Light.Model.Ambient);
+      return;
+   case STATE_LIGHTMODEL_SCENECOLOR:
+      if (state[1] == 0) {
+         /* front */
+         GLint i;
+         for (i = 0; i < 3; i++) {
+            value[i] = ctx->Light.Model.Ambient[i]
+               * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i]
+               + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i];
+         }
+	 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+      }
+      else {
+         /* back */
+         GLint i;
+         for (i = 0; i < 3; i++) {
+            value[i] = ctx->Light.Model.Ambient[i]
+               * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i]
+               + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i];
+         }
+	 value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+      }
+      return;
+   case STATE_LIGHTPROD:
+      {
+         const GLuint ln = (GLuint) state[1];
+         const GLuint face = (GLuint) state[2];
+         GLint i;
+         ASSERT(face == 0 || face == 1);
+         switch (state[3]) {
+            case STATE_AMBIENT:
+               for (i = 0; i < 3; i++) {
+                  value[i] = ctx->Light.Light[ln].Ambient[i] *
+                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i];
+               }
+               /* [3] = material alpha */
+               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
+               return;
+            case STATE_DIFFUSE:
+               for (i = 0; i < 3; i++) {
+                  value[i] = ctx->Light.Light[ln].Diffuse[i] *
+                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i];
+               }
+               /* [3] = material alpha */
+               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
+               return;
+            case STATE_SPECULAR:
+               for (i = 0; i < 3; i++) {
+                  value[i] = ctx->Light.Light[ln].Specular[i] *
+                     ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i];
+               }
+               /* [3] = material alpha */
+               value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3];
+               return;
+            default:
+               _mesa_problem(ctx, "Invalid lightprod state in fetch_state");
+               return;
+         }
+      }
+   case STATE_TEXGEN:
+      {
+         /* state[1] is the texture unit */
+         const GLuint unit = (GLuint) state[1];
+         /* state[2] is the texgen attribute */
+         switch (state[2]) {
+         case STATE_TEXGEN_EYE_S:
+            COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS);
+            return;
+         case STATE_TEXGEN_EYE_T:
+            COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT);
+            return;
+         case STATE_TEXGEN_EYE_R:
+            COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR);
+            return;
+         case STATE_TEXGEN_EYE_Q:
+            COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ);
+            return;
+         case STATE_TEXGEN_OBJECT_S:
+            COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS);
+            return;
+         case STATE_TEXGEN_OBJECT_T:
+            COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT);
+            return;
+         case STATE_TEXGEN_OBJECT_R:
+            COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR);
+            return;
+         case STATE_TEXGEN_OBJECT_Q:
+            COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ);
+            return;
+         default:
+            _mesa_problem(ctx, "Invalid texgen state in fetch_state");
+            return;
+         }
+      }
+   case STATE_TEXENV_COLOR:
+      {		
+         /* state[1] is the texture unit */
+         const GLuint unit = (GLuint) state[1];
+         COPY_4V(value, ctx->Texture.Unit[unit].EnvColor);
+      }			
+      return;
+   case STATE_FOG_COLOR:
+      COPY_4V(value, ctx->Fog.Color);
+      return;
+   case STATE_FOG_PARAMS:
+      value[0] = ctx->Fog.Density;
+      value[1] = ctx->Fog.Start;
+      value[2] = ctx->Fog.End;
+      value[3] = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+      return;
+   case STATE_CLIPPLANE:
+      {
+         const GLuint plane = (GLuint) state[1];
+         COPY_4V(value, ctx->Transform.EyeUserPlane[plane]);
+      }
+      return;
+   case STATE_POINT_SIZE:
+      value[0] = ctx->Point.Size;
+      value[1] = ctx->Point.MinSize;
+      value[2] = ctx->Point.MaxSize;
+      value[3] = ctx->Point.Threshold;
+      return;
+   case STATE_POINT_ATTENUATION:
+      value[0] = ctx->Point.Params[0];
+      value[1] = ctx->Point.Params[1];
+      value[2] = ctx->Point.Params[2];
+      value[3] = 1.0F;
+      return;
+   case STATE_MATRIX:
+      {
+         /* state[1] = modelview, projection, texture, etc. */
+         /* state[2] = which texture matrix or program matrix */
+         /* state[3] = first row to fetch */
+         /* state[4] = last row to fetch */
+         /* state[5] = transpose, inverse or invtrans */
+
+         const GLmatrix *matrix;
+         const gl_state_index mat = state[1];
+         const GLuint index = (GLuint) state[2];
+         const GLuint firstRow = (GLuint) state[3];
+         const GLuint lastRow = (GLuint) state[4];
+         const gl_state_index modifier = state[5];
+         const GLfloat *m;
+         GLuint row, i;
+         if (mat == STATE_MODELVIEW) {
+            matrix = ctx->ModelviewMatrixStack.Top;
+         }
+         else if (mat == STATE_PROJECTION) {
+            matrix = ctx->ProjectionMatrixStack.Top;
+         }
+         else if (mat == STATE_MVP) {
+            matrix = &ctx->_ModelProjectMatrix;
+         }
+         else if (mat == STATE_TEXTURE) {
+            matrix = ctx->TextureMatrixStack[index].Top;
+         }
+         else if (mat == STATE_PROGRAM) {
+            matrix = ctx->ProgramMatrixStack[index].Top;
+         }
+         else {
+            _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()");
+            return;
+         }
+         if (modifier == STATE_MATRIX_INVERSE ||
+             modifier == STATE_MATRIX_INVTRANS) {
+            /* Be sure inverse is up to date:
+	     */
+            _math_matrix_alloc_inv( (GLmatrix *) matrix );
+	    _math_matrix_analyse( (GLmatrix*) matrix );
+            m = matrix->inv;
+         }
+         else {
+            m = matrix->m;
+         }
+         if (modifier == STATE_MATRIX_TRANSPOSE ||
+             modifier == STATE_MATRIX_INVTRANS) {
+            for (i = 0, row = firstRow; row <= lastRow; row++) {
+               value[i++] = m[row * 4 + 0];
+               value[i++] = m[row * 4 + 1];
+               value[i++] = m[row * 4 + 2];
+               value[i++] = m[row * 4 + 3];
+            }
+         }
+         else {
+            for (i = 0, row = firstRow; row <= lastRow; row++) {
+               value[i++] = m[row + 0];
+               value[i++] = m[row + 4];
+               value[i++] = m[row + 8];
+               value[i++] = m[row + 12];
+            }
+         }
+      }
+      return;
+   case STATE_DEPTH_RANGE:
+      value[0] = ctx->Viewport.Near;                     /* near       */
+      value[1] = ctx->Viewport.Far;                      /* far        */
+      value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */
+      value[3] = 0;
+      return;
+   case STATE_FRAGMENT_PROGRAM:
+      {
+         /* state[1] = {STATE_ENV, STATE_LOCAL} */
+         /* state[2] = parameter index          */
+         const int idx = (int) state[2];
+         switch (state[1]) {
+            case STATE_ENV:
+               COPY_4V(value, ctx->FragmentProgram.Parameters[idx]);
+               break;
+            case STATE_LOCAL:
+               COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]);
+               break;
+            default:
+               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+               return;
+         }
+      }
+      return;
+		
+   case STATE_VERTEX_PROGRAM:
+      {
+         /* state[1] = {STATE_ENV, STATE_LOCAL} */
+         /* state[2] = parameter index          */
+         const int idx = (int) state[2];
+         switch (state[1]) {
+            case STATE_ENV:
+               COPY_4V(value, ctx->VertexProgram.Parameters[idx]);
+               break;
+            case STATE_LOCAL:
+               COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]);
+               break;
+            default:
+               _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()");
+               return;
+         }
+      }
+      return;
+
+   case STATE_INTERNAL:
+      {
+         switch (state[1]) {
+	    case STATE_NORMAL_SCALE:
+               ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1);
+               break;
+	    case STATE_TEXRECT_SCALE: {
+   	       const int unit = (int) state[2];
+	       const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
+	       if (texObj) {
+		  struct gl_texture_image *texImage = texObj->Image[0][0];
+		  ASSIGN_4V(value, 1.0 / texImage->Width, 1.0 / texImage->Height, 0, 1);
+	       }
+               break;
+	    }
+	    default:
+	       /* unknown state indexes are silently ignored
+	       *  should be handled by the driver.
+	       */
+               return;
+         }
+      }
+      return;
+
+   default:
+      _mesa_problem(ctx, "Invalid state in _mesa_fetch_state");
+      return;
+   }
+}
+
+
+/**
+ * Return a bitmask of the Mesa state flags (_NEW_* values) which would
+ * indicate that the given context state may have changed.
+ * The bitmask is used during validation to determine if we need to update
+ * vertex/fragment program parameters (like "state.material.color") when
+ * some GL state has changed.
+ */
+GLbitfield
+_mesa_program_state_flags(const GLint state[])
+{
+   switch (state[0]) {
+   case STATE_MATERIAL:
+   case STATE_LIGHT:
+   case STATE_LIGHTMODEL_AMBIENT:
+   case STATE_LIGHTMODEL_SCENECOLOR:
+   case STATE_LIGHTPROD:
+      return _NEW_LIGHT;
+
+   case STATE_TEXGEN:
+   case STATE_TEXENV_COLOR:
+      return _NEW_TEXTURE;
+
+   case STATE_FOG_COLOR:
+   case STATE_FOG_PARAMS:
+      return _NEW_FOG;
+
+   case STATE_CLIPPLANE:
+      return _NEW_TRANSFORM;
+
+   case STATE_POINT_SIZE:
+   case STATE_POINT_ATTENUATION:
+      return _NEW_POINT;
+
+   case STATE_MATRIX:
+      switch (state[1]) {
+      case STATE_MODELVIEW:
+	 return _NEW_MODELVIEW;
+      case STATE_PROJECTION:
+	 return _NEW_PROJECTION;
+      case STATE_MVP:
+	 return _NEW_MODELVIEW | _NEW_PROJECTION;
+      case STATE_TEXTURE:
+	 return _NEW_TEXTURE_MATRIX;
+      case STATE_PROGRAM:
+	 return _NEW_TRACK_MATRIX;
+      default:
+	 _mesa_problem(NULL,
+                       "unexpected matrix in _mesa_program_state_flags()");
+	 return 0;
+      }
+
+   case STATE_DEPTH_RANGE:
+      return _NEW_VIEWPORT;
+
+   case STATE_FRAGMENT_PROGRAM:
+   case STATE_VERTEX_PROGRAM:
+      return _NEW_PROGRAM;
+
+   case STATE_INTERNAL:
+      switch (state[1]) {
+      case STATE_NORMAL_SCALE:
+	 return _NEW_MODELVIEW;
+      case STATE_TEXRECT_SCALE:
+	 return _NEW_TEXTURE;
+      default:
+         /* unknown state indexes are silently ignored and
+         *  no flag set, since it is handled by the driver.
+         */
+	 return 0;
+      }
+
+   default:
+      _mesa_problem(NULL, "unexpected state[0] in make_state_flags()");
+      return 0;
+   }
+}
+
+
+static void
+append(char *dst, const char *src)
+{
+   while (*dst)
+      dst++;
+   while (*src)
+     *dst++ = *src++;
+   *dst = 0;
+}
+
+
+static void
+append_token(char *dst, gl_state_index k)
+{
+   switch (k) {
+   case STATE_MATERIAL:
+      append(dst, "material.");
+      break;
+   case STATE_LIGHT:
+      append(dst, "light");
+      break;
+   case STATE_LIGHTMODEL_AMBIENT:
+      append(dst, "lightmodel.ambient");
+      break;
+   case STATE_LIGHTMODEL_SCENECOLOR:
+      break;
+   case STATE_LIGHTPROD:
+      append(dst, "lightprod");
+      break;
+   case STATE_TEXGEN:
+      append(dst, "texgen");
+      break;
+   case STATE_FOG_COLOR:
+      append(dst, "fog.color");
+      break;
+   case STATE_FOG_PARAMS:
+      append(dst, "fog.params");
+      break;
+   case STATE_CLIPPLANE:
+      append(dst, "clip");
+      break;
+   case STATE_POINT_SIZE:
+      append(dst, "point.size");
+      break;
+   case STATE_POINT_ATTENUATION:
+      append(dst, "point.attenuation");
+      break;
+   case STATE_MATRIX:
+      append(dst, "matrix.");
+      break;
+   case STATE_MODELVIEW:
+      append(dst, "modelview");
+      break;
+   case STATE_PROJECTION:
+      append(dst, "projection");
+      break;
+   case STATE_MVP:
+      append(dst, "mvp");
+      break;
+   case STATE_TEXTURE:
+      append(dst, "texture");
+      break;
+   case STATE_PROGRAM:
+      append(dst, "program");
+      break;
+   case STATE_MATRIX_INVERSE:
+      append(dst, ".inverse");
+      break;
+   case STATE_MATRIX_TRANSPOSE:
+      append(dst, ".transpose");
+      break;
+   case STATE_MATRIX_INVTRANS:
+      append(dst, ".invtrans");
+      break;
+   case STATE_AMBIENT:
+      append(dst, "ambient");
+      break;
+   case STATE_DIFFUSE:
+      append(dst, "diffuse");
+      break;
+   case STATE_SPECULAR:
+      append(dst, "specular");
+      break;
+   case STATE_EMISSION:
+      append(dst, "emission");
+      break;
+   case STATE_SHININESS:
+      append(dst, "shininess");
+      break;
+   case STATE_HALF:
+      append(dst, "half");
+      break;
+   case STATE_POSITION:
+      append(dst, ".position");
+      break;
+   case STATE_ATTENUATION:
+      append(dst, ".attenuation");
+      break;
+   case STATE_SPOT_DIRECTION:
+      append(dst, ".spot.direction");
+      break;
+   case STATE_TEXGEN_EYE_S:
+      append(dst, "eye.s");
+      break;
+   case STATE_TEXGEN_EYE_T:
+      append(dst, "eye.t");
+      break;
+   case STATE_TEXGEN_EYE_R:
+      append(dst, "eye.r");
+      break;
+   case STATE_TEXGEN_EYE_Q:
+      append(dst, "eye.q");
+      break;
+   case STATE_TEXGEN_OBJECT_S:
+      append(dst, "object.s");
+      break;
+   case STATE_TEXGEN_OBJECT_T:
+      append(dst, "object.t");
+      break;
+   case STATE_TEXGEN_OBJECT_R:
+      append(dst, "object.r");
+      break;
+   case STATE_TEXGEN_OBJECT_Q:
+      append(dst, "object.q");
+      break;
+   case STATE_TEXENV_COLOR:
+      append(dst, "texenv");
+      break;
+   case STATE_DEPTH_RANGE:
+      append(dst, "depth.range");
+      break;
+   case STATE_VERTEX_PROGRAM:
+   case STATE_FRAGMENT_PROGRAM:
+      break;
+   case STATE_ENV:
+      append(dst, "env");
+      break;
+   case STATE_LOCAL:
+      append(dst, "local");
+      break;
+   case STATE_INTERNAL:
+   case STATE_NORMAL_SCALE:
+   case STATE_POSITION_NORMALIZED:
+      append(dst, "(internal)");
+      break;
+   default:
+      ;
+   }
+}
+
+static void
+append_face(char *dst, GLint face)
+{
+   if (face == 0)
+      append(dst, "front.");
+   else
+      append(dst, "back.");
+}
+
+static void
+append_index(char *dst, GLint index)
+{
+   char s[20];
+   _mesa_sprintf(s, "[%d].", index);
+   append(dst, s);
+}
+
+/**
+ * Make a string from the given state vector.
+ * For example, return "state.matrix.texture[2].inverse".
+ * Use _mesa_free() to deallocate the string.
+ */
+const char *
+_mesa_program_state_string(const GLint state[6])
+{
+   char str[1000] = "";
+   char tmp[30];
+
+   append(str, "state.");
+   append_token(str, (gl_state_index) state[0]);
+
+   switch (state[0]) {
+   case STATE_MATERIAL:
+      append_face(str, state[1]);
+      append_token(str, (gl_state_index) state[2]);
+      break;
+   case STATE_LIGHT:
+      append(str, "light");
+      append_index(str, state[1]); /* light number [i]. */
+      append_token(str, (gl_state_index) state[2]); /* coefficients */
+      break;
+   case STATE_LIGHTMODEL_AMBIENT:
+      append(str, "lightmodel.ambient");
+      break;
+   case STATE_LIGHTMODEL_SCENECOLOR:
+      if (state[1] == 0) {
+         append(str, "lightmodel.front.scenecolor");
+      }
+      else {
+         append(str, "lightmodel.back.scenecolor");
+      }
+      break;
+   case STATE_LIGHTPROD:
+      append_index(str, state[1]); /* light number [i]. */
+      append_face(str, state[2]);
+      append_token(str, (gl_state_index) state[3]);
+      break;
+   case STATE_TEXGEN:
+      append_index(str, state[1]); /* tex unit [i] */
+      append_token(str, (gl_state_index) state[2]); /* plane coef */
+      break;
+   case STATE_TEXENV_COLOR:
+      append_index(str, state[1]); /* tex unit [i] */
+      append(str, "color");
+      break;
+   case STATE_FOG_COLOR:
+   case STATE_FOG_PARAMS:
+      break;
+   case STATE_CLIPPLANE:
+      append_index(str, state[1]); /* plane [i] */
+      append(str, "plane");
+      break;
+   case STATE_POINT_SIZE:
+   case STATE_POINT_ATTENUATION:
+      break;
+   case STATE_MATRIX:
+      {
+         /* state[1] = modelview, projection, texture, etc. */
+         /* state[2] = which texture matrix or program matrix */
+         /* state[3] = first row to fetch */
+         /* state[4] = last row to fetch */
+         /* state[5] = transpose, inverse or invtrans */
+         const gl_state_index mat = (gl_state_index) state[1];
+         const GLuint index = (GLuint) state[2];
+         const GLuint firstRow = (GLuint) state[3];
+         const GLuint lastRow = (GLuint) state[4];
+         const gl_state_index modifier = (gl_state_index) state[5];
+         append_token(str, mat);
+         if (index)
+            append_index(str, index);
+         if (modifier)
+            append_token(str, modifier);
+         if (firstRow == lastRow)
+            _mesa_sprintf(tmp, ".row[%d]", firstRow);
+         else
+            _mesa_sprintf(tmp, ".row[%d..%d]", firstRow, lastRow);
+         append(str, tmp);
+      }
+      break;
+   case STATE_DEPTH_RANGE:
+      break;
+   case STATE_FRAGMENT_PROGRAM:
+   case STATE_VERTEX_PROGRAM:
+      /* state[1] = {STATE_ENV, STATE_LOCAL} */
+      /* state[2] = parameter index          */
+      append_token(str, (gl_state_index) state[1]);
+      append_index(str, state[2]);
+      break;
+   case STATE_INTERNAL:
+      break;
+   default:
+      _mesa_problem(NULL, "Invalid state in _mesa_program_state_string");
+      break;
+   }
+
+   return _mesa_strdup(str);
+}
+
+
+/**
+ * Loop over all the parameters in a parameter list.  If the parameter
+ * is a GL state reference, look up the current value of that state
+ * variable and put it into the parameter's Value[4] array.
+ * This would be called at glBegin time when using a fragment program.
+ */
+void
+_mesa_load_state_parameters(GLcontext *ctx,
+                            struct gl_program_parameter_list *paramList)
+{
+   GLuint i;
+
+   if (!paramList)
+      return;
+
+   for (i = 0; i < paramList->NumParameters; i++) {
+      if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) {
+         _mesa_fetch_state(ctx, 
+			   paramList->Parameters[i].StateIndexes,
+                           paramList->ParameterValues[i]);
+      }
+   }
+}
+