more work on DEFINE/DECLARATION statements, symbol tables
authorBrian Paul <brian.paul@tungstengraphics.com>
Sun, 16 Feb 2003 23:07:34 +0000 (23:07 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sun, 16 Feb 2003 23:07:34 +0000 (23:07 +0000)
src/mesa/main/mtypes.h
src/mesa/main/nvfragparse.c
src/mesa/main/nvprogram.c
src/mesa/main/nvprogram.h

index 4c3fb3bbd429c75816e7d7196b6f3bf7ceb14e8e..716bbfcf85cd803431cfef931fe139a42371148e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mtypes.h,v 1.102 2003/01/26 14:37:15 brianp Exp $ */
+/* $Id: mtypes.h,v 1.103 2003/02/16 23:07:34 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -1177,6 +1177,11 @@ struct fp_machine
 struct vp_instruction;
 struct fp_instruction;
 
+struct symbol_table
+{
+   struct symbol *Head;
+};
+
 
 /* Base class for any kind of program object */
 struct program
@@ -1208,6 +1213,7 @@ struct fragment_program
    GLuint InputsRead;     /* Bitmask of which input regs are read */
    GLuint OutputsWritten; /* Bitmask of which output regs are written to */
    GLfloat LocalParams[MAX_NV_FRAGMENT_PROGRAM_PARAMS][4];
+   struct symbol_table SymbolTable;
 };
 
 
index 05d0ac5452ea7bb23d5bc7b3a7f5310c3452424d..7b9208d52118bcbfea091f08c7e79a8a45b7b8b7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: nvfragparse.c,v 1.3 2003/02/08 15:56:34 brianp Exp $ */
+/* $Id: nvfragparse.c,v 1.4 2003/02/16 23:07:35 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -142,14 +142,18 @@ static const struct instruction_pattern Instructions[] = {
 /**********************************************************************/
 
 
+/* XXX not used yet */
 struct parse_state {
    const GLubyte *start;    /* start of program */
    const GLubyte *end;      /* one char past end of the program */
    const GLubyte *s;        /* current position */
    GLboolean IsStateProgram;
    GLboolean IsVersion1_1;
+   struct fragment_program *currentProgram;
 };
 
+/* XXX temporary hack */
+static struct fragment_program *CurrentProgram = NULL;
 
 
 /*
@@ -476,13 +480,13 @@ Parse_Identifier(const char **s, char *ident)
 
 
 /**
- * Parse a floating point constant.
+ * Parse a floating point constant, or a defined symbol name.
  * [+/-]N[.N[eN]]
  */
 static GLboolean
 Parse_ScalarConstant(const char **s, GLfloat *number)
 {
-   char *end;
+   char *end = NULL;
 
    *number = (GLfloat) _mesa_strtod(*s, &end);
 
@@ -496,8 +500,9 @@ Parse_ScalarConstant(const char **s, GLfloat *number)
       char ident[100];
       if (!Parse_Identifier(s, ident))
          PARSE_ERROR1("Expected an identifier");
-      /* XXX Look up the value in the symbol table */
-      *number = -999;
+      if (!_mesa_lookup_symbol(&(CurrentProgram->SymbolTable), ident, number)) {
+         PARSE_ERROR1("Undefined symbol");
+      }
       return GL_TRUE;
    }
 }
@@ -571,7 +576,11 @@ Parse_VectorConstant(const char **s, GLfloat *vec)
 }
 
 
