ir_to_mesa: Tell Mesa about our choices for vertex attribute locations.
[mesa.git] / src / mesa / shader / nvvertparse.c
index 88fa32c1d494c294efe8a75c4addbcff118d5cef..7332fc4780badd8f820ea5a5abc504cd3ac55529 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.0.1
+ * Version:  6.5.2
  *
- * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  * including any use thereof or modifications thereto.
  */
 
-#include "glheader.h"
-#include "context.h"
-#include "hash.h"
-#include "imports.h"
-#include "macros.h"
-#include "mtypes.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
 #include "nvprogram.h"
 #include "nvvertparse.h"
-#include "nvvertprog.h"
+#include "prog_instruction.h"
+#include "prog_parameter.h"
+#include "prog_print.h"
 #include "program.h"
 
 
@@ -62,8 +61,8 @@ struct parse_state {
    GLboolean isStateProgram;
    GLboolean isPositionInvariant;
    GLboolean isVersion1_1;
-   GLuint inputsRead;
-   GLuint outputsWritten;
+   GLbitfield inputsRead;
+   GLbitfield outputsWritten;
    GLboolean anyProgRegsWritten;
    GLuint numInst;                 /* number of instructions parsed */
 };
@@ -83,7 +82,7 @@ record_error(struct parse_state *parseState, const char *msg, int lineNo)
    _mesa_debug(parseState->ctx,
                "nvfragparse.c(%d): line %d, column %d:%s (%s)\n",
                lineNo, line, column, (char *) lineStr, msg);
-   _mesa_free((void *) lineStr);
+   free((void *) lineStr);
 #else
    (void) lineNo;
 #endif
@@ -112,7 +111,7 @@ do {                                                                        \
 #define RETURN_ERROR2(msg1, msg2)                                      \
 do {                                                                   \
    char err[1000];                                                     \
-   _mesa_sprintf(err, "%s %s", msg1, msg2);                            \
+   sprintf(err, "%s %s", msg1, msg2);                          \
    record_error(parseState, err, __LINE__);                            \
    return GL_FALSE;                                                    \
 } while(0)
@@ -233,7 +232,7 @@ Peek_Token(struct parse_state *parseState, GLubyte *token)
       parseState->pos += (-i);
       return GL_FALSE;
    }
-   len = _mesa_strlen((const char *) token);
+   len = (GLint) strlen((const char *) token);
    parseState->pos += (i - len);
    return GL_TRUE;
 }
@@ -288,18 +287,9 @@ static const char *InputRegisters[MAX_NV_VERTEX_PROGRAM_INPUTS + 1] = {
 };
 
 static const char *OutputRegisters[MAX_NV_VERTEX_PROGRAM_OUTPUTS + 1] = {
-   "HPOS", "COL0", "COL1", "BFC0", "BFC1", "FOGC", "PSIZ",
-   "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", NULL
-};
-
-/* NOTE: the order here must match opcodes in nvvertprog.h */
-static const char *Opcodes[] = {
-   "MOV", "LIT", "RCP", "RSQ", "EXP", "LOG", "MUL", "ADD", "DP3", "DP4",
-   "DST", "MIN", "MAX", "SLT", "SGE", "MAD", "ARL", "DPH", "RCC", "SUB",
-   "ABS", "END",
-   /* GL_ARB_vertex_program */
-   "FLR", "FRC", "EX2", "LG2", "POW", "XPD", "SWZ",
-   NULL
+   "HPOS", "COL0", "COL1", "FOGC", 
+   "TEX0", "TEX1", "TEX2", "TEX3", "TEX4", "TEX5", "TEX6", "TEX7", 
+   "PSIZ", "BFC0", "BFC1", NULL
 };
 
 
