init secondary color to (0,0,0,1). remove some redundant initializations.
[mesa.git] / src / mesa / main / nvfragparse.c
index 03c20608566f9ac8e34fe5216e19bacfc2f097c5..b742ff0a32da26f3f4bfb1b0e5c3ccd075541b5c 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: nvfragparse.c,v 1.17 2003/04/05 00:38:09 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  5.1
+ * Version:  6.0
  *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
-
 /**
  * \file nvfragparse.c
- * \brief NVIDIA fragment program parser.
+ * NVIDIA fragment program parser.
  * \author Brian Paul
  */
 
+/*
+ * Regarding GL_NV_fragment_program:
+ *
+ * Portions of this software may use or implement intellectual
+ * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
+ * any and all warranties with respect to such intellectual property,
+ * including any use thereof or modifications thereto.
+ */
+
 #include "glheader.h"
 #include "context.h"
 #include "hash.h"
 #include "nvfragprog.h"
 #include "nvfragparse.h"
 #include "nvprogram.h"
-
-
-/* XXX move into imports.[ch] eventually */
-static void *
-_mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize)
-{
-   size_t copySize = MIN2(oldSize, newSize);
-   void *newBuffer = _mesa_malloc(newSize);
-   if (newBuffer && copySize > 0)
-      _mesa_memcpy(newBuffer, oldBuffer, copySize);
-   if (oldBuffer)
-      _mesa_free(oldBuffer);
-   return newBuffer;
-}
+#include "program.h"
 
 
 #define INPUT_1V     1
@@ -69,6 +62,13 @@ _mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize)
 #define OUTPUT_S    21
 #define OUTPUT_NONE 22
 
+/* IRIX defines some of these */
+#undef _R
+#undef _H
+#undef _X
+#undef _C
+#undef _S
+
 /* Optional suffixes */
 #define _R  FLOAT32  /* float */
 #define _H  FLOAT16  /* half-float */
@@ -143,84 +143,18 @@ struct parse_state {
    GLcontext *ctx;
    const GLubyte *start;              /* start of program string */
    const GLubyte *pos;                /* current position */
+   const GLubyte *curLine;
    struct fragment_program *program;  /* current program */
 
-   GLuint numParameters;
-   struct program_parameter *parameters; /* DECLARE */
-
-   GLuint numConstants;
-   struct program_parameter *constants; /* DEFINE */
+   struct program_parameter_list *parameters;
 
    GLuint numInst;                    /* number of instructions parsed */
    GLuint inputsRead;                 /* bitmask of input registers used */
-   GLuint outputsWritten;             /* 2 = depth register */
+   GLuint outputsWritten;             /* bitmask of 1 << FRAG_OUTPUT_* bits */
    GLuint texturesUsed[MAX_TEXTURE_IMAGE_UNITS];
 };
 
 
-/**
- * Add a new program parameter (via DEFINE statement)
- * \return index of the new entry in the parameter list
- */
-static GLuint
-add_parameter(struct parse_state *parseState,
-              const char *name, const GLfloat values[4], GLboolean constant)
-{
-   const GLuint n = parseState->numParameters;
-
-   parseState->parameters = _mesa_realloc(parseState->parameters,
-                                   n * sizeof(struct program_parameter),
-                                   (n + 1) * sizeof(struct program_parameter));
-   parseState->numParameters = n + 1;
-   parseState->parameters[n].Name = _mesa_strdup(name);
-   COPY_4V(parseState->parameters[n].Values, values);
-   parseState->parameters[n].Constant = constant;
-   return n;
-}
-
-
-/**
- * Add a new unnamed constant to the parameter lists.
- * \param parseState  parsing state
- * \param values  four float values
- * \return index of the new parameter.
- */
-static GLuint
-add_unnamed_constant(struct parse_state *parseState, const GLfloat values[4])
-{
-   /* generate a new dummy name */
-   static GLuint n = 0;
-   char name[20];
-   _mesa_sprintf(name, "constant%d", n);
-   n++;
-   /* store it */
-   return add_parameter(parseState, name, values, GL_TRUE);
-}
-
-
-static const GLfloat *
-lookup_parameter(struct parse_state *parseState, const char *name)
-{
-   GLuint i;
-   for (i = 0; i < parseState->numParameters; i++) {
-      if (_mesa_strcmp(parseState->parameters[i].Name, name) == 0)
-         return parseState->parameters[i].Values;
-   }
-   return NULL;
-}
-
-
-static const GLint
-lookup_parameter_index(struct parse_state *parseState, const char *name)
-{
-   GLint i;
-   for (i = 0; i < parseState->numParameters; i++) {
-      if (_mesa_strcmp(parseState->parameters[i].Name, name) == 0)
-         return i;
-   }
-   return -1;
-}
-
 
 /*
  * Called whenever we find an error during parsing.
@@ -349,8 +283,9 @@ static GLboolean IsWhitespace(GLubyte b)
  * \return <= 0 we found an error, else, return number of characters parsed.
  */
 static GLint