-static GLboolean
+/**
+ * Parse <number>, <varname> or {a, b, c, d}.
+ * Return number of values in the vector or scalar, or zero if parse error.
+ */
+static GLuint
 Parse_VectorOrScalarConstant(const char **s, GLfloat *vec)
 {
    char token[100];
@@ -1082,7 +1091,8 @@ Parse_ScalarSrcReg(const char **s, struct fp_src_register *srcReg)
 
 
 static GLboolean
-Parse_InstructionSequence(const char **s, struct fp_instruction program[])
+Parse_InstructionSequence(struct fragment_program *fragProg,
+                          const char **s, struct fp_instruction program[])
 {
    char token[100];
    GLint count = 0;
@@ -1107,19 +1117,22 @@ Parse_InstructionSequence(const char **s, struct fp_instruction program[])
       /* special instructions */
       if (StrEq(token, "DEFINE")) {
          char id[100];
-         GLfloat value[4];
+         GLfloat value[7];  /* yes, 7 to be safe */
          if (!Parse_Identifier(s, id))
             PARSE_ERROR;
          if (!Parse_String(s, "="))
             PARSE_ERROR1("Expected = symbol");
          if (!Parse_VectorOrScalarConstant(s, value))
             PARSE_ERROR;
+         if (!Parse_String(s, ";"))
+            PARSE_ERROR1("Expected ;");
          printf("Parsed DEFINE %s = %f %f %f %f\n", id, value[0], value[1],
                 value[2], value[3]);
+         _mesa_add_symbol(&(fragProg->SymbolTable), id, Definition, value);
       }
       else if (StrEq(token, "DECLARE")) {
          char id[100];
-         GLfloat value[4];
+         GLfloat value[7] = {0, 0, 0, 0, 0, 0, 0};  /* yes, to be safe */
          if (!Parse_Identifier(s, id))
             PARSE_ERROR;
          if (!Peek_Token(s, token))
@@ -1128,128 +1141,128 @@ Parse_InstructionSequence(const char **s, struct fp_instruction program[])
             Parse_String(s, "=");
             if (!Parse_VectorOrScalarConstant(s, value))
                PARSE_ERROR;
-            printf("Parsed DECLARE %s = %f %f %f %f\n", id, value[0], value[1],
-                   value[2], value[3]);
+            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(s, ";"))
+            PARSE_ERROR1("Expected ;");
+         _mesa_add_symbol(&(fragProg->SymbolTable), id, Declaration, value);
       }
+      else {
+         /* arithmetic instruction */
+
+         /* try to find matching instuction */
+         instMatch = MatchInstruction(token);
+         if (instMatch.opcode < 0) {
+            /* bad instruction name */
+            printf("-------- errror\n");
+            PARSE_ERROR2("Unexpected token: ", token);
+         }
 
-      /* try to find matching instuction */
-      instMatch = MatchInstruction(token);
-      if (instMatch.opcode < 0) {
-         /* bad instruction name */
-         PARSE_ERROR2("Unexpected token: ", token);
-      }
-
-      inst->Opcode = instMatch.opcode;
-      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->Opcode = instMatch.opcode;
+         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;
 
-      /*
-       * parse the input and output operands
-       */
-      if (instMatch.outputs == OUTPUT_S || instMatch.outputs == OUTPUT_V) {
-         if (!Parse_MaskedDstReg(s, &inst->DstReg))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-      }
-      else if (instMatch.outputs == OUTPUT_NONE) {
-         ASSERT(instMatch.opcode == FP_OPCODE_KIL);
-         /* This is a little weird, the cond code info is in the dest register */
-         if (!Parse_CondCodeMask(s, &inst->DstReg))
-            PARSE_ERROR;
-      }
+         /*
+          * parse the input and output operands
+          */
+         if (instMatch.outputs == OUTPUT_S || instMatch.outputs == OUTPUT_V) {
+            if (!Parse_MaskedDstReg(s, &inst->DstReg))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+         }
+         else if (instMatch.outputs == OUTPUT_NONE) {
+            ASSERT(instMatch.opcode == FP_OPCODE_KIL);
+            /* This is a little weird, the cond code info is in the dest register */
+            if (!Parse_CondCodeMask(s, &inst->DstReg))
+               PARSE_ERROR;
+         }
 
-      if (instMatch.inputs == INPUT_1V) {
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
-            PARSE_ERROR;
-      }
-      else if (instMatch.inputs == INPUT_2V) {
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
-            PARSE_ERROR;
-      }
-      else if (instMatch.inputs == INPUT_3V) {
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
-            PARSE_ERROR;
-      }
-      else if (instMatch.inputs == INPUT_1S) {
-         if (!Parse_ScalarSrcReg(s, &inst->SrcReg[1]))
-            PARSE_ERROR;
-      }
-      else if (instMatch.inputs == INPUT_2S) {
-         if (!Parse_ScalarSrcReg(s, &inst->SrcReg[0]))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-         if (!Parse_ScalarSrcReg(s, &inst->SrcReg[1]))
-            PARSE_ERROR;
-      }
-      else if (instMatch.inputs == INPUT_CC) {
+         if (instMatch.inputs == INPUT_1V) {
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
+               PARSE_ERROR;
+         }
+         else if (instMatch.inputs == INPUT_2V) {
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
+               PARSE_ERROR;
+         }
+         else if (instMatch.inputs == INPUT_3V) {
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
+               PARSE_ERROR;
+         }
+         else if (instMatch.inputs == INPUT_1S) {
+            if (!Parse_ScalarSrcReg(s, &inst->SrcReg[1]))
+               PARSE_ERROR;
+         }
+         else if (instMatch.inputs == INPUT_2S) {
+            if (!Parse_ScalarSrcReg(s, &inst->SrcReg[0]))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+            if (!Parse_ScalarSrcReg(s, &inst->SrcReg[1]))
+               PARSE_ERROR;
+         }
+         else if (instMatch.inputs == INPUT_CC) {
 #if 00
-         if (!ParseCondCodeSrc(s, &inst->srcReg[0]))
-            PARSE_ERROR;
+            if (!ParseCondCodeSrc(s, &inst->srcReg[0]))
+               PARSE_ERROR;
 #endif
-      }
-      else if (instMatch.inputs == INPUT_1V_T) {
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-         if (!Parse_TextureImageId(s, &inst->TexSrcUnit, &inst->TexSrcTarget))
-            PARSE_ERROR;
-      }
-      else if (instMatch.inputs == INPUT_1V_T) {
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-         if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[2]))
-            PARSE_ERROR;
-         if (!Parse_String(s, ","))
-            PARSE_ERROR;
-         if (!Parse_TextureImageId(s, &inst->TexSrcUnit, &inst->TexSrcTarget))
-            PARSE_ERROR;
-      }
+         }
+         else if (instMatch.inputs == INPUT_1V_T) {
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+            if (!Parse_TextureImageId(s, &inst->TexSrcUnit, &inst->TexSrcTarget))
+               PARSE_ERROR;
+         }
+         else if (instMatch.inputs == INPUT_1V_T) {
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[0]))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[1]))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+            if (!Parse_SwizzleSrcReg(s, &inst->SrcReg[2]))
+               PARSE_ERROR;
+            if (!Parse_String(s, ","))
+               PARSE_ERROR;
+            if (!Parse_TextureImageId(s, &inst->TexSrcUnit, &inst->TexSrcTarget))
+               PARSE_ERROR;
+         }
 
