Merge commit 'origin/gallium-0.1' into gallium-vertex-linear
[mesa.git] / src / mesa / shader / arbprogparse.c
index 12db64612ee4ffa27d0f1822b9264e26e56c830e..b60b9656c62188a2d580fbee863078590e9e6544 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5
+ * Version:  7.1
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2008  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"),
  * \author Karl Rasche
  */
 
-#include "glheader.h"
-#include "imports.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "shader/grammar/grammar_mesa.h"
 #include "arbprogparse.h"
-#include "grammar_mesa.h"
 #include "program.h"
+#include "programopt.h"
+#include "prog_parameter.h"
+#include "prog_statevars.h"
 #include "context.h"
+#include "macros.h"
 #include "mtypes.h"
-#include "program_instruction.h"
+#include "prog_instruction.h"
 
 
-#define MAX_INSTRUCTIONS 256
+/* For ARB programs, use the NV instruction limits */
+#define MAX_INSTRUCTIONS MAX2(MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS, \
+                              MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS)
 
 
 /**
@@ -51,7 +57,7 @@
  */
 struct arb_program
 {
-   struct program Base;
+   struct gl_program Base;
 
    GLuint Position;       /* Just used for error reporting while parsing */
    GLuint MajorVersion;
@@ -66,6 +72,7 @@ struct arb_program
 
    /* ARB_fragment_program specifics */
    GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS]; 
+   GLbitfield ShadowSamplers;
    GLuint NumAluInstructions; 
    GLuint NumTexInstructions;
    GLuint NumTexIndirections;
@@ -74,12 +81,6 @@ struct arb_program
 };
 
 
-#ifndef __extension__
-#if !defined(__GNUC__) || (__GNUC__ < 2) || \
-    ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 7))
-# define __extension__
-#endif
-#endif
 
 /* TODO:
  *    Fragment Program Stuff:
@@ -165,10 +166,11 @@ struct arb_program
 
 typedef GLubyte *production;
 
+
 /**
  * This is the text describing the rules to parse the grammar
  */
-__extension__ static char arb_grammar_text[] =
+LONGSTRING static char arb_grammar_text[] =
 #include "arbprogram_syn.h"
 ;
 
@@ -181,7 +183,7 @@ __extension__ static char arb_grammar_text[] =
     - changed and merged V_* and F_* opcode values to OP_*.
     - added GL_ARB_fragment_program_shadow specific tokens (michal)
 */
-#define  REVISION                                   0x09
+#define  REVISION                                   0x0a
 
 /* program type */
 #define  FRAGMENT_PROGRAM                           0x01
@@ -209,6 +211,9 @@ __extension__ static char arb_grammar_text[] =
 /* GL_ARB_draw_buffers option */
 #define  ARB_DRAW_BUFFERS                           0x07
 
+/* GL_MESA_texture_array option */
+#define  MESA_TEXTURE_ARRAY                        0x08
+
 /* GL_ARB_fragment_program instruction class */
 #define  OP_ALU_INST                                0x00
 #define  OP_TEX_INST                                0x01
@@ -368,6 +373,11 @@ __extension__ static char arb_grammar_text[] =
 #define  TEXTARGET_SHADOW1D                         0x06
 #define  TEXTARGET_SHADOW2D                         0x07
 #define  TEXTARGET_SHADOWRECT                       0x08
+/* GL_MESA_texture_array */
+#define  TEXTARGET_1D_ARRAY                         0x09
+#define  TEXTARGET_2D_ARRAY                         0x0a
+#define  TEXTARGET_SHADOW1D_ARRAY                   0x0b
+#define  TEXTARGET_SHADOW2D_ARRAY                   0x0c
 
 /* face type */
 #define  FACE_FRONT                                 0x00
@@ -580,7 +590,7 @@ var_cache_append (struct var_cache **va, struct var_cache *nv)
 }
 
 static struct var_cache *
-var_cache_find (struct var_cache *va, GLubyte * name)
+var_cache_find (struct var_cache *va, const GLubyte * name)
 {
    /*struct var_cache *first = va;*/
 
@@ -597,11 +607,74 @@ var_cache_find (struct var_cache *va, GLubyte * name)
    return NULL;
 }
 
+
+
+/**
+ * Called when an error is detected while parsing/compiling a program.
+ * Sets the ctx->Program.ErrorString field to descript and records a
+ * GL_INVALID_OPERATION error.
+ * \param position  position of error in program string
+ * \param descrip  verbose error description
+ */
+static void
+program_error(GLcontext *ctx, GLint position, const char *descrip)
+{
+   if (descrip) {
+      const char *prefix = "glProgramString(", *suffix = ")";
+      char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
+                                        _mesa_strlen(prefix) +
+                                        _mesa_strlen(suffix) + 1);
+      if (str) {
+         _mesa_sprintf(str, "%s%s%s", prefix, descrip, suffix);
+         _mesa_error(ctx, GL_INVALID_OPERATION, str);
+         _mesa_free(str);
+      }
+   }
+   _mesa_set_program_error(ctx, position, descrip);
+}
+
+
+/**
+ * As above, but with an extra string parameter for more info.
+ */
+static void
+program_error2(GLcontext *ctx, GLint position, const char *descrip,
+               const char *var)
+{
+   if (descrip) {
+      const char *prefix = "glProgramString(", *suffix = ")";
+      char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
+                                        _mesa_strlen(": ") +
+                                        _mesa_strlen(var) +
+                                        _mesa_strlen(prefix) +
+                                        _mesa_strlen(suffix) + 1);
+      if (str) {
+         _mesa_sprintf(str, "%s%s: %s%s", prefix, descrip, var, suffix);
+         _mesa_error(ctx, GL_INVALID_OPERATION, str);
+         _mesa_free(str);
+      }
+   }
+   {
+      char *str = (char *) _mesa_malloc(_mesa_strlen(descrip) +
+                                        _mesa_strlen(": ") +
+                                        _mesa_strlen(var) + 1);
+      if (str) {
+         _mesa_sprintf(str, "%s: %s", descrip, var);
+      }
+      _mesa_set_program_error(ctx, position, str);
+      if (str) {
+         _mesa_free(str);
+      }
+   }
+}
+
+
+
 /**
  * constructs an integer from 4 GLubytes in LE format
  */
 static GLuint