@@ -319,7 +309,7 @@ Parse_TempReg(struct parse_state *parseState, GLint *tempRegNum)
       RETURN_ERROR1("Expected R##");
 
    if (IsDigit(token[1])) {
-      GLint reg = _mesa_atoi((char *) (token + 1));
+      GLint reg = atoi((char *) (token + 1));
       if (reg >= MAX_NV_VERTEX_PROGRAM_TEMPS)
          RETURN_ERROR1("Bad temporary register name");
       *tempRegNum = reg;
@@ -373,7 +363,7 @@ Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum)
 
    if (IsDigit(token[0])) {
       /* a numbered program parameter register */
-      GLint reg = _mesa_atoi((char *) token);
+      GLint reg = atoi((char *) token);
       if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
          RETURN_ERROR1("Bad program parameter number");
       *regNum = reg;
@@ -390,7 +380,7 @@ Parse_AbsParamReg(struct parse_state *parseState, GLint *regNum)
 
 
 static GLboolean
-Parse_ParamReg(struct parse_state *parseState, struct vp_src_register *srcReg)
+Parse_ParamReg(struct parse_state *parseState, struct prog_src_register *srcReg)
 {
    GLubyte token[100];
 
@@ -407,13 +397,13 @@ Parse_ParamReg(struct parse_state *parseState, struct vp_src_register *srcReg)
       /* a numbered program parameter register */
       GLint reg;
       (void) Parse_Token(parseState, token);
-      reg = _mesa_atoi((char *) token);
+      reg = atoi((char *) token);
       if (reg >= MAX_NV_VERTEX_PROGRAM_PARAMS)
          RETURN_ERROR1("Bad program parameter number");
       srcReg->File = PROGRAM_ENV_PARAM;
       srcReg->Index = reg;
    }
-   else if (_mesa_strcmp((const char *) token, "A0") == 0) {
+   else if (strcmp((const char *) token, "A0") == 0) {
       /* address register "A0.x" */
       if (!Parse_AddrReg(parseState))
          RETURN_ERROR;
@@ -433,7 +423,7 @@ Parse_ParamReg(struct parse_state *parseState, struct vp_src_register *srcReg)
             RETURN_ERROR;
 
          if (IsDigit(token[0])) {
-            const GLint k = _mesa_atoi((char *) token);
+            const GLint k = atoi((char *) token);
             if (sign == '-') {
                if (k > 64)
                   RETURN_ERROR1("Bad address offset");
@@ -490,14 +480,14 @@ Parse_AttribReg(struct parse_state *parseState, GLint *tempRegNum)
       RETURN_ERROR1("Only v[0] accessible in vertex state programs");
 
    if (IsDigit(token[0])) {
-      GLint reg = _mesa_atoi((char *) token);
+      GLint reg = atoi((char *) token);
       if (reg >= MAX_NV_VERTEX_PROGRAM_INPUTS)
          RETURN_ERROR1("Bad vertex attribute register name");
       *tempRegNum = reg;
    }
    else {
       for (j = 0; InputRegisters[j]; j++) {
-         if (_mesa_strcmp((const char *) token, InputRegisters[j]) == 0) {
+         if (strcmp((const char *) token, InputRegisters[j]) == 0) {
             *tempRegNum = j;
             break;
          }
@@ -541,7 +531,7 @@ Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
 
    /* try to match an output register name */
    for (j = start; OutputRegisters[j]; j++) {
-      if (_mesa_strcmp((const char *) token, OutputRegisters[j]) == 0) {
+      if (strcmp((const char *) token, OutputRegisters[j]) == 0) {
          *outputRegNum = j;
          break;
       }
@@ -558,9 +548,10 @@ Parse_OutputReg(struct parse_state *parseState, GLint *outputRegNum)
 
 
 static GLboolean
-Parse_MaskedDstReg(struct parse_state *parseState, struct vp_dst_register *dstReg)
+Parse_MaskedDstReg(struct parse_state *parseState, struct prog_dst_register *dstReg)
 {
    GLubyte token[100];
+   GLint idx;
 
    /* Dst reg can be R<n> or o[n] */
    if (!Peek_Token(parseState, token))
@@ -569,22 +560,25 @@ Parse_MaskedDstReg(struct parse_state *parseState, struct vp_dst_register *dstRe
    if (token[0] == 'R') {
       /* a temporary register */
       dstReg->File = PROGRAM_TEMPORARY;
-      if (!Parse_TempReg(parseState, &dstReg->Index))
+      if (!Parse_TempReg(parseState, &idx))
          RETURN_ERROR;
+      dstReg->Index = idx;
    }
    else if (!parseState->isStateProgram && token[0] == 'o') {
       /* an output register */
       dstReg->File = PROGRAM_OUTPUT;
-      if (!Parse_OutputReg(parseState, &dstReg->Index))
+      if (!Parse_OutputReg(parseState, &idx))
          RETURN_ERROR;
+      dstReg->Index = idx;
    }
    else if (parseState->isStateProgram && token[0] == 'c' &&
             parseState->isStateProgram) {
       /* absolute program parameter register */
       /* Only valid for vertex state programs */
       dstReg->File = PROGRAM_ENV_PARAM;
-      if (!Parse_AbsParamReg(parseState, &dstReg->Index))
+      if (!Parse_AbsParamReg(parseState, &idx))
          RETURN_ERROR;
+      dstReg->Index = idx;
    }
    else {
       RETURN_ERROR1("Bad destination register name");
@@ -604,25 +598,22 @@ Parse_MaskedDstReg(struct parse_state *parseState, struct vp_dst_register *dstRe
       if (!Parse_Token(parseState, token))
          RETURN_ERROR;
 
-      dstReg->WriteMask[0] = GL_FALSE;
-      dstReg->WriteMask[1] = GL_FALSE;
-      dstReg->WriteMask[2] = GL_FALSE;
-      dstReg->WriteMask[3] = GL_FALSE;
+      dstReg->WriteMask = 0;
 
       if (token[k] == 'x') {
-         dstReg->WriteMask[0] = GL_TRUE;
+         dstReg->WriteMask |= WRITEMASK_X;
          k++;
       }
       if (token[k] == 'y') {
-         dstReg->WriteMask[1] = GL_TRUE;
+         dstReg->WriteMask |= WRITEMASK_Y;
          k++;
       }
       if (token[k] == 'z') {
-         dstReg->WriteMask[2] = GL_TRUE;
+         dstReg->WriteMask |= WRITEMASK_Z;
          k++;
       }
       if (token[k] == 'w') {
-         dstReg->WriteMask[3] = GL_TRUE;
+         dstReg->WriteMask |= WRITEMASK_W;
          k++;
       }
       if (k == 0) {
@@ -631,19 +622,17 @@ Parse_MaskedDstReg(struct parse_state *parseState, struct vp_dst_register *dstRe
       return GL_TRUE;
    }
    else {
-      dstReg->WriteMask[0] = GL_TRUE;
-      dstReg->WriteMask[1] = GL_TRUE;
-      dstReg->WriteMask[2] = GL_TRUE;
-      dstReg->WriteMask[3] = GL_TRUE;
+      dstReg->WriteMask = WRITEMASK_XYZW;
       return GL_TRUE;
    }
 }
 
 
 static GLboolean
-Parse_SwizzleSrcReg(struct parse_state *parseState, struct vp_src_register *srcReg)
+Parse_SwizzleSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
 {
    GLubyte token[100];
+   GLint idx;
 
    srcReg->RelAddr = GL_FALSE;
 
@@ -652,19 +641,20 @@ Parse_SwizzleSrcReg(struct parse_state *parseState, struct vp_src_register *srcR
       RETURN_ERROR;
    if (token[0] == '-') {
       (void) Parse_String(parseState, "-");
-      srcReg->Negate = GL_TRUE;
+      srcReg->Negate = NEGATE_XYZW;
       if (!Peek_Token(parseState, token))
          RETURN_ERROR;
    }
    else {
-      srcReg->Negate = GL_FALSE;
+      srcReg->Negate = NEGATE_NONE;
    }
 
    /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
    if (token[0] == 'R') {
       srcReg->File = PROGRAM_TEMPORARY;
-      if (!Parse_TempReg(parseState, &srcReg->Index))
+      if (!Parse_TempReg(parseState, &idx))
          RETURN_ERROR;
+      srcReg->Index = idx;
    }
    else if (token[0] == 'c') {
       if (!Parse_ParamReg(parseState, srcReg))
@@ -672,18 +662,16 @@ Parse_SwizzleSrcReg(struct parse_state *parseState, struct vp_src_register *srcR
    }
    else if (token[0] == 'v') {
       srcReg->File = PROGRAM_INPUT;
-      if (!Parse_AttribReg(parseState, &srcReg->Index))
+      if (!Parse_AttribReg(parseState, &idx))
          RETURN_ERROR;
+      srcReg->Index = idx;
    }
    else {
       RETURN_ERROR2("Bad source register name", token);
    }
 
    /* init swizzle fields */
-   srcReg->Swizzle[0] = 0;
-   srcReg->Swizzle[1] = 1;
-   srcReg->Swizzle[2] = 2;
-   srcReg->Swizzle[3] = 3;
+   srcReg->Swizzle = SWIZZLE_NOOP;
 
    /* Look for optional swizzle suffix */
    if (!Peek_Token(parseState, token))
@@ -697,28 +685,31 @@ Parse_SwizzleSrcReg(struct parse_state *parseState, struct vp_src_register *srcR
       if (token[1] == 0) {
          /* single letter swizzle */
          if (token[0] == 'x')
-            ASSIGN_4V(srcReg->Swizzle, 0, 0, 0, 0);
+            srcReg->Swizzle = SWIZZLE_XXXX;
          else if (token[0] == 'y')
-            ASSIGN_4V(srcReg->Swizzle, 1, 1, 1, 1);
+            srcReg->Swizzle = SWIZZLE_YYYY;
          else if (token[0] == 'z')
-            ASSIGN_4V(srcReg->Swizzle, 2, 2, 2, 2);
+            srcReg->Swizzle = SWIZZLE_ZZZZ;
          else if (token[0] == 'w')
-            ASSIGN_4V(srcReg->Swizzle, 3, 3, 3, 3);
+            srcReg->Swizzle = SWIZZLE_WWWW;
          else
             RETURN_ERROR1("Expected x, y, z, or w");
       }
       else {
          /* 2, 3 or 4-component swizzle */
          GLint k;
+
+         srcReg->Swizzle = 0;
+
          for (k = 0; token[k] && k < 5; k++) {
             if (token[k] == 'x')
-               srcReg->Swizzle[k] = 0;
+               srcReg->Swizzle |= 0 << (k*3);
             else if (token[k] == 'y')
-               srcReg->Swizzle[k] = 1;
+               srcReg->Swizzle |= 1 << (k*3);
             else if (token[k] == 'z')
-               srcReg->Swizzle[k] = 2;
+               srcReg->Swizzle |= 2 << (k*3);
             else if (token[k] == 'w')
-               srcReg->Swizzle[k] = 3;
+               srcReg->Swizzle |= 3 << (k*3);
             else
                RETURN_ERROR;
          }
@@ -732,9 +723,10 @@ Parse_SwizzleSrcReg(struct parse_state *parseState, struct vp_src_register *srcR
 
 
 static GLboolean
-Parse_ScalarSrcReg(struct parse_state *parseState, struct vp_src_register *srcReg)
+Parse_ScalarSrcReg(struct parse_state *parseState, struct prog_src_register *srcReg)
 {
    GLubyte token[100];
+   GLint idx;
 
    srcReg->RelAddr = GL_FALSE;
 
@@ -742,20 +734,21 @@ Parse_ScalarSrcReg(struct parse_state *parseState, struct vp_src_register *srcRe
    if (!Peek_Token(parseState, token))
       RETURN_ERROR;
    if (token[0] == '-') {
-      srcReg->Negate = GL_TRUE;
+      srcReg->Negate = NEGATE_XYZW;
       (void) Parse_String(parseState, "-"); /* consume '-' */
       if (!Peek_Token(parseState, token))
          RETURN_ERROR;
    }
    else {
-      srcReg->Negate = GL_FALSE;
+      srcReg->Negate = NEGATE_NONE;
    }
 
    /* Src reg can be R<n>, c[n], c[n +/- offset], or a named vertex attrib */
    if (token[0] == 'R') {
       srcReg->File = PROGRAM_TEMPORARY;
-      if (!Parse_TempReg(parseState, &srcReg->Index))
+      if (!Parse_TempReg(parseState, &idx))
          RETURN_ERROR;
+      srcReg->Index = idx;
    }
    else if (token[0] == 'c') {
       if (!Parse_ParamReg(parseState, srcReg))
@@ -763,8 +756,9 @@ Parse_ScalarSrcReg(struct parse_state *parseState, struct vp_src_register *srcRe
    }
    else if (token[0] == 'v') {
       srcReg->File = PROGRAM_INPUT;
-      if (!Parse_AttribReg(parseState, &srcReg->Index))
+      if (!Parse_AttribReg(parseState, &idx))
          RETURN_ERROR;
+      srcReg->Index = idx;
    }
    else {
       RETURN_ERROR2("Bad source register name", token);
@@ -778,21 +772,20 @@ Parse_ScalarSrcReg(struct parse_state *parseState, struct vp_src_register *srcRe
       RETURN_ERROR;
 
    if (token[0] == 'x' && token[1] == 0) {
-      srcReg->Swizzle[0] = 0;
+      srcReg->Swizzle = 0;
    }
    else if (token[0] == 'y' && token[1] == 0) {
-      srcReg->Swizzle[0] = 1;
+      srcReg->Swizzle = 1;
    }
    else if (token[0] == 'z' && token[1] == 0) {
-      srcReg->Swizzle[0] = 2;
+      srcReg->Swizzle = 2;
    }
    else if (token[0] == 'w' && token[1] == 0) {
-      srcReg->Swizzle[0] = 3;
+      srcReg->Swizzle = 3;
    }
    else {
       RETURN_ERROR1("Bad scalar source suffix");
    }
-   srcReg->Swizzle[1] = srcReg->Swizzle[2] = srcReg->Swizzle[3] = 0;
 
    return GL_TRUE;
 }
@@ -800,13 +793,13 @@ Parse_ScalarSrcReg(struct parse_state *parseState, struct vp_src_register *srcRe
 
 static GLint
 Parse_UnaryOpInstruction(struct parse_state *parseState,
-                         struct vp_instruction *inst, enum vp_opcode opcode)
+                         struct prog_instruction *inst,
+                         enum prog_opcode opcode)
 {
-   if (opcode == VP_OPCODE_ABS && !parseState->isVersion1_1)
+   if (opcode == OPCODE_ABS && !parseState->isVersion1_1)
       RETURN_ERROR1("ABS illegal for vertex program 1.0");
 
    inst->Opcode = opcode;
-   inst->StringPos = parseState->curLine - parseState->start;
 
    /* dest reg */
    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
@@ -830,15 +823,15 @@ Parse_UnaryOpInstruction(struct parse_state *parseState,
 
 static GLboolean
 Parse_BiOpInstruction(struct parse_state *parseState,
-                      struct vp_instruction *inst, enum vp_opcode opcode)
+                      struct prog_instruction *inst,
+                      enum prog_opcode opcode)
 {
-   if (opcode == VP_OPCODE_DPH && !parseState->isVersion1_1)
+   if (opcode == OPCODE_DPH && !parseState->isVersion1_1)
       RETURN_ERROR1("DPH illegal for vertex program 1.0");
-   if (opcode == VP_OPCODE_SUB && !parseState->isVersion1_1)
+   if (opcode == OPCODE_SUB && !parseState->isVersion1_1)
       RETURN_ERROR1("SUB illegal for vertex program 1.0");
 
    inst->Opcode = opcode;
-   inst->StringPos = parseState->curLine - parseState->start;
 
    /* dest reg */
    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
@@ -882,10 +875,10 @@ Parse_BiOpInstruction(struct parse_state *parseState,
 
 static GLboolean
 Parse_TriOpInstruction(struct parse_state *parseState,
-                       struct vp_instruction *inst, enum vp_opcode opcode)
+                       struct prog_instruction *inst,
+                       enum prog_opcode opcode)
 {
    inst->Opcode = opcode;
-   inst->StringPos = parseState->curLine - parseState->start;
 
    /* dest reg */
    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
@@ -949,13 +942,13 @@ Parse_TriOpInstruction(struct parse_state *parseState,
 
 static GLboolean
 Parse_ScalarInstruction(struct parse_state *parseState,
-                        struct vp_instruction *inst, enum vp_opcode opcode)
+                        struct prog_instruction *inst,
+                        enum prog_opcode opcode)
 {
-   if (opcode == VP_OPCODE_RCC && !parseState->isVersion1_1)
+   if (opcode == OPCODE_RCC && !parseState->isVersion1_1)
       RETURN_ERROR1("RCC illegal for vertex program 1.0");
 
    inst->Opcode = opcode;
-   inst->StringPos = parseState->curLine - parseState->start;
 
    /* dest reg */
    if (!Parse_MaskedDstReg(parseState, &inst->DstReg))
@@ -978,10 +971,14 @@ Parse_ScalarInstruction(struct parse_state *parseState,
 
 
 static GLboolean
-Parse_AddressInstruction(struct parse_state *parseState, struct vp_instruction *inst)
+Parse_AddressInstruction(struct parse_state *parseState, struct prog_instruction *inst)
 {
-   inst->Opcode = VP_OPCODE_ARL;
-   inst->StringPos = parseState->curLine - parseState->start;
+   inst->Opcode = OPCODE_ARL;
+
+   /* Make ARB_vp backends happy */
+   inst->DstReg.File = PROGRAM_ADDRESS;
+   inst->DstReg.WriteMask = WRITEMASK_X;
+   inst->DstReg.Index = 0;
 
    /* dest A0 reg */
    if (!Parse_AddrReg(parseState))
@@ -1004,12 +1001,11 @@ Parse_AddressInstruction(struct parse_state *parseState, struct vp_instruction *
 
 
 static GLboolean
-Parse_EndInstruction(struct parse_state *parseState, struct vp_instruction *inst)
+Parse_EndInstruction(struct parse_state *parseState, struct prog_instruction *inst)
 {
    GLubyte token[100];
 
-   inst->Opcode = VP_OPCODE_END;
-   inst->StringPos = parseState->curLine - parseState->start;
+   inst->Opcode = OPCODE_END;
 
    /* this should fail! */
    if (Parse_Token(parseState, token))
@@ -1019,10 +1015,103 @@ Parse_EndInstruction(struct parse_state *parseState, struct vp_instruction *inst
 }
 
 
+/**
+ * The PRINT instruction is Mesa-specific and is meant as a debugging aid for
+ * the vertex program developer.
+ * The NV_vertex_program extension grammar is modified as follows:
+ *
+ *  <instruction>        ::= <ARL-instruction>
+ *                         | ...
+ *                         | <PRINT-instruction>
+ *
+ *  <PRINT-instruction>  ::= "PRINT" <string literal>
+ *                         | "PRINT" <string literal> "," <srcReg>
+ *                         | "PRINT" <string literal> "," <dstReg>
+ */
+static GLboolean
+Parse_PrintInstruction(struct parse_state *parseState, struct prog_instruction *inst)
+{
+   const GLubyte *str;
+   GLubyte *msg;
+   GLuint len;
+   GLubyte token[100];
+   struct prog_src_register *srcReg = &inst->SrcReg[0];
+   GLint idx;
+
+   inst->Opcode = OPCODE_PRINT;
+
+   /* The first argument is a literal string 'just like this' */
+   if (!Parse_String(parseState, "'"))
+      RETURN_ERROR;
+
+   str = parseState->pos;
+   for (len = 0; str[len] != '\''; len++) /* find closing quote */
+      ;
+   parseState->pos += len + 1;
+   msg = (GLubyte*) malloc(len + 1);
+
+   memcpy(msg, str, len);
+   msg[len] = 0;
+   inst->Data = msg;
+
+   /* comma */
+   if (Parse_String(parseState, ",")) {
+
+      /* The second argument is a register name */
+      if (!Peek_Token(parseState, token))
+         RETURN_ERROR;
+
+      srcReg->RelAddr = GL_FALSE;
+      srcReg->Negate = NEGATE_NONE;
+      srcReg->Swizzle = SWIZZLE_NOOP;
+
+      /* Register can be R<n>, c[n], c[n +/- offset], a named vertex attrib,
+       * or an o[n] output register.
+       */
+      if (token[0] == 'R') {
+         srcReg->File = PROGRAM_TEMPORARY;
+         if (!Parse_TempReg(parseState, &idx))
+            RETURN_ERROR;
+        srcReg->Index = idx;
+      }
+      else if (token[0] == 'c') {
+         srcReg->File = PROGRAM_ENV_PARAM;
+         if (!Parse_ParamReg(parseState, srcReg))
+            RETURN_ERROR;
+      }
+      else if (token[0] == 'v') {
+         srcReg->File = PROGRAM_INPUT;
+         if (!Parse_AttribReg(parseState, &idx))
+            RETURN_ERROR;
+        srcReg->Index = idx;
+      }
+      else if (token[0] == 'o') {
+         srcReg->File = PROGRAM_OUTPUT;
+         if (!Parse_OutputReg(parseState, &idx))
+            RETURN_ERROR;
+        srcReg->Index = idx;
+      }
+      else {
+         RETURN_ERROR2("Bad source register name", token);
+      }
+   }
+   else {
+      srcReg->File = PROGRAM_UNDEFINED;
+   }
+
+   /* semicolon */
+   if (!Parse_String(parseState, ";"))
+      RETURN_ERROR;
+
+   return GL_TRUE;
+}
+
+
 static GLboolean
 Parse_OptionSequence(struct parse_state *parseState,
-                     struct vp_instruction program[])
+                     struct prog_instruction program[])
 {
+   (void) program;
    while (1) {
       if (!Parse_String(parseState, "OPTION"))
          return GL_TRUE;  /* ok, not an OPTION statement */
@@ -1040,101 +1129,102 @@ Parse_OptionSequence(struct parse_state *parseState,
 
 static GLboolean
 Parse_InstructionSequence(struct parse_state *parseState,
-                          struct vp_instruction program[])
+                          struct prog_instruction program[])
 {
    while (1) {
-      struct vp_instruction *inst = program + parseState->numInst;
+      struct prog_instruction *inst = program + parseState->numInst;
 
       /* Initialize the instruction */
-      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;
+      _mesa_init_instructions(inst, 1);
 
       if (Parse_String(parseState, "MOV")) {
-         if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_MOV))
+         if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_MOV))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "LIT")) {
-         if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_LIT))
+         if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_LIT))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "ABS")) {
-         if (!Parse_UnaryOpInstruction(parseState, inst, VP_OPCODE_ABS))
+         if (!Parse_UnaryOpInstruction(parseState, inst, OPCODE_ABS))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "MUL")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_MUL))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MUL))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "ADD")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_ADD))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_ADD))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "DP3")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_DP3))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP3))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "DP4")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_DP4))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DP4))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "DST")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_DST))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DST))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "MIN")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_MIN))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MIN))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "MAX")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_MAX))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_MAX))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "SLT")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_SLT))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SLT))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "SGE")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_SGE))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SGE))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "DPH")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_DPH))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_DPH))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "SUB")) {
-         if (!Parse_BiOpInstruction(parseState, inst, VP_OPCODE_SUB))
+         if (!Parse_BiOpInstruction(parseState, inst, OPCODE_SUB))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "MAD")) {
-         if (!Parse_TriOpInstruction(parseState, inst, VP_OPCODE_MAD))
+         if (!Parse_TriOpInstruction(parseState, inst, OPCODE_MAD))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "RCP")) {
-         if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_RCP))
+         if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCP))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "RSQ")) {
-         if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_RSQ))
+         if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RSQ))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "EXP")) {
-         if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_EXP))
+         if (!Parse_ScalarInstruction(parseState, inst, OPCODE_EXP))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "LOG")) {
-         if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_LOG))
+         if (!Parse_ScalarInstruction(parseState, inst, OPCODE_LOG))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "RCC")) {
-         if (!Parse_ScalarInstruction(parseState, inst, VP_OPCODE_RCC))
+         if (!Parse_ScalarInstruction(parseState, inst, OPCODE_RCC))
             RETURN_ERROR;
       }
       else if (Parse_String(parseState, "ARL")) {
          if (!Parse_AddressInstruction(parseState, inst))
             RETURN_ERROR;
       }