-      /* end of statement semicolon */
-      if (!Parse_String(s, ";"))
-         PARSE_ERROR;
+         /* end of statement semicolon */
+         if (!Parse_String(s, ";"))
+            PARSE_ERROR;
 
-      count++;
-      if (count >= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS)
-         PARSE_ERROR1("Program too long");
+         count++;
+         if (count >= MAX_NV_FRAGMENT_PROGRAM_INSTRUCTIONS)
+            PARSE_ERROR1("Program too long");
+      }
    }
    return GL_TRUE;
 }
 
 
-static GLboolean
-Parse_Program(const char **s, struct fp_instruction instBuffer[])
-{
-   return Parse_InstructionSequence(s, instBuffer);
-}
-
-
 /**
  * Parse/compile the 'str' returning the compiled 'program'.
  * ctx->Program.ErrorPos will be -1 if successful.  Otherwise, ErrorPos
@@ -1297,7 +1310,10 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
       return;
    }
 
-   if (Parse_Program(&s, instBuffer)) {
+   /* XXX temporary */
+   CurrentProgram = program;
+
+   if (Parse_InstructionSequence(program, &s, instBuffer)) {
       GLuint numInst;
       GLuint strLen;
       GLuint inputsRead = 0;
@@ -1323,10 +1339,10 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
          if ((r = InputRegisterNumber(srcReg0)) >= 0
              && !instBuffer[numInst].SrcReg[0].RelAddr)
             inputsRead |= (1 << r);
-         if ((r = InputRegisterNumber(srcReg1) >= 0
+         if ((r = InputRegisterNumber(srcReg1)) >= 0
              && !instBuffer[numInst].SrcReg[1].RelAddr)
             inputsRead |= (1 << r);
-         if ((r = InputRegisterNumber(srcReg2) >= 0
+         if ((r = InputRegisterNumber(srcReg2)) >= 0
              && !instBuffer[numInst].SrcReg[2].RelAddr)
             inputsRead |= (1 << r);
 #endif
@@ -1367,6 +1383,9 @@ _mesa_parse_nv_fragment_program(GLcontext *ctx, GLenum dstTarget,
       }
       program->Instructions = newInst;
 
+      /* allocate registers for declared program parameters */
+      _mesa_assign_program_registers(&(program->SymbolTable));
+
 #ifdef DEBUG
       _mesa_printf("--- glLoadProgramNV result ---\n");
       _mesa_print_nv_fragment_program(program);
index d09e7afbeee490ba2c651032c0cea82f42ffb5bf..b6960c0df8abfdcbf232a7e0321816856ea8d01d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: nvprogram.c,v 1.2 2003/02/10 20:31:11 alanh Exp $ */
+/* $Id: nvprogram.c,v 1.3 2003/02/16 23:07:36 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
 #include "nvprogram.h"
 
 
+/**
+ * Symbol table entry.
+ * Used for named program parameters.
+ */
+struct symbol
+{
+   const char *Name;
+   enum symbol_type Type;
+   GLfloat Value[4];
+   GLuint Register;
+   struct symbol *Next;
+};
+
+
+
+void
+_mesa_add_symbol(struct symbol_table *symbolTable,
+                 const char *name, enum symbol_type type, const GLfloat *value)
+{
+   struct symbol *s = MALLOC_STRUCT(symbol);
+   if (s) {
+      s->Name = _mesa_strdup(name);
+      s->Type = type;
+      s->Value[0] = value[0];
+      s->Value[1] = value[1];
+      s->Value[2] = value[2];
+      s->Value[3] = value[3];
+      s->Next = symbolTable->Head;
+      symbolTable->Head = s;
+   }
+}
+
+
+GLboolean
+_mesa_lookup_symbol(const struct symbol_table *symbolTable,
+                    const char *name, GLfloat *value)
+{
+   const struct symbol *s;
+   for (s = symbolTable->Head; s; s = s->Next) {
+      if (_mesa_strcmp(s->Name, name) == 0) {
+         value[0] = s->Value[0];
+         value[1] = s->Value[1];
+         value[2] = s->Value[2];
+         value[3] = s->Value[3];
+         return GL_TRUE;
+      }
+   }
+   printf("lookup %s failed\n", name);
+   return GL_FALSE;
+}
+
+
+static GLint
+_mesa_lookup_program_register(const struct symbol_table *symbolTable,
+                              GLsizei len, const GLubyte *name)
+{
+   const struct symbol *s;
+   for (s = symbolTable->Head; s; s = s->Next) {
+      if (_mesa_strcmp(s->Name, (const char *) name) == 0 &&
+          _mesa_strlen(s->Name) == len) {
+         return s->Register;
+      }
+   }
+   return -1;
+}
+
+
+void
+_mesa_assign_program_registers(struct symbol_table *symbolTable)
+{
+   struct symbol *s;
+   GLuint reg = 0;
+   for (s = symbolTable->Head; s; s = s->Next) {
+      if (s->Type == Declaration) {
+         s->Register = reg++;
+      }
+   }
+}
+
+
 
 /**
  * Set the vertex/fragment program error state (position and error string).
@@ -984,20 +1064,13 @@ _mesa_TrackMatrixNV(GLenum target, GLuint address,
 }
 
 
-static GLfloat *
-lookup_program_parameter(struct fragment_program *fprog,
-                         GLsizei len, const GLubyte *name)
-{
-   return NULL;
-}
-
-
 void
 glProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
                             GLfloat x, GLfloat y, GLfloat z, GLfloat w)
 {
    struct program *prog;
-   GLfloat *p;
+   struct fragment_program *fragProg;
+   GLint reg;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
@@ -1012,16 +1085,17 @@ glProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name,
       return;
    }
 
-   p = lookup_program_parameter((struct fragment_program *) prog, len, name);
-   if (!p) {
+   fragProg = (struct fragment_program *) prog;
+   reg = _mesa_lookup_program_register(&(fragProg->SymbolTable), len, name);
+   if (reg < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV");
       return;
    }
 
-   p[0] = x;
-   p[1] = y;
-   p[2] = z;
-   p[3] = w;
+   fragProg->LocalParams[reg][0] = x;
+   fragProg->LocalParams[reg][1] = y;
+   fragProg->LocalParams[reg][2] = z;
+   fragProg->LocalParams[reg][3] = w;
 }
 
 
@@ -1056,7 +1130,8 @@ glGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
                                GLfloat *params)
 {
    struct program *prog;
-   const GLfloat *p;
+   struct fragment_program *fragProg;
+   GLint reg;
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
@@ -1071,16 +1146,17 @@ glGetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name,
       return;
    }
 
-   p = lookup_program_parameter((struct fragment_program *) prog, len, name);
-   if (!p) {
+   fragProg = (struct fragment_program *) prog;
+   reg = _mesa_lookup_program_register(&(fragProg->SymbolTable), len, name);
+   if (reg < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV");
       return;
    }
 
-   params[0] = p[0];
-   params[1] = p[1];
-   params[2] = p[2];
-   params[3] = p[3];
+   params[0] = fragProg->LocalParams[reg][0];
+   params[1] = fragProg->LocalParams[reg][1];
+   params[2] = fragProg->LocalParams[reg][2];
+   params[3] = fragProg->LocalParams[reg][3];
 }
 
 
index 3ede70572209f536b02127c6060a7931877d8bc1..5d31ebba3bf9b9705b9b38fe9ede654b7476464d 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: nvprogram.h,v 1.1 2003/01/14 04:55:46 brianp Exp $ */
+/* $Id: nvprogram.h,v 1.2 2003/02/16 23:07:36 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
  * Version:  5.1
  *
- * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2003  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"),
 #define NVPROGRAM_H
 
 
+enum symbol_type
+{
+   Definition,
+   Declaration
+};
+
+
+extern void
+_mesa_add_symbol(struct symbol_table *symbolTable,
+                 const char *name, enum symbol_type type,
+                 const GLfloat *value);
+
+extern GLboolean
+_mesa_lookup_symbol(const struct symbol_table *symbolTable,
+                    const char *name, GLfloat *value);
+
+extern void
+_mesa_assign_program_registers(struct symbol_table *symbolTable);
+
+
 extern void
 _mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string);