-parse_position (GLubyte ** inst)
+parse_position (const GLubyte ** inst)
 {
    GLuint value;
 
@@ -623,10 +696,10 @@ parse_position (GLubyte ** inst)
  * \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,
+parse_string (const GLubyte ** inst, struct var_cache **vc_head,
               struct arb_program *Program, GLuint * found)
 {
-   GLubyte *i = *inst;
+   const GLubyte *i = *inst;
    struct var_cache *va = NULL;
    (void) Program;
 
@@ -649,9 +722,9 @@ parse_string (GLubyte ** inst, struct var_cache **vc_head,
 }
 
 static char *
-parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
+parse_string_without_adding (const GLubyte ** inst, struct arb_program *Program)
 {
-   GLubyte *i = *inst;
+   const GLubyte *i = *inst;
    (void) Program;
    
    *inst += _mesa_strlen ((char *) i) + 1;
@@ -663,7 +736,7 @@ parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
  * \return -1 if we parse '-', return 1 otherwise
  */
 static GLint
-parse_sign (GLubyte ** inst)
+parse_sign (const GLubyte ** inst)
 {
    /*return *(*inst)++ != '+'; */
 
@@ -683,7 +756,7 @@ parse_sign (GLubyte ** inst)
  * parses and returns signed integer
  */
 static GLint
-parse_integer (GLubyte ** inst, struct arb_program *Program)
+parse_integer (const GLubyte ** inst, struct arb_program *Program)
 {
    GLint sign;
    GLint value;
@@ -720,7 +793,7 @@ parse_integer (GLubyte ** inst, struct arb_program *Program)
   in the string.
 */
 static GLdouble
-parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
+parse_float_string(const GLubyte ** inst, struct arb_program *Program, GLdouble *scale)
 {
    GLdouble value = 0.0;
    GLdouble oscale = 1.0;
@@ -753,7 +826,7 @@ parse_float_string(GLubyte ** inst, struct arb_program *Program, GLdouble *scale
      12.34e-4
  */
 static GLfloat
-parse_float (GLubyte ** inst, struct arb_program *Program)
+parse_float (const GLubyte ** inst, struct arb_program *Program)
 {
    GLint exponent;
    GLdouble whole, fraction, fracScale = 1.0;
@@ -773,7 +846,7 @@ parse_float (GLubyte ** inst, struct arb_program *Program)
 /**
  */
 static GLfloat
-parse_signed_float (GLubyte ** inst, struct arb_program *Program)
+parse_signed_float (const GLubyte ** inst, struct arb_program *Program)
 {
    GLint sign = parse_sign (inst);
    GLfloat value = parse_float (inst, Program);
@@ -787,7 +860,7 @@ parse_signed_float (GLubyte ** inst, struct arb_program *Program)
  * \param values - The 4 component vector with the constant value in it
  */
 static GLvoid
-parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
+parse_constant (const GLubyte ** inst, GLfloat *values, struct arb_program *Program,
                 GLboolean use)
 {
    GLuint components, i;
@@ -825,8 +898,8 @@ parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Program,
-                        GLint *offset)
+parse_relative_offset(GLcontext *ctx, const GLubyte **inst,
+                      struct arb_program *Program, GLint *offset)
 {
    (void) ctx;
    *offset = parse_integer(inst, Program);
@@ -838,7 +911,7 @@ parse_relative_offset (GLcontext *ctx, GLubyte **inst, struct arb_program *Progr
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
+parse_color_type (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
                   GLint * color)
 {
    (void) ctx; (void) Program;
@@ -852,17 +925,15 @@ parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
+parse_generic_attrib_num(GLcontext *ctx, const GLubyte ** inst,
                        struct arb_program *Program, GLuint *attrib)
 {
    GLint i = parse_integer(inst, Program);
 
    if ((i < 0) || (i >= 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");
-
+      program_error(ctx, Program->Position,
+                    "Invalid generic vertex attribute index");
       return 1;
    }
 
@@ -877,15 +948,13 @@ parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_output_color_num (GLcontext * ctx, GLubyte ** inst,
+parse_output_color_num (GLcontext * ctx, const GLubyte ** inst,
                     struct arb_program *Program, GLuint * color)
 {
    GLint i = parse_integer (inst, Program);
 
    if ((i < 0) || (i >= (int)ctx->Const.MaxDrawBuffers)) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Invalid draw buffer index");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid draw buffer index");
+      program_error(ctx, Program->Position, "Invalid draw buffer index");
       return 1;
    }
 
@@ -899,15 +968,13 @@ parse_output_color_num (GLcontext * ctx, GLubyte ** inst,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
+parse_texcoord_num (GLcontext * ctx, const GLubyte ** inst,
                     struct arb_program *Program, GLuint * coord)
 {
    GLint i = parse_integer (inst, Program);
 
    if ((i < 0) || (i >= (int)ctx->Const.MaxTextureUnits)) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Invalid texture unit index");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
+      program_error(ctx, Program->Position, "Invalid texture unit index");
       return 1;
    }
 
@@ -920,15 +987,13 @@ parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
+parse_weight_num (GLcontext * ctx, const 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");
+      program_error(ctx, Program->Position, "Invalid weight index");
       return 1;
    }
 
@@ -940,15 +1005,13 @@ parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
+parse_clipplane_num (GLcontext * ctx, const 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");
+      program_error(ctx, Program->Position, "Invalid clip plane index");
       return 1;
    }
 
@@ -960,7 +1023,7 @@ parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
  * \return 0 on front face, 1 on back face
  */
 static GLuint
-parse_face_type (GLubyte ** inst)
+parse_face_type (const GLubyte ** inst)
 {
    switch (*(*inst)++) {
       case FACE_FRONT:
@@ -983,7 +1046,7 @@ parse_face_type (GLubyte ** inst)
  * \return 0 on sucess, 1 on failure
  */
 static GLuint
-parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
+parse_matrix (GLcontext * ctx, const GLubyte ** inst, struct arb_program *Program,
               GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
 {
    GLubyte mat = *(*inst)++;
@@ -992,33 +1055,29 @@ parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
 
    switch (mat) {
       case MATRIX_MODELVIEW:
-         *matrix = STATE_MODELVIEW;
+         *matrix = STATE_MODELVIEW_MATRIX;
          *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");
+            program_error(ctx, Program->Position,
+                          "ARB_vertex_blend not supported");
             return 1;
          }
          break;
 
       case MATRIX_PROJECTION:
-         *matrix = STATE_PROJECTION;
+         *matrix = STATE_PROJECTION_MATRIX;
          break;
 
       case MATRIX_MVP:
-         *matrix = STATE_MVP;
+         *matrix = STATE_MVP_MATRIX;
          break;
 
       case MATRIX_TEXTURE:
-         *matrix = STATE_TEXTURE;
+         *matrix = STATE_TEXTURE_MATRIX;
          *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);
+            program_error(ctx, Program->Position, "Invalid Texture Unit");
+            /* bad *matrix_id */
             return 1;
          }
          break;
@@ -1026,21 +1085,17 @@ parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
          /* 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");
+         program_error(ctx, Program->Position,
+                       "ARB_matrix_palette not supported");
          return 1;
          break;
 
       case MATRIX_PROGRAM:
-         *matrix = STATE_PROGRAM;
+         *matrix = STATE_PROGRAM_MATRIX;
          *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);
+            program_error(ctx, Program->Position, "Invalid Program Matrix");
+            /* bad *matrix_idx */
             return 1;
          }
          break;
@@ -1074,8 +1129,9 @@ parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
  * \return             - 0 on sucess, 1 on error
  */
 static GLuint
-parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
-                         struct arb_program *Program, GLint * state_tokens)
+parse_state_single_item (GLcontext * ctx, const GLubyte ** inst,
+                         struct arb_program *Program,
+                         gl_state_index state_tokens[STATE_LENGTH])
 {
    switch (*(*inst)++) {
       case STATE_MATERIAL_PARSER:
@@ -1106,10 +1162,8 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
 
          /* 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]);
+            program_error(ctx, Program->Position, "Invalid Light Number");
+            /* bad state_tokens[1] */
             return 1;
          }
 
@@ -1130,7 +1184,7 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
                state_tokens[2] = STATE_ATTENUATION;
                break;
             case LIGHT_HALF:
-               state_tokens[2] = STATE_HALF;
+               state_tokens[2] = STATE_HALF_VECTOR;
                break;
             case LIGHT_SPOT_DIRECTION:
                state_tokens[2] = STATE_SPOT_DIRECTION;
@@ -1156,10 +1210,8 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
 
          /* 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]);
+            program_error(ctx, Program->Position, "Invalid Light Number");
+            /* bad state_tokens[1] */
             return 1;
          }
 
@@ -1210,10 +1262,10 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
            state_tokens[1] = coord;
 
             /* EYE or OBJECT */
-            type = *(*inst++);
+            type = *(*inst)++;
 
             /* 0 - s, 1 - t, 2 - r, 3 - q */
-            coord = *(*inst++);
+            coord = *(*inst)++;
 
             if (type == TEX_GEN_EYE) {
                switch (coord) {
@@ -1229,6 +1281,9 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
                   case COMPONENT_W:
                      state_tokens[2] = STATE_TEXGEN_EYE_Q;
                      break;
+                  default:
+                     _mesa_problem(ctx, "bad texgen component in "
+                                   "parse_state_single_item()");
                }
             }
             else {
@@ -1245,6 +1300,9 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
                   case COMPONENT_W:
                      state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
                      break;
+                  default:
+                     _mesa_problem(ctx, "bad texgen component in "
+                                   "parse_state_single_item()");
                }
             }
          }
@@ -1261,12 +1319,13 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
       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]))
+         if (parse_clipplane_num (ctx, inst, Program,
+                                  (GLint *) &state_tokens[1]))
             return 1;
          break;
 
       case STATE_POINT:
-         switch (*(*inst++)) {
+         switch (*(*inst)++) {
             case POINT_SIZE:
                state_tokens[0] = STATE_POINT_SIZE;
                break;
@@ -1279,27 +1338,25 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
 
          /* 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]))
+         if (parse_matrix(ctx, inst, Program,
+                          (GLint *) &state_tokens[0],
+                          (GLint *) &state_tokens[1],
+                          (GLint *) &state_tokens[4]))
             return 1;
 
-         state_tokens[3] = parse_integer (inst, Program);       /* The first row to grab */
+         state_tokens[2] = 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]);
+            state_tokens[3] = parse_integer (inst, Program);
+            if (state_tokens[3] < state_tokens[2]) {
+               program_error(ctx, Program->Position,
+                             "Second matrix index less than the first");
+               /* state_tokens[4] vs. state_tokens[3] */
                return 1;
             }
          }
          else {
-            state_tokens[4] = state_tokens[3];
+            state_tokens[3] = state_tokens[2];
             (*inst)++;
          }
          break;
@@ -1339,8 +1396,9 @@ parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
  * \return             - 0 on sucess, 1 on failure
  */
 static GLuint
-parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
-                           struct arb_program *Program, GLint * state_tokens)
+parse_program_single_item (GLcontext * ctx, const GLubyte ** inst,
+                           struct arb_program *Program,
+                           gl_state_index state_tokens[STATE_LENGTH])
 {
    if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
       state_tokens[0] = STATE_FRAGMENT_PROGRAM;
@@ -1359,11 +1417,9 @@ parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
              ||
              ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
               (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxEnvParams))) {
-            _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]);
+            program_error(ctx, Program->Position,
+                          "Invalid Program Env Parameter");
+            /* bad state_tokens[2] */
             return 1;
          }
 
@@ -1379,11 +1435,9 @@ parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
              ||
              ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) &&
               (state_tokens[2] >= (GLint) ctx->Const.VertexProgram.MaxLocalParams))) {
-            _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]);
+            program_error(ctx, Program->Position,
+                          "Invalid Program Local Parameter");
+            /* bad state_tokens[2] */
             return 1;
          }
          break;