+      else if (Parse_String(parseState, "PRINT")) {
+         if (!Parse_PrintInstruction(parseState, inst))
+            RETURN_ERROR;
+      }
       else if (Parse_String(parseState, "END")) {
          if (!Parse_EndInstruction(parseState, inst))
             RETURN_ERROR;
@@ -1173,7 +1263,7 @@ Parse_InstructionSequence(struct parse_state *parseState,
 
 static GLboolean
 Parse_Program(struct parse_state *parseState,
-              struct vp_instruction instBuffer[])
+              struct prog_instruction instBuffer[])
 {
    if (parseState->isVersion1_1) {
       if (!Parse_OptionSequence(parseState, instBuffer)) {
@@ -1192,11 +1282,11 @@ Parse_Program(struct parse_state *parseState,
 void
 _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
                               const GLubyte *str, GLsizei len,
-                              struct vertex_program *program)
+                              struct gl_vertex_program *program)
 {
    struct parse_state parseState;
-   struct vp_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS];
-   struct vp_instruction *newInst;
+   struct prog_instruction instBuffer[MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS];
+   struct prog_instruction *newInst;
    GLenum target;
    GLubyte *programString;
 
@@ -1206,7 +1296,7 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
       return;
    }
-   MEMCPY(programString, str, len);
+   memcpy(programString, str, len);
    programString[len] = 0;
 
    /* Get ready to parse */
@@ -1223,18 +1313,18 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
    _mesa_set_program_error(ctx, -1, NULL);
 
    /* check the program header */
-   if (_mesa_strncmp((const char *) programString, "!!VP1.0", 7) == 0) {
+   if (strncmp((const char *) programString, "!!VP1.0", 7) == 0) {
       target = GL_VERTEX_PROGRAM_NV;
       parseState.pos = programString + 7;
       parseState.isStateProgram = GL_FALSE;
    }
-   else if (_mesa_strncmp((const char *) programString, "!!VP1.1", 7) == 0) {
+   else if (strncmp((const char *) programString, "!!VP1.1", 7) == 0) {
       target = GL_VERTEX_PROGRAM_NV;
       parseState.pos = programString + 7;
       parseState.isStateProgram = GL_FALSE;
       parseState.isVersion1_1 = GL_TRUE;
    }
-   else if (_mesa_strncmp((const char *) programString, "!!VSP1.0", 8) == 0) {
+   else if (strncmp((const char *) programString, "!!VSP1.0", 8) == 0) {
       target = GL_VERTEX_STATE_PROGRAM_NV;
       parseState.pos = programString + 8;
       parseState.isStateProgram = GL_TRUE;
@@ -1255,6 +1345,9 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
 
 
    if (Parse_Program(&parseState, instBuffer)) {
+      gl_state_index state_tokens[STATE_LENGTH] = {0, 0, 0, 0, 0};
+      int i;
+
       /* successful parse! */
 
       if (parseState.isStateProgram) {
@@ -1266,7 +1359,7 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
       }
       else {
          if (!parseState.isPositionInvariant &&
-             !(parseState.outputsWritten & 1)) {
+             !(parseState.outputsWritten & (1 << VERT_RESULT_HPOS))) {
             /* bit 1 = HPOS register */
             _mesa_error(ctx, GL_INVALID_OPERATION,
                         "glLoadProgramNV(HPOS not written)");
@@ -1276,37 +1369,61 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
 
       /* copy the compiled instructions */
       assert(parseState.numInst <= MAX_NV_VERTEX_PROGRAM_INSTRUCTIONS);
-      newInst = (struct vp_instruction *)
-         MALLOC(parseState.numInst * sizeof(struct vp_instruction));
+      newInst = _mesa_alloc_instructions(parseState.numInst);
       if (!newInst) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV");
-         FREE(programString);
+         free(programString);
          return;  /* out of memory */
       }
-      MEMCPY(newInst, instBuffer,
-             parseState.numInst * sizeof(struct vp_instruction));
+      _mesa_copy_instructions(newInst, instBuffer, parseState.numInst);
 
       /* install the program */
       program->Base.Target = target;
       if (program->Base.String) {
-         FREE(program->Base.String);
+         free(program->Base.String);
       }
       program->Base.String = programString;
       program->Base.Format = GL_PROGRAM_FORMAT_ASCII_ARB;
-      if (program->Instructions) {
-         FREE(program->Instructions);
+      if (program->Base.Instructions) {
+         free(program->Base.Instructions);
       }
-      program->Instructions = newInst;
-      program->InputsRead = parseState.inputsRead;
-      program->OutputsWritten = parseState.outputsWritten;
+      program->Base.Instructions = newInst;
+      program->Base.InputsRead = parseState.inputsRead;
+      if (parseState.isPositionInvariant)
+         program->Base.InputsRead |= VERT_BIT_POS;
+      program->Base.NumInstructions = parseState.numInst;
+      program->Base.OutputsWritten = parseState.outputsWritten;
       program->IsPositionInvariant = parseState.isPositionInvariant;
       program->IsNVProgram = GL_TRUE;
 
-#ifdef DEBUG
-      _mesa_printf("--- glLoadProgramNV result ---\n");
-      _mesa_print_nv_vertex_program(program);
-      _mesa_printf("------------------------------\n");
+#ifdef DEBUG_foo
+      printf("--- glLoadProgramNV result ---\n");
+      _mesa_fprint_program_opt(stdout, &program->Base, PROG_PRINT_NV, 0);
+      printf("------------------------------\n");
 #endif
+
+      if (program->Base.Parameters)
+        _mesa_free_parameter_list(program->Base.Parameters);
+
+      program->Base.Parameters = _mesa_new_parameter_list ();
+      program->Base.NumParameters = 0;
+
+      state_tokens[0] = STATE_VERTEX_PROGRAM;
+      state_tokens[1] = STATE_ENV;
+      /* Add refs to all of the potential params, in order.  If we want to not
+       * upload everything, _mesa_layout_parameters is the answer.
+       */
+      for (i = 0; i < MAX_NV_VERTEX_PROGRAM_PARAMS; i++) {
+        GLint index;
+        state_tokens[2] = i;
+        index = _mesa_add_state_reference(program->Base.Parameters,
+                                          state_tokens);
+        assert(index == i);
+      }
+      program->Base.NumParameters = program->Base.Parameters->NumParameters;
+
+      _mesa_setup_nv_temporary_count(ctx, &program->Base);
+      _mesa_emit_nv_temp_initialization(ctx, &program->Base);
    }
    else {
       /* Error! */
@@ -1320,167 +1437,6 @@ _mesa_parse_nv_vertex_program(GLcontext *ctx, GLenum dstTarget,
 }
 
 
-static void
-PrintSrcReg(const struct vp_src_register *src)
-{
-   static const char comps[5] = "xyzw";
-   if (src->Negate)
-      _mesa_printf("-");
-   if (src->RelAddr) {
-      if (src->Index > 0)
-         _mesa_printf("c[A0.x + %d]", src->Index);
-      else if (src->Index < 0)
-         _mesa_printf("c[A0.x - %d]", -src->Index);
-      else
-         _mesa_printf("c[A0.x]");
-   }
-   else if (src->File == PROGRAM_OUTPUT) {
-      _mesa_printf("o[%s]", OutputRegisters[src->Index]);
-   }
-   else if (src->File == PROGRAM_INPUT) {
-      _mesa_printf("v[%s]", InputRegisters[src->Index]);
-   }
-   else if (src->File == PROGRAM_ENV_PARAM) {
-      _mesa_printf("c[%d]", src->Index);
-   }
-   else {
-      ASSERT(src->File == PROGRAM_TEMPORARY);
-      _mesa_printf("R%d", src->Index);
-   }
-
-   if (src->Swizzle[0] == src->Swizzle[1] &&
-       src->Swizzle[0] == src->Swizzle[2] &&
-       src->Swizzle[0] == src->Swizzle[3]) {
-      _mesa_printf(".%c", comps[src->Swizzle[0]]);
-   }
-   else if (src->Swizzle[0] != 0 ||
-            src->Swizzle[1] != 1 ||
-            src->Swizzle[2] != 2 ||
-            src->Swizzle[3] != 3) {
-      _mesa_printf(".%c%c%c%c",
-             comps[src->Swizzle[0]],
-             comps[src->Swizzle[1]],
-             comps[src->Swizzle[2]],
-             comps[src->Swizzle[3]]);
-   }
-}
-
-
-static void
-PrintDstReg(const struct vp_dst_register *dst)
-{
-   GLint w = dst->WriteMask[0] + dst->WriteMask[1]
-           + dst->WriteMask[2] + dst->WriteMask[3];
-
-   if (dst->File == PROGRAM_OUTPUT) {
-      _mesa_printf("o[%s]", OutputRegisters[dst->Index]);
-   }
-   else if (dst->File == PROGRAM_INPUT) {
-      _mesa_printf("v[%s]", InputRegisters[dst->Index]);
-   }
-   else if (dst->File == PROGRAM_ENV_PARAM) {
-      _mesa_printf("c[%d]", dst->Index);
-   }
-   else {
-      ASSERT(dst->File == PROGRAM_TEMPORARY);
-      _mesa_printf("R%d", dst->Index);
-   }
-
-   if (w != 0 && w != 4) {
-      _mesa_printf(".");
-      if (dst->WriteMask[0])
-         _mesa_printf("x");
-      if (dst->WriteMask[1])
-         _mesa_printf("y");
-      if (dst->WriteMask[2])
-         _mesa_printf("z");
-      if (dst->WriteMask[3])
-         _mesa_printf("w");
-   }
-}
-
-
-/**
- * Print a single NVIDIA vertex program instruction.
- */
-void
-_mesa_print_nv_vertex_instruction(const struct vp_instruction *inst)
-{
-   switch (inst->Opcode) {
-      case VP_OPCODE_MOV:
-      case VP_OPCODE_LIT:
-      case VP_OPCODE_RCP:
-      case VP_OPCODE_RSQ:
-      case VP_OPCODE_EXP:
-      case VP_OPCODE_LOG:
-      case VP_OPCODE_RCC:
-      case VP_OPCODE_ABS:
-         _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
-         PrintDstReg(&inst->DstReg);
-         _mesa_printf(", ");
-         PrintSrcReg(&inst->SrcReg[0]);
-         _mesa_printf(";\n");
-         break;
-      case VP_OPCODE_MUL:
-      case VP_OPCODE_ADD:
-      case VP_OPCODE_DP3:
-      case VP_OPCODE_DP4:
-      case VP_OPCODE_DST:
-      case VP_OPCODE_MIN:
-      case VP_OPCODE_MAX:
-      case VP_OPCODE_SLT:
-      case VP_OPCODE_SGE:
-      case VP_OPCODE_DPH:
-      case VP_OPCODE_SUB:
-         _mesa_printf("%s ", Opcodes[(int) inst->Opcode]);
-         PrintDstReg(&inst->DstReg);
-         _mesa_printf(", ");
-         PrintSrcReg(&inst->SrcReg[0]);
-         _mesa_printf(", ");
-         PrintSrcReg(&inst->SrcReg[1]);
-         _mesa_printf(";\n");
-         break;
-      case VP_OPCODE_MAD:
-         _mesa_printf("MAD ");
-         PrintDstReg(&inst->DstReg);
-         _mesa_printf(", ");
-         PrintSrcReg(&inst->SrcReg[0]);
-         _mesa_printf(", ");
-         PrintSrcReg(&inst->SrcReg[1]);
-         _mesa_printf(", ");
-         PrintSrcReg(&inst->SrcReg[2]);
-         _mesa_printf(";\n");
-         break;
-      case VP_OPCODE_ARL:
-         _mesa_printf("ARL A0.x, ");
-         PrintSrcReg(&inst->SrcReg[0]);
-         _mesa_printf(";\n");
-         break;
-      case VP_OPCODE_END:
-         _mesa_printf("END\n");
-         break;
-      default:
-         _mesa_printf("BAD INSTRUCTION\n");
-   }
-}
-
-
-/**
- * Print (unparse) the given vertex program.  Just for debugging.
- */
-void
-_mesa_print_nv_vertex_program(const struct vertex_program *program)
-{
-   const struct vp_instruction *inst;
-
-   for (inst = program->Instructions; ; inst++) {
-      _mesa_print_nv_vertex_instruction(inst);
-      if (inst->Opcode == VP_OPCODE_END)
-         return;
-   }
-}
-
-
 const char *
 _mesa_nv_vertex_input_register_name(GLuint i)
 {
@@ -1495,3 +1451,4 @@ _mesa_nv_vertex_output_register_name(GLuint i)
    ASSERT(i < MAX_NV_VERTEX_PROGRAM_OUTPUTS);
    return OutputRegisters[i];
 }
+