tgsi: Parse DCL statements.
authorMichal Krol <michal@tungstengraphics.com>
Sun, 13 Jul 2008 09:37:36 +0000 (11:37 +0200)
committerMichal Krol <michal@tungstengraphics.com>
Sun, 13 Jul 2008 11:17:32 +0000 (13:17 +0200)
src/gallium/auxiliary/tgsi/util/tgsi_text.c

index bb365d1efe96f15c8a97e319a6f81791a934a931..03c9217243620942511962cb935ff43e4723415c 100644 (file)
@@ -49,6 +49,21 @@ static boolean is_digit_alpha_underscore( const char *cur )
    return is_digit( cur ) || is_alpha_underscore( cur );
 }
 
+static boolean str_match_no_case( const char **pcur, const char *str )
+{
+   const char *cur = *pcur;
+
+   while (*str != '\0' && *str == toupper( *cur )) {
+      str++;
+      cur++;
+   }
+   if (*str == '\0') {
+      *pcur = cur;
+      return TRUE;
+   }
+   return FALSE;
+}
+
 /* Eat zero or more whitespaces.
  */
 static void eat_opt_white( const char **pcur )
@@ -110,28 +125,14 @@ static boolean parse_header( struct translate_ctx *ctx )
 {
    uint processor;
 
-   if (ctx->cur[0] == 'F' && ctx->cur[1] == 'R' && ctx->cur[2] == 'A' && ctx->cur[3] == 'G') {
-      ctx->cur += 4;
+   if (str_match_no_case( &ctx->cur, "FRAG1.1" ))
       processor = TGSI_PROCESSOR_FRAGMENT;
-   }
-   else if (ctx->cur[0] == 'V' && ctx->cur[1] == 'E' && ctx->cur[2] == 'R' && ctx->cur[3] == 'T') {
-      ctx->cur += 4;
+   else if (str_match_no_case( &ctx->cur, "VERT1.1" ))
       processor = TGSI_PROCESSOR_VERTEX;
-   }
-   else if (ctx->cur[0] == 'G' && ctx->cur[1] == 'E' && ctx->cur[2] == 'O' && ctx->cur[3] == 'M') {
-      ctx->cur += 4;
+   else if (str_match_no_case( &ctx->cur, "GEOM1.1" ))
       processor = TGSI_PROCESSOR_GEOMETRY;
-   }
-   else {
-      report_error( ctx, "Unknown processor type" );
-      return FALSE;
-   }
-
-   if (ctx->cur[0] == '1' && ctx->cur[1] == '.' && ctx->cur[2] == '1') {
-      ctx->cur += 3;
-   }
    else {
-      report_error( ctx, "Unknown version" );
+      report_error( ctx, "Unknown header" );
       return FALSE;
    }
 
@@ -187,16 +188,13 @@ parse_file(
 
    for (i = 0; i < TGSI_FILE_COUNT; i++) {
       const char *cur = ctx->cur;
-      const char *name = file_names[i];
 
-      while (*name != '\0' && *name == toupper( *cur )) {
-         name++;
-         cur++;
-      }
-      if (*name == '\0' && !is_digit_alpha_underscore( cur )) {
-         ctx->cur = cur;
-         *file = i;
-         return TRUE;
+      if (str_match_no_case( &cur, file_names[i] )) {
+         if (!is_digit_alpha_underscore( cur )) {
+            ctx->cur = cur;
+            *file = i;
+            return TRUE;
+         }
       }
    }
    report_error( ctx, "Unknown register file" );
@@ -204,7 +202,53 @@ parse_file(
 }
 
 static boolean
-parse_register(
+parse_opt_writemask(
+   struct translate_ctx *ctx,
+   uint *writemask )
+{
+   const char *cur;
+
+   cur = ctx->cur;
+   eat_opt_white( &cur );
+   if (*cur == '.') {
+      cur++;
+      *writemask = TGSI_WRITEMASK_NONE;
+      eat_opt_white( &cur );
+      if (toupper( *cur ) == 'X') {
+         cur++;
+         *writemask |= TGSI_WRITEMASK_X;
+      }
+      if (toupper( *cur ) == 'Y') {
+         cur++;
+         *writemask |= TGSI_WRITEMASK_Y;
+      }
+      if (toupper( *cur ) == 'Z') {
+         cur++;
+         *writemask |= TGSI_WRITEMASK_Z;
+      }
+      if (toupper( *cur ) == 'W') {
+         cur++;
+         *writemask |= TGSI_WRITEMASK_W;
+      }
+
+      if (*writemask == TGSI_WRITEMASK_NONE) {
+         report_error( ctx, "Writemask expected" );
+         return FALSE;
+      }
+
+      ctx->cur = cur;
+   }
+   else {
+      *writemask = TGSI_WRITEMASK_XYZW;
+   }
+   return TRUE;
+}
+
+/* Parse register part common for decls and operands.
+ *    <register_prefix> ::= <file> `[' <index>
+ */
+static boolean
+parse_register_prefix(
    struct translate_ctx *ctx,
    uint *file,
    uint *index )
@@ -222,6 +266,20 @@ parse_register(
       report_error( ctx, "Expected literal integer" );
       return FALSE;
    }
+   return TRUE;
+}
+
+/* Parse register operand.
+ *    <register> ::= <register_prefix> `]'
+ */
+static boolean
+parse_register(
+   struct translate_ctx *ctx,
+   uint *file,
+   uint *index )
+{
+   if (!parse_register_prefix( ctx, file, index ))
+      return FALSE;
    eat_opt_white( &ctx->cur );
    if (*ctx->cur != ']') {
       report_error( ctx, "Expected `]'" );
@@ -232,54 +290,55 @@ parse_register(
    return TRUE;
 }
 
+/* Parse register declaration.
+ *    <register> ::= <register_prefix> `]' | <register_prefix> `..' <index> `]'
+ */
+static boolean
+parse_register_dcl(
+   struct translate_ctx *ctx,
+   uint *file,
+   uint *first,
+   uint *last )
+{
+   if (!parse_register_prefix( ctx, file, first ))
+      return FALSE;
+   eat_opt_white( &ctx->cur );
+   if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
+      ctx->cur += 2;
+      eat_opt_white( &ctx->cur );
+      if (!parse_uint( &ctx->cur, last )) {
+         report_error( ctx, "Expected literal integer" );
+         return FALSE;
+      }
+      eat_opt_white( &ctx->cur );
+   }
+   else {
+      *last = *first;
+   }
+   if (*ctx->cur != ']') {
+      report_error( ctx, "Expected `]' or `..'" );
+      return FALSE;
+   }
+   ctx->cur++;
+   return TRUE;
+}
+
 static boolean
 parse_dst_operand(
    struct translate_ctx *ctx,
    struct tgsi_full_dst_register *dst )
 {
-   const char *cur;
    uint file;
    uint index;
+   uint writemask;
 
    if (!parse_register( ctx, &file, &index ))
       return FALSE;
+   if (!parse_opt_writemask( ctx, &writemask ))
+      return FALSE;
    dst->DstRegister.File = file;
    dst->DstRegister.Index = index;
-
-   /* Parse optional write mask.
-    */
-   cur = ctx->cur;
-   eat_opt_white( &cur );
-   if (*cur == '.') {
-      uint writemask = TGSI_WRITEMASK_NONE;
-
-      cur++;
-      eat_opt_white( &cur );
-      if (toupper( *cur ) == 'X') {
-         cur++;
-         writemask |= TGSI_WRITEMASK_X;
-      }
-      if (toupper( *cur ) == 'Y') {
-         cur++;
-         writemask |= TGSI_WRITEMASK_Y;
-      }
-      if (toupper( *cur ) == 'Z') {
-         cur++;
-         writemask |= TGSI_WRITEMASK_Z;
-      }
-      if (toupper( *cur ) == 'W') {
-         cur++;
-         writemask |= TGSI_WRITEMASK_W;
-      }
-
-      if (writemask == TGSI_WRITEMASK_NONE) {
-         report_error( ctx, "Writemask expected" );
-         return FALSE;
-      }
-
-      dst->DstRegister.WriteMask = writemask;
-      ctx->cur = cur;
-   }
+   dst->DstRegister.WriteMask = writemask;
    return TRUE;
 }
 
@@ -478,15 +537,10 @@ static boolean parse_instruction( struct translate_ctx *ctx )
    eat_opt_white( &ctx->cur );
    for (i = 0; i < TGSI_OPCODE_LAST; i++) {
       const char *cur = ctx->cur;
-      const char *op = opcode_info[i].mnemonic;
 
-      while (*op != '\0' && *op == toupper( *cur )) {
-         op++;
-         cur++;
-      }
-      if (*op == '\0') {
+      if (str_match_no_case( &cur, opcode_info[i].mnemonic )) {
          /* TODO: _SAT suffix */
-         if (*cur == '\0' || eat_white( &cur )) {
+         if (eat_white( &cur )) {
             ctx->cur = cur;
             break;
          }
@@ -525,7 +579,6 @@ static boolean parse_instruction( struct translate_ctx *ctx )
             return FALSE;
       }
    }
-   eat_opt_white( &ctx->cur );
 
    advance = tgsi_build_full_instruction(
       &inst,
@@ -539,22 +592,151 @@ static boolean parse_instruction( struct translate_ctx *ctx )
    return TRUE;
 }
 
+static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
+{
+   "POSITION",
+   "COLOR",
+   "BCOLOR",
+   "FOG",
+   "PSIZE",
+   "GENERIC",
+   "NORMAL"
+};
+
+static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
+{
+   "CONSTANT",
+   "LINEAR",
+   "PERSPECTIVE"
+};
+
+static boolean parse_declaration( struct translate_ctx *ctx )
+{
+   struct tgsi_full_declaration decl;
+   uint file;
+   uint first;
+   uint last;
+   uint writemask;
+   const char *cur;
+   uint advance;
+
+   if (!eat_white( &ctx->cur )) {
+      report_error( ctx, "Syntax error" );
+      return FALSE;
+   }
+   if (!parse_register_dcl( ctx, &file, &first, &last ))
+      return FALSE;
+   if (!parse_opt_writemask( ctx, &writemask ))
+      return FALSE;
+
+   decl = tgsi_default_full_declaration();
+   decl.Declaration.File = file;
+   decl.Declaration.UsageMask = writemask;
+   decl.DeclarationRange.First = first;
+   decl.DeclarationRange.Last = last;
+
+   cur = ctx->cur;
+   eat_opt_white( &cur );
+   if (*cur == ',') {
+      uint i;
+
+      cur++;
+      eat_opt_white( &cur );
+      for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
+         if (str_match_no_case( &cur, semantic_names[i] )) {
+            const char *cur2 = cur;
+            uint index;
+
+            if (is_digit_alpha_underscore( cur ))
+               continue;
+            eat_opt_white( &cur2 );
+            if (*cur2 == '[') {
+               cur2++;
+               eat_opt_white( &cur2 );
+               if (!parse_uint( &cur2, &index )) {
+                  report_error( ctx, "Expected literal integer" );
+                  return FALSE;
+               }
+               eat_opt_white( &cur2 );
+               if (*cur2 != ']') {
+                  report_error( ctx, "Expected `]'" );
+                  return FALSE;
+               }
+               cur2++;
+
+               decl.Semantic.SemanticIndex = index;
+
+               cur = cur2;
+            }
+
+            decl.Declaration.Semantic = 1;
+            decl.Semantic.SemanticName = i;
+
+            ctx->cur = cur;
+            break;
+         }
+      }
+   }
+
+   cur = ctx->cur;
+   eat_opt_white( &cur );
+   if (*cur == ',') {
+      uint i;
+
+      cur++;
+      eat_opt_white( &cur );
+      for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
+         if (str_match_no_case( &cur, interpolate_names[i] )) {
+            if (is_digit_alpha_underscore( cur ))
+               continue;
+            decl.Declaration.Interpolate = i;
+
+            ctx->cur = cur;
+            break;
+         }
+      }
+      if (i == TGSI_INTERPOLATE_COUNT) {
+         report_error( ctx, "Expected semantic or interpolate attribute" );
+         return FALSE;
+      }
+   }
+
+   advance = tgsi_build_full_declaration(
+      &decl,
+      ctx->tokens_cur,
+      ctx->header,
+      (uint) (ctx->tokens_end - ctx->tokens_cur) );
+   if (advance == 0)
+      return FALSE;
+   ctx->tokens_cur += advance;
+
+   return TRUE;
+}
+
 static boolean translate( struct translate_ctx *ctx )
 {
    eat_opt_white( &ctx->cur );
    if (!parse_header( ctx ))
       return FALSE;
 
-   eat_white( &ctx->cur );
    while (*ctx->cur != '\0') {
       uint label_val = 0;
 
+      if (!eat_white( &ctx->cur )) {
+         report_error( ctx, "Syntax error" );
+         return FALSE;
+      }
+
       if (parse_label( ctx, &label_val )) {
          if (!parse_instruction( ctx ))
             return FALSE;
       }
+      else if (str_match_no_case( &ctx->cur, "DCL" )) {
+         if (!parse_declaration( ctx ))
+            return FALSE;
+      }
       else {
-         report_error( ctx, "Instruction expected" );
+         report_error( ctx, "Expected `DCL' or a label" );
          return FALSE;
       }
    }