@@ -1439,10 +1493,10 @@ generic_attrib_check(struct var_cache *vc_head)
  *
  * \param inputReg  returns the input register index, one of the
  *                  VERT_ATTRIB_* or FRAG_ATTRIB_* values.
- * \return returns 0 on sucess, 1 on error
+ * \return returns 0 on success, 1 on error
  */
 static GLuint
-parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
+parse_attrib_binding(GLcontext * ctx, const GLubyte ** inst,
                      struct arb_program *Program,
                      GLuint *inputReg, GLuint *is_generic)
 {
@@ -1461,7 +1515,7 @@ parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
             break;
          case FRAGMENT_ATTRIB_TEXCOORD:
             {
-               GLuint texcoord;
+               GLuint texcoord = 0;
                err = parse_texcoord_num (ctx, inst, Program, &texcoord);
                *inputReg = FRAG_ATTRIB_TEX0 + texcoord;
             }
@@ -1485,14 +1539,19 @@ parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
 
          case VERTEX_ATTRIB_WEIGHT:
             {
-               const char *msg = "ARB_vertex_blend not supported";
                GLint weight;
                err = parse_weight_num (ctx, inst, Program, &weight);
                *inputReg = VERT_ATTRIB_WEIGHT;
-               _mesa_set_program_error(ctx, Program->Position, msg);
-               _mesa_error(ctx, GL_INVALID_OPERATION, msg);
+#if 1
+               /* hack for Warcraft (see bug 8060) */
+               _mesa_warning(ctx, "Application error: vertex program uses 'vertex.weight' but GL_ARB_vertex_blend not supported.");
+               break;
+#else
+               program_error(ctx, Program->Position,
+                             "ARB_vertex_blend not supported");
+               return 1;
+#endif
             }
-            return 1;
 
          case VERTEX_ATTRIB_NORMAL:
             *inputReg = VERT_ATTRIB_NORMAL;
@@ -1517,7 +1576,7 @@ parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
 
          case VERTEX_ATTRIB_TEXCOORD:
             {
-               GLuint unit;
+               GLuint unit = 0;
                err = parse_texcoord_num (ctx, inst, Program, &unit);
                *inputReg = VERT_ATTRIB_TEX0 + unit;
             }
@@ -1528,18 +1587,15 @@ parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
             {
                const char *msg = "ARB_palette_matrix not supported";
                parse_integer (inst, Program);
-               _mesa_set_program_error (ctx, Program->Position, msg);
-               _mesa_error (ctx, GL_INVALID_OPERATION, msg);
+               program_error(ctx, Program->Position, msg);
             }
             return 1;
 
          case VERTEX_ATTRIB_GENERIC:
             {
                GLuint attrib;
-
                err = parse_generic_attrib_num(ctx, inst, Program, &attrib);
-
-                          if (!err) {
+               if (!err) {
                   *is_generic = 1;
                   /* Add VERT_ATTRIB_GENERIC0 here because ARB_vertex_program's
                    * attributes do not alias the conventional vertex
@@ -1560,13 +1616,9 @@ parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
    }
 
    if (err) {
-      const char *msg = "Bad attribute binding";
-      _mesa_set_program_error(ctx, Program->Position, msg);
-      _mesa_error(ctx, GL_INVALID_OPERATION, msg);
+      program_error(ctx, Program->Position, "Bad attribute binding");
    }
 
-   Program->Base.InputsRead |= (1 << *inputReg);
-
    return err;
 }
 
@@ -1580,7 +1632,7 @@ parse_attrib_binding(GLcontext * ctx, GLubyte ** inst,
  *                   one of the VERT_RESULT_* or FRAG_RESULT_* values.
  */
 static GLuint
-parse_result_binding(GLcontext *ctx, GLubyte **inst,
+parse_result_binding(GLcontext *ctx, const GLubyte **inst,
                      GLuint *outputReg, struct arb_program *Program)
 {
    const GLubyte token = *(*inst)++;
@@ -1671,25 +1723,18 @@ parse_result_binding(GLcontext *ctx, GLubyte **inst,
  * \return 0 on sucess, 1 on error
  */
 static GLint
-parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_attrib (GLcontext * ctx, const 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);
+      program_error2(ctx, Program->Position,
+                     "Duplicate variable declaration",
+                     (char *) attrib_var->name);
       return 1;
    }
 
@@ -1700,12 +1745,9 @@ parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
       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");
+      program_error(ctx, Program->Position,
+                    "Cannot use both a generic vertex attribute "
+                    "and a specific attribute of the same type");
       return 1;
    }
 
@@ -1719,13 +1761,13 @@ parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
  *               if we get a signed or unsigned float for scalar constants
  */
 static GLuint
-parse_param_elements (GLcontext * ctx, GLubyte ** inst,
+parse_param_elements (GLcontext * ctx, const GLubyte ** inst,
                       struct var_cache *param_var,
                       struct arb_program *Program, GLboolean use)
 {
    GLint idx;
    GLuint err = 0;
-   GLint state_tokens[6];
+   gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
    GLfloat const_values[4];
 
    switch (*(*inst)++) {
@@ -1736,14 +1778,18 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst,
          /* 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])) {
+         if ((state_tokens[0] == STATE_MODELVIEW_MATRIX ||
+              state_tokens[0] == STATE_PROJECTION_MATRIX ||
+              state_tokens[0] == STATE_MVP_MATRIX ||
+              state_tokens[0] == STATE_TEXTURE_MATRIX ||
+              state_tokens[0] == STATE_PROGRAM_MATRIX)
+             && (state_tokens[2] != state_tokens[3])) {
             GLint row;
-            GLint first_row = state_tokens[3];
-            GLint last_row = state_tokens[4];
+            const GLint first_row = state_tokens[2];
+            const GLint last_row = state_tokens[3];
 
             for (row = first_row; row <= last_row; row++) {
-               state_tokens[3] = state_tokens[4] = row;
+               state_tokens[2] = state_tokens[3] = row;
 
                idx = _mesa_add_state_reference(Program->Base.Parameters,
                                                state_tokens);
@@ -1796,10 +1842,8 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst,
                   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);
+               program_error(ctx, Program->Position,
+                             "Invalid Program Parameter"); /*end_idx*/
                return 1;
             }
 
@@ -1817,21 +1861,21 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst,
          break;
 
       case PARAM_CONSTANT:
+         /* parsing something like {1.0, 2.0, 3.0, 4.0} */
          parse_constant (inst, const_values, Program, use);
          idx = _mesa_add_named_constant(Program->Base.Parameters,
                                         (char *) param_var->name,
-                                        const_values);
+                                        const_values, 4);
          if (param_var->param_binding_begin == ~0U)
             param_var->param_binding_begin = idx;
+         param_var->param_binding_type = PROGRAM_CONSTANT;
          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()");
+         program_error(ctx, Program->Position,
+                       "Unexpected token (in parse_param_elements())");
          return 1;
    }
 
@@ -1842,9 +1886,7 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst,
        || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
            && (Program->Base.NumParameters >=
                ctx->Const.FragmentProgram.MaxLocalParams))) {
-      _mesa_set_program_error (ctx, Program->Position,
-                               "Too many parameter variables");
-      _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
+      program_error(ctx, Program->Position, "Too many parameter variables");
       return 1;
    }
 
@@ -1860,7 +1902,7 @@ parse_param_elements (GLcontext * ctx, GLubyte ** inst,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_param (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
              struct arb_program *Program)
 {
    GLuint found, err;
@@ -1872,25 +1914,16 @@ parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
    Program->Position = parse_position (inst);
 
    if (found) {
-      char *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);
+      program_error2(ctx, Program->Position,
+                     "Duplicate variable declaration",
+                     (char *) param_var->name);
       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);
+      program_error(ctx, Program->Position, "Negative parameter array length");
       return 1;
    }
 
@@ -1918,10 +1951,8 @@ parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
    /* Test array length here! */
    if (specified_length) {
       if (specified_length != (int)param_var->param_binding_length) {
-         const char *msg
-            = "Declared parameter array length does not match parameter list";
-         _mesa_set_program_error(ctx, Program->Position, msg);
-         _mesa_error(ctx, GL_INVALID_OPERATION, msg);
+         program_error(ctx, Program->Position,
+              "Declared parameter array length does not match parameter list");
       }
    }
 
@@ -1934,7 +1965,7 @@ parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
  *
  */
 static GLuint
-parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_param_use (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
                  struct arb_program *Program, struct var_cache **new_var)
 {
    struct var_cache *param_var;
@@ -1970,7 +2001,7 @@ parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_temp (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
             struct arb_program *Program)
 {
    GLuint found;
@@ -1980,15 +2011,9 @@ parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
       temp_var = parse_string (inst, vc_head, Program, &found);
       Program->Position = parse_position (inst);
       if (found) {
-         char *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);
+         program_error2(ctx, Program->Position,
+                        "Duplicate variable declaration",
+                        (char *) temp_var->name);
          return 1;
       }
 
@@ -2000,10 +2025,8 @@ parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
           || ((Program->Base.Target == GL_VERTEX_PROGRAM_ARB)
               && (Program->Base.NumTemporaries >=
                   ctx->Const.VertexProgram.MaxTemps))) {
-         _mesa_set_program_error (ctx, Program->Position,
-                                  "Too many TEMP variables declared");
-         _mesa_error (ctx, GL_INVALID_OPERATION,
-                      "Too many TEMP variables declared");
+         program_error(ctx, Program->Position,
+                       "Too many TEMP variables declared");
          return 1;
       }
 
@@ -2021,7 +2044,7 @@ parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_output (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
               struct arb_program *Program)
 {
    GLuint found;
@@ -2031,15 +2054,9 @@ parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
    output_var = parse_string (inst, vc_head, Program, &found);
    Program->Position = parse_position (inst);
    if (found) {
-      char *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);
+      program_error2(ctx, Program->Position,
+                     "Duplicate variable declaration",
+                     (char *) output_var->name);
       return 1;
    }
 
@@ -2055,7 +2072,7 @@ parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_alias (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
              struct arb_program *Program)
 {
    GLuint found;
@@ -2065,15 +2082,9 @@ parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
    Program->Position = parse_position (inst);
 
    if (found) {
-      char *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);
+      program_error2(ctx, Program->Position,
+                    "Duplicate variable declaration",
+                     (char *) temp_var->name);
       return 1;
    }
 
@@ -2083,15 +2094,9 @@ parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
 
    if (!found)
    {
-      char *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);
+      program_error2(ctx, Program->Position,
+                     "Undefined alias value",
+                     (char *) temp_var->alias_binding->name);
       return 1;
    }
 
@@ -2104,7 +2109,7 @@ parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_address (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
                struct arb_program *Program)
 {
    GLuint found;
@@ -2114,15 +2119,9 @@ parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
       temp_var = parse_string (inst, vc_head, Program, &found);
       Program->Position = parse_position (inst);
       if (found) {
-         char *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);
+         program_error2(ctx, Program->Position,
+                        "Duplicate variable declaration",
+                        (char *) temp_var->name);
          return 1;
       }
 
@@ -2131,9 +2130,7 @@ parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
       if (Program->Base.NumAddressRegs >=
           ctx->Const.VertexProgram.MaxAddressRegs) {
          const char *msg = "Too many ADDRESS variables declared";
-         _mesa_set_program_error(ctx, Program->Position, msg);
-                                  
-         _mesa_error(ctx, GL_INVALID_OPERATION, msg);
+         program_error(ctx, Program->Position, msg);
          return 1;
       }
 
@@ -2151,7 +2148,7 @@ parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
  * \return 0 on sucess, 1 on error
  */
 static GLint
-parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_declaration (GLcontext * ctx, const GLubyte ** inst, struct var_cache **vc_head,
                    struct arb_program *Program)
 {
    GLint err = 0;
@@ -2200,7 +2197,7 @@ parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
+parse_masked_dst_reg (GLcontext * ctx, const GLubyte ** inst,
                       struct var_cache **vc_head, struct arb_program *Program,
                       enum register_file *File, GLuint *Index, GLint *WriteMask)
 {
@@ -2223,10 +2220,7 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** 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);
+            program_error(ctx, Program->Position, "0: Undefined variable");
             return 1;
          }
 
@@ -2243,20 +2237,15 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
 
                /* 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);
+               program_error(ctx, Program->Position,
+                             "Destination register is read only");
                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()");
+         program_error(ctx, Program->Position,
+                       "Unexpected opcode in parse_masked_dst_reg()");
          return 1;
    }
 
@@ -2268,9 +2257,7 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
    */
    /*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,
+      program_error(ctx, Program->Position,
                   "Vertex program specified position invariance and wrote vertex position");
    }*/
 
@@ -2300,7 +2287,7 @@ parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_address_reg (GLcontext * ctx, GLubyte ** inst,
+parse_address_reg (GLcontext * ctx, const GLubyte ** inst,
                           struct var_cache **vc_head,
                           struct arb_program *Program, GLint * Index)
 {
@@ -2314,17 +2301,12 @@ parse_address_reg (GLcontext * ctx, GLubyte ** 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);
+      program_error(ctx, Program->Position, "Undefined variable");
       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);
+      program_error(ctx, Program->Position, "Variable is not of type ADDRESS");
       return 1;
    }
 
@@ -2341,7 +2323,7 @@ parse_address_reg (GLcontext * ctx, GLubyte ** inst,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
+parse_masked_address_reg (GLcontext * ctx, const GLubyte ** inst,
                           struct var_cache **vc_head,
                           struct arb_program *Program, GLint * Index,
                           GLboolean * WriteMask)
@@ -2369,7 +2351,7 @@ parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
  * swizzle, or just 1 component for a scalar src register selection
  */
 static void
-parse_swizzle_mask(GLubyte ** inst, GLubyte *swizzle, GLint len)
+parse_swizzle_mask(const GLubyte ** inst, GLubyte *swizzle, GLint len)
 {
    GLint i;
 
@@ -2405,7 +2387,7 @@ parse_swizzle_mask(GLubyte ** inst, GLubyte *swizzle, GLint len)
  * \return negateMask  four element bitfield
  */
 static void
-parse_extended_swizzle_mask(GLubyte **inst, GLubyte swizzle[4],
+parse_extended_swizzle_mask(const GLubyte **inst, GLubyte swizzle[4],
                             GLubyte *negateMask)
 {
    GLint i;
@@ -2446,7 +2428,8 @@ parse_extended_swizzle_mask(GLubyte **inst, GLubyte swizzle[4],
 
 
 static GLuint
-parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
+parse_src_reg (GLcontext * ctx, const GLubyte ** inst,
+               struct var_cache **vc_head,
                struct arb_program *Program,
                enum register_file * File, GLint * Index,
                GLboolean *IsRelOffset )
@@ -2476,10 +2459,9 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
          src->attrib_is_generic = is_generic;
          var_cache_append(vc_head, src);
          if (generic_attrib_check(*vc_head)) {
-            const char *msg = "Cannot use both a generic vertex attribute "
-               "and a specific attribute of the same type";
-            _mesa_set_program_error (ctx, Program->Position, msg);
-            _mesa_error (ctx, GL_INVALID_OPERATION, msg);
+            program_error(ctx, Program->Position,
+                          "Cannot use both a generic vertex attribute "
+                          "and a specific attribute of the same type");
             return 1;
          }
          break;
@@ -2492,10 +2474,9 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
                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);
+                  program_error2(ctx, Program->Position,
+                                 "Undefined variable",
+                                 (char *) src->name);
                   return 1;
                }
 
@@ -2507,11 +2488,9 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
 
                      if ((offset < 0)
                          || (offset >= (int)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);
+                        program_error(ctx, Program->Position,
+                                      "Index out of range");
+                        /* offset, src->name */
                         return 1;
                      }
 
@@ -2559,10 +2538,8 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
 
          /* 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);
+            program_error(ctx, Program->Position,
+                          "3: Undefined variable"); /* src->name */
             return 1;
          }
 
@@ -2585,43 +2562,45 @@ parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
 
                /* 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);
+               program_error(ctx, Program->Position,
+                             "destination register is read only");
+               /* bad 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");
+         program_error(ctx, Program->Position,
+                       "Unknown token in parse_src_reg");
          return 1;
    }
 
+   /* Add attributes to InputsRead only if they are used the program.
+    * This avoids the handling of unused ATTRIB declarations in the drivers. */
+   if (*File == PROGRAM_INPUT)
+      Program->Base.InputsRead |= (1 << *Index);
+
    return 0;
 }
 
+
 /**
- * Parse fragment program vector source register.
+ * Parse vertex/fragment program vector source register.
  */
 static GLuint
-parse_fp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
-                        struct var_cache **vc_head,
-                        struct arb_program *program,
-                        struct prog_src_register *reg)
+parse_vector_src_reg(GLcontext *ctx, const GLubyte **inst,
+                     struct var_cache **vc_head,
+                     struct arb_program *program,
+                     struct prog_src_register *reg)
 {
    enum register_file file;
    GLint index;
-   GLboolean negate;
+   GLubyte negateMask;
    GLubyte swizzle[4];
    GLboolean isRelOffset;
 
    /* Grab the sign */
-   negate = (parse_sign (inst) == -1) ? 0xf : 0x0;
+   negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
 
    /* And the src reg */
    if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
@@ -2632,67 +2611,66 @@ parse_fp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
 
    reg->File = file;
    reg->Index = index;
-   reg->Abs = 0;               /* NV only */
-   reg->NegateAbs = 0;         /* NV only */
-   reg->NegateBase = negate;
    reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
+   reg->NegateBase = negateMask;
+   reg->RelAddr = isRelOffset;
    return 0;
 }
 
 
-static GLuint 
-parse_fp_dst_reg(GLcontext * ctx, GLubyte ** inst,
-                struct var_cache **vc_head, struct arb_program *Program,
-                struct prog_dst_register *reg )
+/**
+ * Parse vertex/fragment program scalar source register.
+ */
+static GLuint
+parse_scalar_src_reg(GLcontext *ctx, const GLubyte **inst,
+                     struct var_cache **vc_head,
+                     struct arb_program *program,
+                     struct prog_src_register *reg)
 {
-   GLint mask;
-   GLuint idx;
    enum register_file file;
+   GLint index;
+   GLubyte negateMask;
+   GLubyte swizzle[4];
+   GLboolean isRelOffset;
 
-   if (parse_masked_dst_reg (ctx, inst, vc_head, Program, &file, &idx, &mask))
+   /* Grab the sign */
+   negateMask = (parse_sign (inst) == -1) ? NEGATE_XYZW : NEGATE_NONE;
+
+   /* And the src reg */
+   if (parse_src_reg(ctx, inst, vc_head, program, &file, &index, &isRelOffset))
       return 1;
 
-   reg->CondMask = 0;          /* NV only */
-   reg->CondSwizzle = 0;       /* NV only */
+   /* finally, the swizzle */
+   parse_swizzle_mask(inst, swizzle, 1);
+
    reg->File = file;
-   reg->Index = idx;
-   reg->WriteMask = mask;
+   reg->Index = index;
+   reg->Swizzle = (swizzle[0] << 0);
+   reg->NegateBase = negateMask;
+   reg->RelAddr = isRelOffset;
    return 0;
 }
 
 
 /**
- * Parse fragment program scalar src register.
+ * Parse vertex/fragment program destination register.
+ * \return 1 if error, 0 if no error.
  */
-static GLuint
-parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
-                        struct var_cache **vc_head,
-                         struct arb_program *Program,
-                        struct prog_src_register *reg )
+static GLuint 
+parse_dst_reg(GLcontext * ctx, const GLubyte ** inst,
+              struct var_cache **vc_head, struct arb_program *program,
+              struct prog_dst_register *reg )
 {
-   enum register_file File;
-   GLint Index;
-   GLubyte Negate;
-   GLubyte Swizzle[4];
-   GLboolean IsRelOffset;
-
-   /* Grab the sign */
-   Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
+   GLint mask;
+   GLuint idx;
+   enum register_file file;
 
-   /* And the src reg */
-   if (parse_src_reg (ctx, inst, vc_head, Program, &File, &Index, &IsRelOffset))
+   if (parse_masked_dst_reg (ctx, inst, vc_head, program, &file, &idx, &mask))
       return 1;
 
-   /* finally, the swizzle */
-   parse_swizzle_mask(inst, Swizzle, 1);
-
-   reg->File = File;
-   reg->Index = Index;
-   reg->Abs = 0;               /* NV only */
-   reg->NegateAbs = 0;         /* NV only */
-   reg->NegateBase = Negate;
-   reg->Swizzle = (Swizzle[0] << 0);
-
+   reg->File = file;
+   reg->Index = idx;
+   reg->WriteMask = mask;
    return 0;
 }
 
@@ -2700,9 +2678,10 @@ parse_fp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
 /**
  * This is a big mother that handles getting opcodes into the instruction
  * and handling the src & dst registers for fragment program instructions
+ * \return 1 if error, 0 if no error
  */
 static GLuint
-parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
+parse_fp_instruction (GLcontext * ctx, const GLubyte ** inst,
                       struct var_cache **vc_head, struct arb_program *Program,
                       struct prog_instruction *fp)
 {
@@ -2710,8 +2689,9 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
    GLuint texcoord;
    GLubyte instClass, type, code;
    GLboolean rel;
+   GLuint shadow_tex = 0;
 
-   _mesa_init_instruction(fp);
+   _mesa_init_instructions(fp, 1);
 
    /* Record the position in the program string for debugging */
    fp->StringPos = Program->Position;
@@ -2771,10 +2751,10 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
                break;
          }
 
-         if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
+         if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
             return 1;
 
-         if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
+         if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
             return 1;
          break;
 
@@ -2824,10 +2804,10 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
                break;
          }
 