-GetToken(const GLubyte *str, GLubyte *token)
+GetToken(struct parse_state *parseState, GLubyte *token)
 {
+   const GLubyte *str = parseState->pos;
    GLint i = 0, j = 0;
 
    token[0] = 0;
@@ -362,9 +297,13 @@ GetToken(const GLubyte *str, GLubyte *token)
          while (str[i] && (str[i] != '\n' && str[i] != '\r')) {
             i++;
          }
+         if (str[i] == '\n' || str[i] == '\r')
+            parseState->curLine = str + i + 1;
       }
       else {
          /* skip whitespace */
+         if (str[i] == '\n' || str[i] == '\r')
+            parseState->curLine = str + i + 1;
          i++;
       }
    }
@@ -410,7 +349,7 @@ static GLboolean
 Parse_Token(struct parse_state *parseState, GLubyte *token)
 {
    GLint i;
-   i = GetToken(parseState->pos, token);
+   i = GetToken(parseState, token);
    if (i <= 0) {
       parseState->pos += (-i);
       return GL_FALSE;
@@ -427,7 +366,7 @@ static GLboolean
 Peek_Token(struct parse_state *parseState, GLubyte *token)
 {
    GLint i, len;
-   i = GetToken(parseState->pos, token);
+   i = GetToken(parseState, token);
    if (i <= 0) {
       parseState->pos += (-i);
       return GL_FALSE;
@@ -455,59 +394,6 @@ static const char *OutputRegisters[MAX_NV_FRAGMENT_PROGRAM_OUTPUTS + 1] = {
 };
 
 
-static GLint
-TempRegisterNumber(GLuint r)
-{
-   if (r >= FP_TEMP_REG_START && r <= FP_TEMP_REG_END)
-      return r - FP_TEMP_REG_START;
-   else
-      return -1;
-}
-
-static GLint
-HalfTempRegisterNumber(GLuint r)
-{
-   if (r >= FP_TEMP_REG_START + 32 && r <= FP_TEMP_REG_END)
-      return r - FP_TEMP_REG_START - 32;
-   else
-      return -1;
-}
-
-static GLint
-InputRegisterNumber(GLuint r)
-{
-   if (r >= FP_INPUT_REG_START && r <= FP_INPUT_REG_END)
-      return r - FP_INPUT_REG_START;
-   else
-      return -1;
-}
-
-static GLint
-OutputRegisterNumber(GLuint r)
-{
-   if (r >= FP_OUTPUT_REG_START && r <= FP_OUTPUT_REG_END)
-      return r - FP_OUTPUT_REG_START;
-   else
-      return -1;
-}
-
-static GLint
-ProgramRegisterNumber(GLuint r)
-{
-   if (r >= FP_PROG_REG_START && r <= FP_PROG_REG_END)
-      return r - FP_PROG_REG_START;
-   else
-      return -1;
-}
-
-static GLint
-DummyRegisterNumber(GLuint r)
-{
-   if (r >= FP_DUMMY_REG_START && r <= FP_DUMMY_REG_END)
-      return r - FP_DUMMY_REG_START;
-   else
-      return -1;
-}
 
 
 /**********************************************************************/
@@ -527,9 +413,13 @@ Parse_String(struct parse_state *parseState, const char *pattern)
          while (*parseState->pos && (*parseState->pos != '\n' && *parseState->pos != '\r')) {
             parseState->pos += 1;
          }
+         if (*parseState->pos == '\n' || *parseState->pos == '\r')
+            parseState->curLine = parseState->pos + 1;
       }
       else {
          /* skip whitespace */
+         if (*parseState->pos == '\n' || *parseState->pos == '\r')
+            parseState->curLine = parseState->pos + 1;
          parseState->pos += 1;
       }
    }
@@ -562,6 +452,7 @@ Parse_Identifier(struct parse_state *parseState, GLubyte *ident)
 /**
  * Parse a floating point constant, or a defined symbol name.
  * [+/-]N[.N[eN]]
+ * Output:  number[0 .. 3] will get the value.
  */
 static GLboolean
 Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
@@ -573,6 +464,9 @@ Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
    if (end && end > (char *) parseState->pos) {
       /* got a number */
       parseState->pos = (GLubyte *) end;
+      number[1] = *number;
+      number[2] = *number;
+      number[3] = *number;
       return GL_TRUE;
    }
    else {
@@ -581,7 +475,8 @@ Parse_ScalarConstant(struct parse_state *parseState, GLfloat *number)
       const GLfloat *constant;
       if (!Parse_Identifier(parseState, ident))
          RETURN_ERROR1("Expected an identifier");
-      constant = lookup_parameter(parseState, (const char *) ident);
+      constant = _mesa_lookup_parameter_value(parseState->parameters,
+                                              -1, (const char *) ident);
       /* XXX Check that it's a constant and not a parameter */
       if (!constant) {
          RETURN_ERROR1("Undefined symbol");
@@ -607,11 +502,12 @@ Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec)
 {
    /* "{" was already consumed */
 
+   ASSIGN_4V(vec, 0.0, 0.0, 0.0, 1.0);
+
    if (!Parse_ScalarConstant(parseState, vec+0))  /* X */
       return GL_FALSE;
 
    if (Parse_String(parseState, "}")) {
-      vec[1] = vec[2] = vec[3] = vec[0];
       return GL_TRUE;
    }
 
@@ -622,7 +518,6 @@ Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec)
       return GL_FALSE;
 
    if (Parse_String(parseState, "}")) {
-      vec[2] = vec[3] = vec[1];
       return GL_TRUE;
    }
 
@@ -633,7 +528,6 @@ Parse_VectorConstant(struct parse_state *parseState, GLfloat *vec)
       return GL_FALSE;
 
    if (Parse_String(parseState, "}")) {
-      vec[3] = vec[2];
       return GL_TRUE;
    }
 
@@ -827,7 +721,7 @@ Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
          reg += 32;
       if (reg >= MAX_NV_FRAGMENT_PROGRAM_TEMPS)
          RETURN_ERROR1("Invalid temporary register name");
-      *tempRegNum = FP_TEMP_REG_START + reg;
+      *tempRegNum = reg;
    }
    else {
       RETURN_ERROR1("Invalid temporary register name");
@@ -844,10 +738,10 @@ static GLboolean
 Parse_DummyReg(struct parse_state *parseState, GLint *regNum)
 {
    if (Parse_String(parseState, "RC")) {
-       *regNum = FP_DUMMY_REG_START;
+       *regNum = 0;
    }
    else if (Parse_String(parseState, "HC")) {
-       *regNum = FP_DUMMY_REG_START + 1;
+       *regNum = 1;
    }
    else {
       RETURN_ERROR1("Invalid write-only register name");
@@ -876,7 +770,7 @@ Parse_ProgramParamReg(struct parse_state *parseState, GLint *regNum)
       GLint reg = _mesa_atoi((const char *) token);
       if (reg >= MAX_NV_FRAGMENT_PROGRAM_PARAMS)
          RETURN_ERROR1("Invalid constant program number");
-      *regNum = FP_PROG_REG_START + reg;
+      *regNum = reg;
    }
    else {
       RETURN_ERROR;
@@ -908,7 +802,7 @@ Parse_FragReg(struct parse_state *parseState, GLint *tempRegNum)
    }
    for (j = 0; InputRegisters[j]; j++) {
       if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
-         *tempRegNum = FP_INPUT_REG_START + j;
+         *tempRegNum = j;
          parseState->inputsRead |= (1 << j);
          break;
       }
@@ -943,9 +837,10 @@ Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
    /* try to match an output register name */
    for (j = 0; OutputRegisters[j]; j++) {
       if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
-         *outputRegNum = FP_OUTPUT_REG_START + j;
+         static GLuint bothColors = (1 << FRAG_OUTPUT_COLR) | (1 << FRAG_OUTPUT_COLH);
+         *outputRegNum = j;
          parseState->outputsWritten |= (1 << j);
-         if ((parseState->outputsWritten & 0x3) == 0x3) {
+         if ((parseState->outputsWritten & bothColors) == bothColors) {
             RETURN_ERROR1("Illegal to write to both o[COLR] and o[COLH]");
          }
          break;
@@ -975,17 +870,20 @@ Parse_MaskedDstReg(struct parse_state *parseState,
    if (_mesa_strcmp((const char *) token, "RC") == 0 ||
        _mesa_strcmp((const char *) token, "HC") == 0) {
       /* a write-only register */
-      if (!Parse_DummyReg(parseState, &dstReg->Register))
+      dstReg->File = PROGRAM_WRITE_ONLY;
+      if (!Parse_DummyReg(parseState, &dstReg->Index))
          RETURN_ERROR;
    }
    else if (token[0] == 'R' || token[0] == 'H') {
       /* a temporary register */
-      if (!Parse_TempReg(parseState, &dstReg->Register))
+      dstReg->File = PROGRAM_TEMPORARY;
+      if (!Parse_TempReg(parseState, &dstReg->Index))
          RETURN_ERROR;
    }
    else if (token[0] == 'o') {
       /* an output register */
-      if (!Parse_OutputReg(parseState, &dstReg->Register))
+      dstReg->File = PROGRAM_OUTPUT;
+      if (!Parse_OutputReg(parseState, &dstReg->Index))
          RETURN_ERROR;
    }
    else {
@@ -1103,17 +1001,20 @@ Parse_VectorSrc(struct parse_state *parseState,
     * literal or vector literal.
     */
    if (token[0] == 'R' || token[0] == 'H') {
-      if (!Parse_TempReg(parseState, &srcReg->Register))
+      srcReg->File = PROGRAM_TEMPORARY;
+      if (!Parse_TempReg(parseState, &srcReg->Index))
          RETURN_ERROR;
    }
    else if (token[0] == 'f') {
       /* XXX this might be an identier! */
-      if (!Parse_FragReg(parseState, &srcReg->Register))
+      srcReg->File = PROGRAM_INPUT;
+      if (!Parse_FragReg(parseState, &srcReg->Index))
          RETURN_ERROR;
    }
    else if (token[0] == 'p') {
       /* XXX this might be an identier! */
-      if (!Parse_ProgramParamReg(parseState, &srcReg->Register))
+      srcReg->File = PROGRAM_LOCAL_PARAM;
+      if (!Parse_ProgramParamReg(parseState, &srcReg->Index))
          RETURN_ERROR;
    }
    else if (IsLetter(token[0])){
@@ -1121,30 +1022,34 @@ Parse_VectorSrc(struct parse_state *parseState,
       GLint paramIndex;
       if (!Parse_Identifier(parseState, ident))
          RETURN_ERROR;
-      paramIndex = lookup_parameter_index(parseState, (const char *) ident);
+      paramIndex = _mesa_lookup_parameter_index(parseState->parameters,
+                                                -1, (const char *) ident);
       if (paramIndex < 0) {
          RETURN_ERROR2("Undefined constant or parameter: ", ident);
       }
-      srcReg->IsParameter = GL_TRUE;
-      srcReg->Register = paramIndex;      
+      srcReg->File = PROGRAM_NAMED_PARAM;
+      srcReg->Index = paramIndex;      
    }
-   else if (IsDigit(token[0]) || token[0] == '-' || token[0] == '+'){
-      /* XXX literal scalar constant */
+   else if (IsDigit(token[0]) || token[0] == '-' || token[0] == '+' || token[0] == '.'){
+      /* literal scalar constant */
       GLfloat values[4];
+      GLuint paramIndex;
       if (!Parse_ScalarConstant(parseState, values))
          RETURN_ERROR;
-      srcReg->Register = 0; /* XXX fix */
+      paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
+      srcReg->File = PROGRAM_NAMED_PARAM;
+      srcReg->Index = paramIndex;
    }
    else if (token[0] == '{'){
-      /* XXX literal vector constant */
+      /* literal vector constant */
       GLfloat values[4];
       GLuint paramIndex;
       (void) Parse_String(parseState, "{");
       if (!Parse_VectorConstant(parseState, values))
          RETURN_ERROR;
-      paramIndex = add_unnamed_constant(parseState, values);
-      srcReg->IsParameter = GL_TRUE;
-      srcReg->Register = paramIndex;      
+      paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
+      srcReg->File = PROGRAM_NAMED_PARAM;
+      srcReg->Index = paramIndex;      
    }
    else {
       RETURN_ERROR2("Invalid source register name", token);
@@ -1179,13 +1084,32 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
                    struct fp_src_register *srcReg)
 {
    GLubyte token[100];
+   GLfloat sign = 1.0F;
+   GLboolean needSuffix = GL_TRUE;
 
-   /* check for '-' */
-   if (Parse_String(parseState, "-")) {
-      srcReg->NegateBase = GL_TRUE;
+   /*
+    * First, take care of +/- and absolute value stuff.
+    */
+   if (Parse_String(parseState, "-"))
+      sign = -1.0F;
+   else if (Parse_String(parseState, "+"))
+      sign = +1.0F;
+
+   if (Parse_String(parseState, "|")) {
+      srcReg->Abs = GL_TRUE;
+      srcReg->NegateAbs = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
+
+      if (Parse_String(parseState, "-"))
+         srcReg->NegateBase = GL_TRUE;
+      else if (Parse_String(parseState, "+"))
+         srcReg->NegateBase = GL_FALSE;
+      else
+         srcReg->NegateBase = GL_FALSE;
    }
    else {
-      srcReg->NegateBase = GL_FALSE;
+      srcReg->Abs = GL_FALSE;
+      srcReg->NegateAbs = GL_FALSE;
+      srcReg->NegateBase = (sign < 0.0F) ? GL_TRUE : GL_FALSE;
    }
 
    if (!Peek_Token(parseState, token))
@@ -1193,41 +1117,75 @@ Parse_ScalarSrcReg(struct parse_state *parseState,
 
    /* Src reg can be R<n>, H<n> or a named fragment attrib */
    if (token[0] == 'R' || token[0] == 'H') {
-      if (!Parse_TempReg(parseState, &srcReg->Register))
+      srcReg->File = PROGRAM_TEMPORARY;
+      if (!Parse_TempReg(parseState, &srcReg->Index))
          RETURN_ERROR;
    }
    else if (token[0] == 'f') {
-      if (!Parse_FragReg(parseState, &srcReg->Register))
+      srcReg->File = PROGRAM_INPUT;
+      if (!Parse_FragReg(parseState, &srcReg->Index))
+         RETURN_ERROR;
+   }
+   else if (token[0] == '{') {
+      /* vector literal */
+      GLfloat values[4];
+      GLuint paramIndex;
+      (void) Parse_String(parseState, "{");
+      if (!Parse_VectorConstant(parseState, values))
+         RETURN_ERROR;
+      paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
+      srcReg->File = PROGRAM_NAMED_PARAM;
+      srcReg->Index = paramIndex;      
+   }
+   else if (IsDigit(token[0])) {
+      /* scalar literal */
+      GLfloat values[4];
+      GLuint paramIndex;
+      if (!Parse_ScalarConstant(parseState, values))
          RETURN_ERROR;
+      paramIndex = _mesa_add_unnamed_constant(parseState->parameters, values);
+      srcReg->Index = paramIndex;      
+      srcReg->File = PROGRAM_NAMED_PARAM;
+      needSuffix = GL_FALSE;
    }
    else {
-      RETURN_ERROR2("Invalid source register name", token);
+      RETURN_ERROR2("Invalid scalar source argument", token);
    }
 
-   /* Look for .[xyzw] suffix */
-   if (!Parse_String(parseState, "."))
-      RETURN_ERROR1("Expected .");
+   if (needSuffix) {
+      /* parse .[xyzw] suffix */
+      if (!Parse_String(parseState, "."))
+         RETURN_ERROR1("Expected .");
 
-   if (!Parse_Token(parseState, token))
-      RETURN_ERROR;
+      if (!Parse_Token(parseState, token))
+         RETURN_ERROR;
 
-   if (token[0] == 'x' && token[1] == 0) {
-      srcReg->Swizzle[0] = 0;
-   }
-   else if (token[0] == 'y' && token[1] == 0) {
-      srcReg->Swizzle[0] = 1;
-   }
-   else if (token[0] == 'z' && token[1] == 0) {
-      srcReg->Swizzle[0] = 2;
-   }
-   else if (token[0] == 'w' && token[1] == 0) {
-      srcReg->Swizzle[0] = 3;
+      if (token[0] == 'x' && token[1] == 0) {
+         srcReg->Swizzle[0] = 0;
+      }
+      else if (token[0] == 'y' && token[1] == 0) {
+         srcReg->Swizzle[0] = 1;
+      }
+      else if (token[0] == 'z' && token[1] == 0) {
+         srcReg->Swizzle[0] = 2;
+      }
+      else if (token[0] == 'w' && token[1] == 0) {
+         srcReg->Swizzle[0] = 3;
+      }
+      else {
+         RETURN_ERROR1("Invalid scalar source suffix");
+      }
    }
    else {
-      RETURN_ERROR1("Invalid scalar source suffix");
+      srcReg->Swizzle[0] = 0;
    }
    srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;
 
+   /* Finish absolute value */
+   if (srcReg->Abs && !Parse_String(parseState, "|")) {
+      RETURN_ERROR1("Expected |");
+   }
+
    return GL_TRUE;
 }
 
@@ -1243,10 +1201,14 @@ Parse_InstructionSequence(struct parse_state *parseState,
       GLubyte token[100];
 
       /* Initialize the instruction */
-      inst->SrcReg[0].Register = -1;
-      inst->SrcReg[1].Register = -1;
-      inst->SrcReg[2].Register = -1;
-      inst->DstReg.Register = -1;
+      inst->SrcReg[0].File = (enum register_file) -1;
+      inst->SrcReg[1].File = (enum register_file) -1;
+      inst->SrcReg[2].File = (enum register_file) -1;
+      inst->DstReg.File = (enum register_file) -1;
+      inst->DstReg.CondSwizzle[0] = 0;
+      inst->DstReg.CondSwizzle[1] = 1;
+      inst->DstReg.CondSwizzle[2] = 2;
+      inst->DstReg.CondSwizzle[3] = 3;
 
       /* special instructions */
       if (Parse_String(parseState, "DEFINE")) {
@@ -1261,12 +1223,12 @@ Parse_InstructionSequence(struct parse_state *parseState,
             RETURN_ERROR;
          if (!Parse_String(parseState, ";"))
             RETURN_ERROR1("Expected ;");
-         printf("Parsed DEFINE %s = %f %f %f %f\n", id, value[0], value[1],
-                value[2], value[3]);
-         if (lookup_parameter(parseState, (const char *) id)) {
+         if (_mesa_lookup_parameter_index(parseState->parameters,
+                                          -1, (const char *) id) >= 0) {
             RETURN_ERROR2(id, "already defined");
          }
-         add_parameter(parseState, (const char *) id, value, GL_TRUE);
+         _mesa_add_named_parameter(parseState->parameters,
+                                   (const char *) id, value);
       }
       else if (Parse_String(parseState, "DECLARE")) {
          GLubyte id[100];
@@ -1277,21 +1239,20 @@ Parse_InstructionSequence(struct parse_state *parseState,
          if (Parse_String(parseState, "=")) {
             if (!Parse_VectorOrScalarConstant(parseState, value))
                RETURN_ERROR;
-            printf("Parsed DECLARE %s = %f %f %f %f\n", id,
-                   value[0], value[1], value[2], value[3]);
-         }
-         else {
-            printf("Parsed DECLARE %s\n", id);
          }
          if (!Parse_String(parseState, ";"))
             RETURN_ERROR1("Expected ;");
-         if (lookup_parameter(parseState, (const char *) id)) {
+         if (_mesa_lookup_parameter_index(parseState->parameters,
+                                          -1, (const char *) id) >= 0) {
             RETURN_ERROR2(id, "already declared");
          }
-         add_parameter(parseState, (const char *) id, value, GL_FALSE);
+         _mesa_add_named_parameter(parseState->parameters,
+                                   (const char *) id, value);
       }
       else if (Parse_String(parseState, "END")) {
          inst->Opcode = FP_OPCODE_END;
+         inst->StringPos = parseState->curLine - parseState->start;
+         assert(inst->StringPos >= 0);
          parseState->numInst++;
          if (Parse_Token(parseState, token)) {
             RETURN_ERROR1("Code after END opcode.");
@@ -1317,6 +1278,8 @@ Parse_InstructionSequence(struct parse_state *parseState,
          inst->Precision = instMatch.suffixes & (_R | _H | _X);
          inst->Saturate = (instMatch.suffixes & (_S)) ? GL_TRUE : GL_FALSE;
          inst->UpdateCondRegister = (instMatch.suffixes & (_C)) ? GL_TRUE : GL_FALSE;
+         inst->StringPos = parseState->curLine - parseState->start;
+         assert(inst->StringPos >= 0);
 
          /*
           * parse the input and output operands
@@ -1347,7 +1310,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
                RETURN_ERROR;
          }
          else if (instMatch.inputs == INPUT_3V) {
-            if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
+            if (!Parse_VectorSrc(parseState, &inst->SrcReg[0]))
                RETURN_ERROR;
             if (!Parse_String(parseState, ","))
                RETURN_ERROR1("Expected ,");
@@ -1355,11 +1318,11 @@ Parse_InstructionSequence(struct parse_state *parseState,
                RETURN_ERROR;
             if (!Parse_String(parseState, ","))
                RETURN_ERROR1("Expected ,");
-            if (!Parse_VectorSrc(parseState, &inst->SrcReg[1]))
+            if (!Parse_VectorSrc(parseState, &inst->SrcReg[2]))
                RETURN_ERROR;
          }
          else if (instMatch.inputs == INPUT_1S) {
-            if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[1]))
+            if (!Parse_ScalarSrcReg(parseState, &inst->SrcReg[0]))
                RETURN_ERROR;
          }
          else if (instMatch.inputs == INPUT_2S) {
@@ -1446,6 +1409,8 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
    parseState.start = programString;
    parseState.program = program;
    parseState.numInst = 0;
+   parseState.curLine = programString;
+   parseState.parameters = _mesa_new_parameter_list();
 
    /* Reset error state */
    _mesa_set_program_error(ctx, -1, NULL);
@@ -1504,6 +1469,7 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
          FREE(program->Base.String);
       }
       program->Base.String = programString;
+      program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
       if (program->Instructions) {
          FREE(program->Instructions);
       }
@@ -1514,24 +1480,8 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
          program->TexturesUsed[u] = parseState.texturesUsed[u];
 
       /* save program parameters */
-      if (program->Parameters) {
-         GLuint i;
-         for (i = 0; i < program->NumParameters; i++)
-            _mesa_free((void *) program->Parameters[i].Name);
-         _mesa_free(program->Parameters);
-      }
-      program->NumParameters = parseState.numParameters;
       program->Parameters = parseState.parameters;
 
-      /* free program constants */
-      if (parseState.constants) {
-         GLuint i;
-         for (i = 0; i < parseState.numConstants; i++)
-            _mesa_free((void *) parseState.constants[i].Name);
-         _mesa_free(parseState.constants);
-      }
-         
-
       /* allocate registers for declared program parameters */
 #if 00
       _mesa_assign_program_registers(&(program->SymbolTable));
@@ -1552,10 +1502,10 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
 
 
 static void
-PrintSrcReg(const struct fp_src_register *src)
+PrintSrcReg(const struct fragment_program *program,
+            const struct fp_src_register *src)
 {
    static const char comps[5] = "xyzw";
-   GLint r;
 
    if (src->NegateAbs) {
       _mesa_printf("-");
@@ -1566,26 +1516,40 @@ PrintSrcReg(const struct fp_src_register *src)
    if (src->NegateBase) {
       _mesa_printf("-");
    }
-   if ((r = OutputRegisterNumber(src->Register)) >= 0) {
-      _mesa_printf("o[%s]", OutputRegisters[r]);
+   if (src->File == PROGRAM_NAMED_PARAM) {
+      if (program->Parameters->Parameters[src->Index].Type == CONSTANT) {
+         printf("{%g, %g, %g, %g}",
+                program->Parameters->Parameters[src->Index].Values[0],
+                program->Parameters->Parameters[src->Index].Values[1],
+                program->Parameters->Parameters[src->Index].Values[2],
+                program->Parameters->Parameters[src->Index].Values[3]);
+      }
+      else {
+         ASSERT(program->Parameters->Parameters[src->Index].Type
+                == NAMED_PARAMETER);
+         printf("%s", program->Parameters->Parameters[src->Index].Name);
+      }
    }
-   else if ((r = InputRegisterNumber(src->Register)) >= 0) {
-      _mesa_printf("f[%s]", InputRegisters[r]);
+   else if (src->File == PROGRAM_OUTPUT) {
+      _mesa_printf("o[%s]", OutputRegisters[src->Index]);
    }
-   else if ((r = ProgramRegisterNumber(src->Register)) >= 0) {
-      _mesa_printf("p[%d]", r);
+   else if (src->File == PROGRAM_INPUT) {
+      _mesa_printf("f[%s]", InputRegisters[src->Index]);
    }
-   else if ((r = HalfTempRegisterNumber(src->Register)) >= 0) {
-      _mesa_printf("H%d", r);
+   else if (src->File == PROGRAM_LOCAL_PARAM) {
+      _mesa_printf("p[%d]", src->Index);
    }
-   else if ((r = TempRegisterNumber(src->Register)) >= 0) {
-      _mesa_printf("R%d", r);
+   else if (src->File == PROGRAM_TEMPORARY) {
+      if (src->Index >= 32)
+         _mesa_printf("H%d", src->Index);
+      else
+         _mesa_printf("R%d", src->Index);
    }
-   else if ((r = DummyRegisterNumber(src->Register)) >= 0) {
-      _mesa_printf("%cC", "HR"[r]);
+   else if (src->File == PROGRAM_WRITE_ONLY) {
+      _mesa_printf("%cC", "HR"[src->Index]);
    }
    else {
-      _mesa_problem(NULL, "Invalid fragment register %d", src->Register);
+      _mesa_problem(NULL, "Invalid fragment register %d", src->Index);
       return;
    }
    if (src->Swizzle[0] == src->Swizzle[1] &&
@@ -1665,22 +1629,21 @@ PrintDstReg(const struct fp_dst_register *dst)
 {
    GLint w = dst->WriteMask[0] + dst->WriteMask[1]
            + dst->WriteMask[2] + dst->WriteMask[3];
-   GLint r;
 
-   if ((r = OutputRegisterNumber(dst->Register)) >= 0) {
-      _mesa_printf("o[%s]", OutputRegisters[r]);
-   }
-   else if ((r = HalfTempRegisterNumber(dst->Register)) >= 0) {
-      _mesa_printf("H[%s]", InputRegisters[r]);
+   if (dst->File == PROGRAM_OUTPUT) {
+      _mesa_printf("o[%s]", OutputRegisters[dst->Index]);
    }
-   else if ((r = TempRegisterNumber(dst->Register)) >= 0) {
-      _mesa_printf("R%d", r);
+   else if (dst->File == PROGRAM_TEMPORARY) {
+      if (dst->Index >= 32)
+         _mesa_printf("H%d", dst->Index);
+      else
+         _mesa_printf("R%d", dst->Index);
    }
-   else if ((r = ProgramRegisterNumber(dst->Register)) >= 0) {
-      _mesa_printf("p[%d]", r);
+   else if (dst->File == PROGRAM_LOCAL_PARAM) {
+      _mesa_printf("p[%d]", dst->Index);
    }
-   else if ((r = DummyRegisterNumber(dst->Register)) >= 0) {
-      _mesa_printf("%cC", "HR"[r]);
+   else if (dst->File == PROGRAM_WRITE_ONLY) {
+      _mesa_printf("%cC", "HR"[dst->Index]);
    }
    else {
       _mesa_printf("???");
@@ -1747,32 +1710,32 @@ _mesa_print_nv_fragment_program(const struct fragment_program *program)
             /* print source register(s) */
             if (Instructions[i].inputs == INPUT_1V ||
                 Instructions[i].inputs == INPUT_1S) {
-               PrintSrcReg(&inst->SrcReg[0]);
+               PrintSrcReg(program, &inst->SrcReg[0]);
             }
             else if (Instructions[i].inputs == INPUT_2V ||
                      Instructions[i].inputs == INPUT_2S) {
-               PrintSrcReg(&inst->SrcReg[0]);
+               PrintSrcReg(program, &inst->SrcReg[0]);
                _mesa_printf(", ");
-               PrintSrcReg(&inst->SrcReg[1]);
+               PrintSrcReg(program, &inst->SrcReg[1]);
             }
             else if (Instructions[i].inputs == INPUT_3V) {
-               PrintSrcReg(&inst->SrcReg[0]);
+               PrintSrcReg(program, &inst->SrcReg[0]);
                _mesa_printf(", ");
-               PrintSrcReg(&inst->SrcReg[1]);
+               PrintSrcReg(program, &inst->SrcReg[1]);
                _mesa_printf(", ");
-               PrintSrcReg(&inst->SrcReg[2]);
+               PrintSrcReg(program, &inst->SrcReg[2]);
             }
             else if (Instructions[i].inputs == INPUT_1V_T) {
-               PrintSrcReg(&inst->SrcReg[0]);
+               PrintSrcReg(program, &inst->SrcReg[0]);
                _mesa_printf(", ");
                PrintTextureSrc(inst);
             }
             else if (Instructions[i].inputs == INPUT_3V_T) {
-               PrintSrcReg(&inst->SrcReg[0]);
+               PrintSrcReg(program, &inst->SrcReg[0]);
                _mesa_printf(", ");
-               PrintSrcReg(&inst->SrcReg[1]);
+               PrintSrcReg(program, &inst->SrcReg[1]);
                _mesa_printf(", ");
-               PrintSrcReg(&inst->SrcReg[2]);
+               PrintSrcReg(program, &inst->SrcReg[2]);
                _mesa_printf(", ");
                PrintTextureSrc(inst);
             }
@@ -1786,3 +1749,19 @@ _mesa_print_nv_fragment_program(const struct fragment_program *program)
    }
    _mesa_printf("END\n");
 }
+
+
+const char *
+_mesa_nv_fragment_input_register_name(GLuint i)
+{
+   ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_INPUTS);
+   return InputRegisters[i];
+}
+
+
+const char *
+_mesa_nv_fragment_output_register_name(GLuint i)
+{
+   ASSERT(i < MAX_NV_FRAGMENT_PROGRAM_OUTPUTS);
+   return OutputRegisters[i];
+}