-         if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
+         if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
             return 1;
 
-         if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
+         if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
             return 1;
          break;
 
@@ -2840,11 +2820,11 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
                break;
          }
 
-         if (parse_fp_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
+         if (parse_dst_reg(ctx, inst, vc_head, Program, &fp->DstReg))
             return 1;
 
          for (a = 0; a < 2; a++) {
-           if (parse_fp_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
+           if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
                return 1;
          }
          break;
@@ -2925,10 +2905,10 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
                break;
          }
 
-         if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
+         if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
             return 1;
          for (a = 0; a < 2; a++) {
-           if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
+           if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
               return 1;
          }
          break;
@@ -2954,11 +2934,11 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
                break;
          }
 
-         if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
+         if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
             return 1;
 
          for (a = 0; a < 3; a++) {
-           if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
+           if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[a]))
               return 1;
          }
          break;
@@ -2971,7 +2951,7 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
                fp->Opcode = OPCODE_SWZ;
                break;
          }
-         if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
+         if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
             return 1;
 
         {
@@ -3014,10 +2994,10 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
                break;
          }
 
-         if (parse_fp_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
+         if (parse_dst_reg (ctx, inst, vc_head, Program, &fp->DstReg))
             return 1;
 
-        if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
+        if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
             return 1;
 
          /* texImageUnit */
@@ -3027,58 +3007,80 @@ parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
 
          /* texTarget */
          switch (*(*inst)++) {
+            case TEXTARGET_SHADOW1D:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
             case TEXTARGET_1D:
                fp->TexSrcTarget = TEXTURE_1D_INDEX;
                break;
+            case TEXTARGET_SHADOW2D:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
             case TEXTARGET_2D:
                fp->TexSrcTarget = TEXTURE_2D_INDEX;
                break;
             case TEXTARGET_3D:
                fp->TexSrcTarget = TEXTURE_3D_INDEX;
                break;
+            case TEXTARGET_SHADOWRECT:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
             case TEXTARGET_RECT:
                fp->TexSrcTarget = TEXTURE_RECT_INDEX;
                break;
             case TEXTARGET_CUBE:
                fp->TexSrcTarget = TEXTURE_CUBE_INDEX;
                break;
-           case TEXTARGET_SHADOW1D:
-           case TEXTARGET_SHADOW2D:
-           case TEXTARGET_SHADOWRECT:
-              /* TODO ARB_fragment_program_shadow code */
-              break;
+            case TEXTARGET_SHADOW1D_ARRAY:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
+            case TEXTARGET_1D_ARRAY:
+               fp->TexSrcTarget = TEXTURE_1D_ARRAY_INDEX;
+               break;
+            case TEXTARGET_SHADOW2D_ARRAY:
+               shadow_tex = 1 << texcoord;
+               /* FALLTHROUGH */
+            case TEXTARGET_2D_ARRAY:
+               fp->TexSrcTarget = TEXTURE_2D_ARRAY_INDEX;
+               break;
          }
-         Program->TexturesUsed[texcoord] |= (1<<fp->TexSrcTarget);
+
+         /* Don't test the first time a particular sampler is seen.  Each time
+          * after that, make sure the shadow state is the same.
+          */
+         if ((_mesa_bitcount(Program->TexturesUsed[texcoord]) > 0)
+             && ((Program->ShadowSamplers & (1 << texcoord)) != shadow_tex)) {
+            program_error(ctx, Program->Position,
+                          "texture image unit used for shadow sampling and non-shadow sampling");
+            return 1;
+         }
+
+         Program->TexturesUsed[texcoord] |= (1 << fp->TexSrcTarget);
+         /* Check that both "2D" and "CUBE" (for example) aren't both used */
+         if (_mesa_bitcount(Program->TexturesUsed[texcoord]) > 1) {
+            program_error(ctx, Program->Position,
+                          "multiple targets used on one texture image unit");
+            return 1;
+         }
+      
+
+         Program->ShadowSamplers |= shadow_tex;
          break;
 
       case OP_TEX_KIL:
          Program->UsesKill = 1;
-        if (parse_fp_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
+        if (parse_vector_src_reg(ctx, inst, vc_head, Program, &fp->SrcReg[0]))
             return 1;
          fp->Opcode = OPCODE_KIL;
          break;
+      default:
+         _mesa_problem(ctx, "bad type 0x%x in parse_fp_instruction()", type);
+         return 1;
    }
 
    return 0;
 }
 
-static GLuint 
-parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst,
-                struct var_cache **vc_head, struct arb_program *Program,
-                struct prog_dst_register *reg )
-{
-   GLint mask;
-   GLuint idx;
-   enum register_file file;
-
-   if (parse_masked_dst_reg(ctx, inst, vc_head, Program, &file, &idx, &mask))
-      return 1;
-
-   reg->File = file;
-   reg->Index = idx;
-   reg->WriteMask = mask;
-   return 0;
-}
 
 /**
  * Handle the parsing out of a masked address register
@@ -3089,7 +3091,7 @@ parse_vp_dst_reg(GLcontext * ctx, GLubyte ** inst,
  * \return 0 on sucess, 1 on error
  */
 static GLuint
-parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst,
+parse_vp_address_reg (GLcontext * ctx, const GLubyte ** inst,
                      struct var_cache **vc_head,
                      struct arb_program *Program,
                      struct prog_dst_register *reg)
@@ -3110,78 +3112,13 @@ parse_vp_address_reg (GLcontext * ctx, GLubyte ** inst,
    return 0;
 }
 
-/**
- * Parse vertex program vector source register.
- */
-static GLuint
-parse_vp_vector_src_reg(GLcontext * ctx, GLubyte ** inst,
-                        struct var_cache **vc_head,
-                        struct arb_program *program,
-                        struct prog_src_register *reg )
-{
-   enum register_file file;
-   GLint index;
-   GLubyte negateMask;
-   GLubyte swizzle[4];
-   GLboolean isRelOffset;
-
-   /* Grab the sign */
-   negateMask = (parse_sign (inst) == -1) ? 0xf : 0x0;
-
-   /* 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);
-
-   reg->File = file;
-   reg->Index = index;
-   reg->Swizzle = MAKE_SWIZZLE4(swizzle[0], swizzle[1],
-                                swizzle[2], swizzle[3]);
-   reg->NegateBase = negateMask;
-   reg->RelAddr = isRelOffset;
-   return 0;
-}
-
-
-static GLuint
-parse_vp_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
-                        struct var_cache **vc_head,
-                         struct arb_program *Program,
-                        struct prog_src_register *reg )
-{
-   enum register_file File;
-   GLint Index;
-   GLubyte Negate;
-   GLubyte Swizzle[4];
-   GLboolean IsRelOffset;
-
-   /* Grab the sign */
-   Negate = (parse_sign (inst) == -1) ? 0x1 : 0x0;
-
-   /* 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, 1);
-
-   reg->File = File;
-   reg->Index = Index;
-   reg->Swizzle = (Swizzle[0] << 0);
-   reg->NegateBase = Negate;
-   reg->RelAddr = IsRelOffset;
-   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,
+parse_vp_instruction (GLcontext * ctx, const GLubyte ** inst,
                       struct var_cache **vc_head, struct arb_program *Program,
                       struct prog_instruction *vp)
 {
@@ -3194,7 +3131,7 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
    /* The actual opcode name */
    code = *(*inst)++;
 
-   _mesa_init_instruction(vp);
+   _mesa_init_instructions(vp, 1);
    /* Record the position in the program string for debugging */
    vp->StringPos = Program->Position;
 
@@ -3212,7 +3149,7 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
          vp->DstReg.File = PROGRAM_ADDRESS;
 
          /* Get a scalar src register */
-        if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
+        if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
             return 1;
 
          break;
@@ -3236,10 +3173,10 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
                break;
          }
 
-         if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
+         if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
             return 1;
 
-         if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
+         if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
             return 1;
          break;
 
@@ -3264,10 +3201,10 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
                vp->Opcode = OPCODE_RSQ;
                break;
          }
-         if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
+         if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
             return 1;
 
-        if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
+        if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[0]))
             return 1;
          break;
 
@@ -3277,11 +3214,11 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
                vp->Opcode = OPCODE_POW;
                break;
          }
-         if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
+         if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
             return 1;
 
          for (a = 0; a < 2; a++) {
-           if (parse_vp_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
+           if (parse_scalar_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
                return 1;
          }
          break;
@@ -3325,11 +3262,11 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
                vp->Opcode = OPCODE_XPD;
                break;
          }
-         if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
+         if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
             return 1;
 
          for (a = 0; a < 2; a++) {
-           if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
+           if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
                return 1;
          }
          break;
@@ -3341,11 +3278,11 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
                break;
          }
 
-         if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
+         if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
             return 1;
 
          for (a = 0; a < 3; a++) {
-           if (parse_vp_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
+           if (parse_vector_src_reg(ctx, inst, vc_head, Program, &vp->SrcReg[a]))
                return 1;
          }
          break;
@@ -3363,7 +3300,7 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
             enum register_file file;
            GLint index;
 
-           if (parse_vp_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
+           if (parse_dst_reg(ctx, inst, vc_head, Program, &vp->DstReg))
               return 1;
 
            if (parse_src_reg(ctx, inst, vc_head, Program, &file, &index, &relAddr))
@@ -3385,186 +3322,6 @@ parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
 
 #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)
@@ -3572,12 +3329,12 @@ debug_variables (GLcontext * ctx, struct var_cache *vc_head,
    struct var_cache *vc;
    GLint a, b;
 
-   fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
+   fprintf (stderr, "debug_variables, vc_head: %p\n", (void*) vc_head);
 
    /* First of all, print out the contents of the var_cache */
    vc = vc_head;
    while (vc) {
-      fprintf (stderr, "[%x]\n", vc);
+      fprintf (stderr, "[%p]\n", (void*) vc);
       switch (vc->type) {
          case vt_none:
             fprintf (stderr, "UNDEFINED %s\n", vc->name);
@@ -3592,27 +3349,20 @@ debug_variables (GLcontext * ctx, struct var_cache *vc_head,
             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]);
+                        Program->Base.Parameters->Parameters[a + b].Name);
+               if (Program->Base.Parameters->Parameters[a + b].Type == PROGRAM_STATE_VAR) {
+                  const char *s;
+                  s = _mesa_program_state_string(Program->Base.Parameters->Parameters
+                                                 [a + b].StateIndexes);
+                  fprintf(stderr, "%s\n", s);
+                  _mesa_free((char *) s);
                }
                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]);
+                           Program->Base.Parameters->ParameterValues[a + b][0],
+                           Program->Base.Parameters->ParameterValues[a + b][1],
+                           Program->Base.Parameters->ParameterValues[a + b][2],
+                           Program->Base.Parameters->ParameterValues[a + b][3]);
             }
             break;
          case vt_temp:
@@ -3625,9 +3375,12 @@ debug_variables (GLcontext * ctx, struct var_cache *vc_head,
             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);
+            fprintf (stderr, "          binding: 0x%p (%s)\n",
+                     (void*) vc->alias_binding, vc->alias_binding->name);
             break;
+         default:
+            /* nothing */
+            ;
       }
       vc = vc->next;
    }
@@ -3642,8 +3395,8 @@ debug_variables (GLcontext * ctx, struct var_cache *vc_head,
  * \return 1 on error, 0 on success
  */
 static GLint
-parse_instructions(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
-                  struct arb_program *Program)
+parse_instructions(GLcontext * ctx, const GLubyte * inst,
+                   struct var_cache **vc_head, struct arb_program *Program)
 {
    const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
       ? ctx->Const.FragmentProgram.MaxInstructions
@@ -3696,15 +3449,18 @@ parse_instructions(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
                      /* do nothing for now */
                   }
                   break;
+
+               case MESA_TEXTURE_ARRAY:
+                 /* do nothing for now */
+                  break;
             }
             break;
 
          case INSTRUCTION:
             /* check length */
             if (Program->Base.NumInstructions + 1 >= maxInst) {
-               const char *msg = "Max instruction count exceeded";
-               _mesa_set_program_error(ctx, Program->Position, msg);
-               _mesa_error(ctx, GL_INVALID_OPERATION, msg);
+               program_error(ctx, Program->Position,
+                             "Max instruction count exceeded");
                return 1;
             }
             Program->Position = parse_position (&inst);
@@ -3737,7 +3493,7 @@ parse_instructions(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
    /* Finally, tag on an OPCODE_END instruction */
    {
       const GLuint numInst = Program->Base.NumInstructions;
-      _mesa_init_instruction(Program->Base.Instructions + numInst);
+      _mesa_init_instructions(Program->Base.Instructions + numInst, 1);
       Program->Base.Instructions[numInst].Opcode = OPCODE_END;
       /* YYY Wrong Position in program, whatever, at least not random -> crash
         Program->Position = parse_position (&inst);
@@ -3761,8 +3517,8 @@ parse_instructions(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
 
 
 /* XXX temporary */
-__extension__ static char core_grammar_text[] =
-#include "grammar_syn.h"
+LONGSTRING static char core_grammar_text[] =
+#include "shader/grammar/grammar_syn.h"
 ;
 
 
@@ -3812,15 +3568,15 @@ enable_parser_extensions(GLcontext *ctx, grammar id)
    /* These are not supported at this time */
    if ((ctx->Extensions.ARB_vertex_blend ||
         ctx->Extensions.EXT_vertex_weighting)
-       && !enable_ext(ctx, id, "point_parameters"))
+       && !enable_ext(ctx, id, "vertex_blend"))
       return GL_FALSE;
    if (ctx->Extensions.ARB_matrix_palette
        && !enable_ext(ctx, id, "matrix_palette"))
       return GL_FALSE;
+#endif
    if (ctx->Extensions.ARB_fragment_program_shadow
        && !enable_ext(ctx, id, "fragment_program_shadow"))
       return GL_FALSE;
-#endif
    if (ctx->Extensions.EXT_point_parameters
        && !enable_ext(ctx, id, "point_parameters"))
       return GL_FALSE;
@@ -3836,6 +3592,13 @@ enable_parser_extensions(GLcontext *ctx, grammar id)
    if (ctx->Extensions.ARB_draw_buffers
        && !enable_ext(ctx, id, "draw_buffers"))
       return GL_FALSE;
+   if (ctx->Extensions.MESA_texture_array
+       && !enable_ext(ctx, id, "texture_array"))
+      return GL_FALSE;
+#if 1
+   /* hack for Warcraft (see bug 8060) */
+   enable_ext(ctx, id, "vertex_blend");
+#endif
 
    return GL_TRUE;
 }
@@ -3939,9 +3702,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
       GLint 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,
-                         "glProgramStringARB(illegal character)");
+            program_error(ctx, i, "illegal character");
             grammar_destroy (arbprogram_syn_id);
             return GL_FALSE;
          }
@@ -3964,25 +3725,25 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
 
    /* Syntax parse error */
    if (err) {
-      _mesa_free(strz);
-      _mesa_free(parsed);
-      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,
-                   "glProgramStringARB(syntax error)");
+      grammar_get_last_error((GLubyte *) error_msg, 300, &error_pos);
+      program_error(ctx, error_pos, error_msg);
 
-      /* useful for debugging */
 #if DEBUG_PARSING
+      /* useful for debugging */
       do {
          int line, col;
          char *s;
          fprintf(stderr, "program: %s\n", (char *) strz);
-         fprintf(stderr, "Error Pos: %d\n", ctx->program.ErrorPos);
-         s = (char *) _mesa_find_line_column(strz, strz+ctx->program.ErrorPos, &line, &col);
+         fprintf(stderr, "Error Pos: %d\n", ctx->Program.ErrorPos);
+         s = (char *) _mesa_find_line_column(strz, strz+ctx->Program.ErrorPos,
+                                             &line, &col);
          fprintf(stderr, "line %d col %d: %s\n", line, col, s);
-      } while (0)
+      } while (0);
 #endif
 
+      _mesa_free(strz);
+      _mesa_free(parsed);
+
       grammar_destroy (arbprogram_syn_id);
       return GL_FALSE;
    }
@@ -3997,8 +3758,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
 
    /* Initialize the arb_program struct */
    program->Base.String = strz;
-   program->Base.Instructions = (struct prog_instruction *)
-      _mesa_malloc(MAX_INSTRUCTIONS * sizeof(struct prog_instruction));
+   program->Base.Instructions = _mesa_alloc_instructions(MAX_INSTRUCTIONS);
    program->Base.NumInstructions =
    program->Base.NumTemporaries =
    program->Base.NumParameters =
@@ -4013,6 +3773,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
    program->HintPositionInvariant = GL_FALSE;
    for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
       program->TexturesUsed[a] = 0x0;
+   program->ShadowSamplers = 0x0;
    program->NumAluInstructions =
    program->NumTexInstructions =
    program->NumTexIndirections = 0;
@@ -4026,9 +3787,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
 
    /* Check the grammer rev */
    if (*inst++ != REVISION) {
-      _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
-      _mesa_error(ctx, GL_INVALID_OPERATION,
-                  "glProgramStringARB(Grammar version mismatch)");
+      program_error (ctx, 0, "Grammar version mismatch");
       err = GL_TRUE;
    }
    else {
@@ -4047,11 +3806,11 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
    /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
     * to size [ap.Base.NumInstructions].
     */
-   program->Base.Instructions = (struct prog_instruction *)
-      _mesa_realloc(program->Base.Instructions,
-             MAX_INSTRUCTIONS * sizeof(struct prog_instruction),/*orig*/
-             program->Base.NumInstructions * sizeof(struct prog_instruction));
-   
+   program->Base.Instructions
+      = _mesa_realloc_instructions(program->Base.Instructions,
+                                   MAX_INSTRUCTIONS,
+                                   program->Base.NumInstructions);
+
    return !err;
 }
 
@@ -4060,7 +3819,7 @@ _mesa_parse_arb_program(GLcontext *ctx, GLenum target,
 void
 _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
                                  const GLvoid *str, GLsizei len,
-                                 struct fragment_program *program)
+                                 struct gl_fragment_program *program)
 {
    struct arb_program ap;
    GLuint i;
@@ -4080,17 +3839,27 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
    program->Base.NumParameters   = ap.Base.NumParameters;
    program->Base.NumAttributes   = ap.Base.NumAttributes;
    program->Base.NumAddressRegs  = ap.Base.NumAddressRegs;
-   program->NumAluInstructions   = ap.NumAluInstructions;
-   program->NumTexInstructions   = ap.NumTexInstructions;
-   program->NumTexIndirections   = ap.NumTexIndirections;
-   program->NumNativeAluInstructions = ap.NumAluInstructions;
-   program->NumNativeTexInstructions = ap.NumTexInstructions;
-   program->NumNativeTexIndirections = ap.NumTexIndirections;
+   program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
+   program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
+   program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
+   program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
+   program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
+   program->Base.NumAluInstructions   = ap.Base.NumAluInstructions;
+   program->Base.NumTexInstructions   = ap.Base.NumTexInstructions;
+   program->Base.NumTexIndirections   = ap.Base.NumTexIndirections;
+   program->Base.NumNativeAluInstructions = ap.Base.NumAluInstructions;
+   program->Base.NumNativeTexInstructions = ap.Base.NumTexInstructions;
+   program->Base.NumNativeTexIndirections = ap.Base.NumTexIndirections;
    program->Base.InputsRead      = ap.Base.InputsRead;
    program->Base.OutputsWritten  = ap.Base.OutputsWritten;
-   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
-      program->TexturesUsed[i] = ap.TexturesUsed[i];
+   for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) {
+      program->Base.TexturesUsed[i] = ap.TexturesUsed[i];
+      if (ap.TexturesUsed[i])
+         program->Base.SamplersUsed |= (1 << i);
+   }
+   program->Base.ShadowSamplers = ap.ShadowSamplers;
    program->FogOption          = ap.FogOption;
+   program->UsesKill          = ap.UsesKill;
 
    if (program->Base.Instructions)
       _mesa_free(program->Base.Instructions);
@@ -4100,8 +3869,19 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
       _mesa_free_parameter_list(program->Base.Parameters);
    program->Base.Parameters    = ap.Base.Parameters;
 
+   /* Append fog instructions now if the program has "OPTION ARB_fog_exp"
+    * or similar.  We used to leave this up to drivers, but it appears
+    * there's no hardware that wants to do fog in a discrete stage separate
+    * from the fragment shader.
+    */
+   if (program->FogOption != GL_NONE) {
+      _mesa_append_fog_code(ctx, program);
+      program->FogOption = GL_NONE;
+   }
+
 #if DEBUG_FP
-   _mesa_print_program(&program.Base);
+   _mesa_printf("____________Fragment program %u ________\n", program->Base.ID);
+   _mesa_print_program(&program->Base);
 #endif
 }
 
@@ -4115,14 +3895,14 @@ _mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
 void
 _mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
                               const GLvoid *str, GLsizei len,
-                              struct vertex_program *program)
+                              struct gl_vertex_program *program)
 {
    struct arb_program ap;
 
    ASSERT(target == GL_VERTEX_PROGRAM_ARB);
 
    if (!_mesa_parse_arb_program(ctx, target, (const GLubyte*) str, len, &ap)) {
-      /* Error in the program. Just return. */
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramString(bad program)");
       return;
    }
 
@@ -4135,6 +3915,11 @@ _mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
    program->Base.NumParameters   = ap.Base.NumParameters;
    program->Base.NumAttributes   = ap.Base.NumAttributes;
    program->Base.NumAddressRegs  = ap.Base.NumAddressRegs;
+   program->Base.NumNativeInstructions = ap.Base.NumNativeInstructions;
+   program->Base.NumNativeTemporaries = ap.Base.NumNativeTemporaries;
+   program->Base.NumNativeParameters = ap.Base.NumNativeParameters;
+   program->Base.NumNativeAttributes = ap.Base.NumNativeAttributes;
+   program->Base.NumNativeAddressRegs = ap.Base.NumNativeAddressRegs;
    program->Base.InputsRead     = ap.Base.InputsRead;
    program->Base.OutputsWritten = ap.Base.OutputsWritten;
    program->IsPositionInvariant = ap.HintPositionInvariant;
@@ -4148,6 +3933,7 @@ _mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
    program->Base.Parameters = ap.Base.Parameters; 
 
 #if DEBUG_VP
+   _mesa_printf("____________Vertex program %u __________\n", program->Base.Id);
    _mesa_print_program(&program->Base);
 #endif
 }