Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "util/u_debug.h"
  29. #include "util/u_memory.h"
  30. #include "util/u_prim.h"
  31. #include "pipe/p_defines.h"
  32. #include "util/u_inlines.h"
  33. #include "tgsi_text.h"
  34. #include "tgsi_build.h"
  35. #include "tgsi_info.h"
  36. #include "tgsi_parse.h"
  37. #include "tgsi_sanity.h"
  38. #include "tgsi_strings.h"
  39. #include "tgsi_util.h"
  40. #include "tgsi_dump.h"
  41.  
  42. static boolean is_alpha_underscore( const char *cur )
  43. {
  44.    return
  45.       (*cur >= 'a' && *cur <= 'z') ||
  46.       (*cur >= 'A' && *cur <= 'Z') ||
  47.       *cur == '_';
  48. }
  49.  
  50. static boolean is_digit( const char *cur )
  51. {
  52.    return *cur >= '0' && *cur <= '9';
  53. }
  54.  
  55. static boolean is_digit_alpha_underscore( const char *cur )
  56. {
  57.    return is_digit( cur ) || is_alpha_underscore( cur );
  58. }
  59.  
  60. static char uprcase( char c )
  61. {
  62.    if (c >= 'a' && c <= 'z')
  63.       return c + 'A' - 'a';
  64.    return c;
  65. }
  66.  
  67. /*
  68.  * Ignore case of str1 and assume str1 is already uppercase.
  69.  * Return TRUE iff str1 and str2 are equal.
  70.  */
  71. static int
  72. streq_nocase_uprcase(const char *str1,
  73.                      const char *str2)
  74. {
  75.    while (*str1 && *str2) {
  76.       if (*str1 != uprcase(*str2))
  77.          return FALSE;
  78.       str1++;
  79.       str2++;
  80.    }
  81.    return *str1 == 0 && *str2 == 0;
  82. }
  83.  
  84. /* Return TRUE if both strings match.
  85.  * The second string is terminated by zero.
  86.  * The pointer to the first string is moved at end of the read word
  87.  * on success.
  88.  */
  89. static boolean str_match_no_case( const char **pcur, const char *str )
  90. {
  91.    const char *cur = *pcur;
  92.  
  93.    while (*str != '\0' && *str == uprcase( *cur )) {
  94.       str++;
  95.       cur++;
  96.    }
  97.    if (*str == '\0') {
  98.       *pcur = cur;
  99.       return TRUE;
  100.    }
  101.    return FALSE;
  102. }
  103.  
  104. /* Return TRUE if both strings match.
  105.  * The first string is be terminated by a non-digit non-letter non-underscore
  106.  * character, the second string is terminated by zero.
  107.  * The pointer to the first string is moved at end of the read word
  108.  * on success.
  109.  */
  110. static boolean str_match_nocase_whole( const char **pcur, const char *str )
  111. {
  112.    const char *cur = *pcur;
  113.  
  114.    if (str_match_no_case(&cur, str) &&
  115.        !is_digit_alpha_underscore(cur)) {
  116.       *pcur = cur;
  117.       return TRUE;
  118.    }
  119.    return FALSE;
  120. }
  121.  
  122. /* Eat zero or more whitespaces.
  123.  */
  124. static void eat_opt_white( const char **pcur )
  125. {
  126.    while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
  127.       (*pcur)++;
  128. }
  129.  
  130. /* Eat one or more whitespaces.
  131.  * Return TRUE if at least one whitespace eaten.
  132.  */
  133. static boolean eat_white( const char **pcur )
  134. {
  135.    const char *cur = *pcur;
  136.  
  137.    eat_opt_white( pcur );
  138.    return *pcur > cur;
  139. }
  140.  
  141. /* Parse unsigned integer.
  142.  * No checks for overflow.
  143.  */
  144. static boolean parse_uint( const char **pcur, uint *val )
  145. {
  146.    const char *cur = *pcur;
  147.  
  148.    if (is_digit( cur )) {
  149.       *val = *cur++ - '0';
  150.       while (is_digit( cur ))
  151.          *val = *val * 10 + *cur++ - '0';
  152.       *pcur = cur;
  153.       return TRUE;
  154.    }
  155.    return FALSE;
  156. }
  157.  
  158. static boolean parse_int( const char **pcur, int *val )
  159. {
  160.    const char *cur = *pcur;
  161.    int sign = (*cur == '-' ? -1 : 1);
  162.  
  163.    if (*cur == '+' || *cur == '-')
  164.       cur++;
  165.  
  166.    if (parse_uint(&cur, (uint *)val)) {
  167.       *val *= sign;
  168.       *pcur = cur;
  169.       return TRUE;
  170.    }
  171.  
  172.    return FALSE;
  173. }
  174.  
  175. static boolean parse_identifier( const char **pcur, char *ret )
  176. {
  177.    const char *cur = *pcur;
  178.    int i = 0;
  179.    if (is_alpha_underscore( cur )) {
  180.       ret[i++] = *cur++;
  181.       while (is_alpha_underscore( cur ) || is_digit( cur ))
  182.          ret[i++] = *cur++;
  183.       ret[i++] = '\0';
  184.       *pcur = cur;
  185.       return TRUE;
  186.    }
  187.    return FALSE;
  188. }
  189.  
  190. /* Parse floating point.
  191.  */
  192. static boolean parse_float( const char **pcur, float *val )
  193. {
  194.    const char *cur = *pcur;
  195.    boolean integral_part = FALSE;
  196.    boolean fractional_part = FALSE;
  197.  
  198.    *val = (float) atof( cur );
  199.  
  200.    if (*cur == '-' || *cur == '+')
  201.       cur++;
  202.    if (is_digit( cur )) {
  203.       cur++;
  204.       integral_part = TRUE;
  205.       while (is_digit( cur ))
  206.          cur++;
  207.    }
  208.    if (*cur == '.') {
  209.       cur++;
  210.       if (is_digit( cur )) {
  211.          cur++;
  212.          fractional_part = TRUE;
  213.          while (is_digit( cur ))
  214.             cur++;
  215.       }
  216.    }
  217.    if (!integral_part && !fractional_part)
  218.       return FALSE;
  219.    if (uprcase( *cur ) == 'E') {
  220.       cur++;
  221.       if (*cur == '-' || *cur == '+')
  222.          cur++;
  223.       if (is_digit( cur )) {
  224.          cur++;
  225.          while (is_digit( cur ))
  226.             cur++;
  227.       }
  228.       else
  229.          return FALSE;
  230.    }
  231.    *pcur = cur;
  232.    return TRUE;
  233. }
  234.  
  235. static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1)
  236. {
  237.    const char *cur = *pcur;
  238.    union {
  239.       double dval;
  240.       uint32_t uval[2];
  241.    } v;
  242.  
  243.    v.dval = strtod(cur, (char**)pcur);
  244.    if (*pcur == cur)
  245.       return FALSE;
  246.  
  247.    *val0 = v.uval[0];
  248.    *val1 = v.uval[1];
  249.  
  250.    return TRUE;
  251. }
  252.  
  253. struct translate_ctx
  254. {
  255.    const char *text;
  256.    const char *cur;
  257.    struct tgsi_token *tokens;
  258.    struct tgsi_token *tokens_cur;
  259.    struct tgsi_token *tokens_end;
  260.    struct tgsi_header *header;
  261.    unsigned processor : 4;
  262.    int implied_array_size : 5;
  263.    unsigned num_immediates;
  264. };
  265.  
  266. static void report_error( struct translate_ctx *ctx, const char *msg )
  267. {
  268.    int line = 1;
  269.    int column = 1;
  270.    const char *itr = ctx->text;
  271.  
  272.    while (itr != ctx->cur) {
  273.       if (*itr == '\n') {
  274.          column = 1;
  275.          ++line;
  276.       }
  277.       ++column;
  278.       ++itr;
  279.    }
  280.  
  281.    debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
  282. }
  283.  
  284. /* Parse shader header.
  285.  * Return TRUE for one of the following headers.
  286.  *    FRAG
  287.  *    GEOM
  288.  *    VERT
  289.  */
  290. static boolean parse_header( struct translate_ctx *ctx )
  291. {
  292.    uint processor;
  293.  
  294.    if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
  295.       processor = TGSI_PROCESSOR_FRAGMENT;
  296.    else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
  297.       processor = TGSI_PROCESSOR_VERTEX;
  298.    else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
  299.       processor = TGSI_PROCESSOR_GEOMETRY;
  300.    else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
  301.       processor = TGSI_PROCESSOR_COMPUTE;
  302.    else {
  303.       report_error( ctx, "Unknown header" );
  304.       return FALSE;
  305.    }
  306.  
  307.    if (ctx->tokens_cur >= ctx->tokens_end)
  308.       return FALSE;
  309.    ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
  310.    *ctx->header = tgsi_build_header();
  311.  
  312.    if (ctx->tokens_cur >= ctx->tokens_end)
  313.       return FALSE;
  314.    *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
  315.    ctx->processor = processor;
  316.  
  317.    return TRUE;
  318. }
  319.  
  320. static boolean parse_label( struct translate_ctx *ctx, uint *val )
  321. {
  322.    const char *cur = ctx->cur;
  323.  
  324.    if (parse_uint( &cur, val )) {
  325.       eat_opt_white( &cur );
  326.       if (*cur == ':') {
  327.          cur++;
  328.          ctx->cur = cur;
  329.          return TRUE;
  330.       }
  331.    }
  332.    return FALSE;
  333. }
  334.  
  335. static boolean
  336. parse_file( const char **pcur, uint *file )
  337. {
  338.    uint i;
  339.  
  340.    for (i = 0; i < TGSI_FILE_COUNT; i++) {
  341.       const char *cur = *pcur;
  342.  
  343.       if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
  344.          *pcur = cur;
  345.          *file = i;
  346.          return TRUE;
  347.       }
  348.    }
  349.    return FALSE;
  350. }
  351.  
  352. static boolean
  353. parse_opt_writemask(
  354.    struct translate_ctx *ctx,
  355.    uint *writemask )
  356. {
  357.    const char *cur;
  358.  
  359.    cur = ctx->cur;
  360.    eat_opt_white( &cur );
  361.    if (*cur == '.') {
  362.       cur++;
  363.       *writemask = TGSI_WRITEMASK_NONE;
  364.       eat_opt_white( &cur );
  365.       if (uprcase( *cur ) == 'X') {
  366.          cur++;
  367.          *writemask |= TGSI_WRITEMASK_X;
  368.       }
  369.       if (uprcase( *cur ) == 'Y') {
  370.          cur++;
  371.          *writemask |= TGSI_WRITEMASK_Y;
  372.       }
  373.       if (uprcase( *cur ) == 'Z') {
  374.          cur++;
  375.          *writemask |= TGSI_WRITEMASK_Z;
  376.       }
  377.       if (uprcase( *cur ) == 'W') {
  378.          cur++;
  379.          *writemask |= TGSI_WRITEMASK_W;
  380.       }
  381.  
  382.       if (*writemask == TGSI_WRITEMASK_NONE) {
  383.          report_error( ctx, "Writemask expected" );
  384.          return FALSE;
  385.       }
  386.  
  387.       ctx->cur = cur;
  388.    }
  389.    else {
  390.       *writemask = TGSI_WRITEMASK_XYZW;
  391.    }
  392.    return TRUE;
  393. }
  394.  
  395.  
  396. /* <register_file_bracket> ::= <file> `['
  397.  */
  398. static boolean
  399. parse_register_file_bracket(
  400.    struct translate_ctx *ctx,
  401.    uint *file )
  402. {
  403.    if (!parse_file( &ctx->cur, file )) {
  404.       report_error( ctx, "Unknown register file" );
  405.       return FALSE;
  406.    }
  407.    eat_opt_white( &ctx->cur );
  408.    if (*ctx->cur != '[') {
  409.       report_error( ctx, "Expected `['" );
  410.       return FALSE;
  411.    }
  412.    ctx->cur++;
  413.    return TRUE;
  414. }
  415.  
  416. /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
  417.  */
  418. static boolean
  419. parse_register_file_bracket_index(
  420.    struct translate_ctx *ctx,
  421.    uint *file,
  422.    int *index )
  423. {
  424.    uint uindex;
  425.  
  426.    if (!parse_register_file_bracket( ctx, file ))
  427.       return FALSE;
  428.    eat_opt_white( &ctx->cur );
  429.    if (!parse_uint( &ctx->cur, &uindex )) {
  430.       report_error( ctx, "Expected literal unsigned integer" );
  431.       return FALSE;
  432.    }
  433.    *index = (int) uindex;
  434.    return TRUE;
  435. }
  436.  
  437. /* Parse simple 1d register operand.
  438.  *    <register_dst> ::= <register_file_bracket_index> `]'
  439.  */
  440. static boolean
  441. parse_register_1d(struct translate_ctx *ctx,
  442.                   uint *file,
  443.                   int *index )
  444. {
  445.    if (!parse_register_file_bracket_index( ctx, file, index ))
  446.       return FALSE;
  447.    eat_opt_white( &ctx->cur );
  448.    if (*ctx->cur != ']') {
  449.       report_error( ctx, "Expected `]'" );
  450.       return FALSE;
  451.    }
  452.    ctx->cur++;
  453.    return TRUE;
  454. }
  455.  
  456. struct parsed_bracket {
  457.    int index;
  458.  
  459.    uint ind_file;
  460.    int ind_index;
  461.    uint ind_comp;
  462.    uint ind_array;
  463. };
  464.  
  465.  
  466. static boolean
  467. parse_register_bracket(
  468.    struct translate_ctx *ctx,
  469.    struct parsed_bracket *brackets)
  470. {
  471.    const char *cur;
  472.    uint uindex;
  473.  
  474.    memset(brackets, 0, sizeof(struct parsed_bracket));
  475.  
  476.    eat_opt_white( &ctx->cur );
  477.  
  478.    cur = ctx->cur;
  479.    if (parse_file( &cur, &brackets->ind_file )) {
  480.       if (!parse_register_1d( ctx, &brackets->ind_file,
  481.                               &brackets->ind_index ))
  482.          return FALSE;
  483.       eat_opt_white( &ctx->cur );
  484.  
  485.       if (*ctx->cur == '.') {
  486.          ctx->cur++;
  487.          eat_opt_white(&ctx->cur);
  488.  
  489.          switch (uprcase(*ctx->cur)) {
  490.          case 'X':
  491.             brackets->ind_comp = TGSI_SWIZZLE_X;
  492.             break;
  493.          case 'Y':
  494.             brackets->ind_comp = TGSI_SWIZZLE_Y;
  495.             break;
  496.          case 'Z':
  497.             brackets->ind_comp = TGSI_SWIZZLE_Z;
  498.             break;
  499.          case 'W':
  500.             brackets->ind_comp = TGSI_SWIZZLE_W;
  501.             break;
  502.          default:
  503.             report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
  504.             return FALSE;
  505.          }
  506.          ctx->cur++;
  507.          eat_opt_white(&ctx->cur);
  508.       }
  509.  
  510.       if (*ctx->cur == '+' || *ctx->cur == '-')
  511.          parse_int( &ctx->cur, &brackets->index );
  512.       else
  513.          brackets->index = 0;
  514.    }
  515.    else {
  516.       if (!parse_uint( &ctx->cur, &uindex )) {
  517.          report_error( ctx, "Expected literal unsigned integer" );
  518.          return FALSE;
  519.       }
  520.       brackets->index = (int) uindex;
  521.       brackets->ind_file = TGSI_FILE_NULL;
  522.       brackets->ind_index = 0;
  523.    }
  524.    eat_opt_white( &ctx->cur );
  525.    if (*ctx->cur != ']') {
  526.       report_error( ctx, "Expected `]'" );
  527.       return FALSE;
  528.    }
  529.    ctx->cur++;
  530.    if (*ctx->cur == '(') {
  531.       ctx->cur++;
  532.       eat_opt_white( &ctx->cur );
  533.       if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
  534.          report_error( ctx, "Expected literal unsigned integer" );
  535.          return FALSE;
  536.       }
  537.       eat_opt_white( &ctx->cur );
  538.       if (*ctx->cur != ')') {
  539.          report_error( ctx, "Expected `)'" );
  540.          return FALSE;
  541.       }
  542.       ctx->cur++;
  543.    }
  544.    return TRUE;
  545. }
  546.  
  547. static boolean
  548. parse_opt_register_src_bracket(
  549.    struct translate_ctx *ctx,
  550.    struct parsed_bracket *brackets,
  551.    int *parsed_brackets)
  552. {
  553.    const char *cur = ctx->cur;
  554.  
  555.    *parsed_brackets = 0;
  556.  
  557.    eat_opt_white( &cur );
  558.    if (cur[0] == '[') {
  559.       ++cur;
  560.       ctx->cur = cur;
  561.  
  562.       if (!parse_register_bracket(ctx, brackets))
  563.          return FALSE;
  564.  
  565.       *parsed_brackets = 1;
  566.    }
  567.  
  568.    return TRUE;
  569. }
  570.  
  571.  
  572. /* Parse source register operand.
  573.  *    <register_src> ::= <register_file_bracket_index> `]' |
  574.  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
  575.  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
  576.  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
  577.  */
  578. static boolean
  579. parse_register_src(
  580.    struct translate_ctx *ctx,
  581.    uint *file,
  582.    struct parsed_bracket *brackets)
  583. {
  584.    brackets->ind_comp = TGSI_SWIZZLE_X;
  585.    if (!parse_register_file_bracket( ctx, file ))
  586.       return FALSE;
  587.    if (!parse_register_bracket( ctx, brackets ))
  588.        return FALSE;
  589.  
  590.    return TRUE;
  591. }
  592.  
  593. struct parsed_dcl_bracket {
  594.    uint first;
  595.    uint last;
  596. };
  597.  
  598. static boolean
  599. parse_register_dcl_bracket(
  600.    struct translate_ctx *ctx,
  601.    struct parsed_dcl_bracket *bracket)
  602. {
  603.    uint uindex;
  604.    memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
  605.  
  606.    eat_opt_white( &ctx->cur );
  607.  
  608.    if (!parse_uint( &ctx->cur, &uindex )) {
  609.       /* it can be an empty bracket [] which means its range
  610.        * is from 0 to some implied size */
  611.       if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
  612.          bracket->first = 0;
  613.          bracket->last = ctx->implied_array_size - 1;
  614.          goto cleanup;
  615.       }
  616.       report_error( ctx, "Expected literal unsigned integer" );
  617.       return FALSE;
  618.    }
  619.    bracket->first = uindex;
  620.  
  621.    eat_opt_white( &ctx->cur );
  622.  
  623.    if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
  624.       uint uindex;
  625.  
  626.       ctx->cur += 2;
  627.       eat_opt_white( &ctx->cur );
  628.       if (!parse_uint( &ctx->cur, &uindex )) {
  629.          report_error( ctx, "Expected literal integer" );
  630.          return FALSE;
  631.       }
  632.       bracket->last = (int) uindex;
  633.       eat_opt_white( &ctx->cur );
  634.    }
  635.    else {
  636.       bracket->last = bracket->first;
  637.    }
  638.  
  639. cleanup:
  640.    if (*ctx->cur != ']') {
  641.       report_error( ctx, "Expected `]' or `..'" );
  642.       return FALSE;
  643.    }
  644.    ctx->cur++;
  645.    return TRUE;
  646. }
  647.  
  648. /* Parse register declaration.
  649.  *    <register_dcl> ::= <register_file_bracket_index> `]' |
  650.  *                       <register_file_bracket_index> `..' <index> `]'
  651.  */
  652. static boolean
  653. parse_register_dcl(
  654.    struct translate_ctx *ctx,
  655.    uint *file,
  656.    struct parsed_dcl_bracket *brackets,
  657.    int *num_brackets)
  658. {
  659.    const char *cur;
  660.  
  661.    *num_brackets = 0;
  662.  
  663.    if (!parse_register_file_bracket( ctx, file ))
  664.       return FALSE;
  665.    if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
  666.       return FALSE;
  667.  
  668.    *num_brackets = 1;
  669.  
  670.    cur = ctx->cur;
  671.    eat_opt_white( &cur );
  672.  
  673.    if (cur[0] == '[') {
  674.       ++cur;
  675.       ctx->cur = cur;
  676.       if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
  677.          return FALSE;
  678.       /* for geometry shader we don't really care about
  679.        * the first brackets it's always the size of the
  680.        * input primitive. so we want to declare just
  681.        * the index relevant to the semantics which is in
  682.        * the second bracket */
  683.       if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
  684.          brackets[0] = brackets[1];
  685.          *num_brackets = 1;
  686.       } else {
  687.          *num_brackets = 2;
  688.       }
  689.    }
  690.  
  691.    return TRUE;
  692. }
  693.  
  694.  
  695. /* Parse destination register operand.*/
  696. static boolean
  697. parse_register_dst(
  698.    struct translate_ctx *ctx,
  699.    uint *file,
  700.    struct parsed_bracket *brackets)
  701. {
  702.    brackets->ind_comp = TGSI_SWIZZLE_X;
  703.    if (!parse_register_file_bracket( ctx, file ))
  704.       return FALSE;
  705.    if (!parse_register_bracket( ctx, brackets ))
  706.        return FALSE;
  707.  
  708.    return TRUE;
  709. }
  710.  
  711. static boolean
  712. parse_dst_operand(
  713.    struct translate_ctx *ctx,
  714.    struct tgsi_full_dst_register *dst )
  715. {
  716.    uint file;
  717.    uint writemask;
  718.    const char *cur;
  719.    struct parsed_bracket bracket[2];
  720.    int parsed_opt_brackets;
  721.  
  722.    if (!parse_register_dst( ctx, &file, &bracket[0] ))
  723.       return FALSE;
  724.    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
  725.       return FALSE;
  726.  
  727.    cur = ctx->cur;
  728.    eat_opt_white( &cur );
  729.  
  730.    if (!parse_opt_writemask( ctx, &writemask ))
  731.       return FALSE;
  732.  
  733.    dst->Register.File = file;
  734.    if (parsed_opt_brackets) {
  735.       dst->Register.Dimension = 1;
  736.       dst->Dimension.Indirect = 0;
  737.       dst->Dimension.Dimension = 0;
  738.       dst->Dimension.Index = bracket[0].index;
  739.       bracket[0] = bracket[1];
  740.    }
  741.    dst->Register.Index = bracket[0].index;
  742.    dst->Register.WriteMask = writemask;
  743.    if (bracket[0].ind_file != TGSI_FILE_NULL) {
  744.       dst->Register.Indirect = 1;
  745.       dst->Indirect.File = bracket[0].ind_file;
  746.       dst->Indirect.Index = bracket[0].ind_index;
  747.       dst->Indirect.Swizzle = bracket[0].ind_comp;
  748.       dst->Indirect.ArrayID = bracket[0].ind_array;
  749.    }
  750.    return TRUE;
  751. }
  752.  
  753. static boolean
  754. parse_optional_swizzle(
  755.    struct translate_ctx *ctx,
  756.    uint *swizzle,
  757.    boolean *parsed_swizzle,
  758.    int components)
  759. {
  760.    const char *cur = ctx->cur;
  761.  
  762.    *parsed_swizzle = FALSE;
  763.  
  764.    eat_opt_white( &cur );
  765.    if (*cur == '.') {
  766.       uint i;
  767.  
  768.       cur++;
  769.       eat_opt_white( &cur );
  770.       for (i = 0; i < components; i++) {
  771.          if (uprcase( *cur ) == 'X')
  772.             swizzle[i] = TGSI_SWIZZLE_X;
  773.          else if (uprcase( *cur ) == 'Y')
  774.             swizzle[i] = TGSI_SWIZZLE_Y;
  775.          else if (uprcase( *cur ) == 'Z')
  776.             swizzle[i] = TGSI_SWIZZLE_Z;
  777.          else if (uprcase( *cur ) == 'W')
  778.             swizzle[i] = TGSI_SWIZZLE_W;
  779.          else {
  780.             report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
  781.             return FALSE;
  782.          }
  783.          cur++;
  784.       }
  785.       *parsed_swizzle = TRUE;
  786.       ctx->cur = cur;
  787.    }
  788.    return TRUE;
  789. }
  790.  
  791. static boolean
  792. parse_src_operand(
  793.    struct translate_ctx *ctx,
  794.    struct tgsi_full_src_register *src )
  795. {
  796.    uint file;
  797.    uint swizzle[4];
  798.    boolean parsed_swizzle;
  799.    struct parsed_bracket bracket[2];
  800.    int parsed_opt_brackets;
  801.  
  802.    if (*ctx->cur == '-') {
  803.       ctx->cur++;
  804.       eat_opt_white( &ctx->cur );
  805.       src->Register.Negate = 1;
  806.    }
  807.  
  808.    if (*ctx->cur == '|') {
  809.       ctx->cur++;
  810.       eat_opt_white( &ctx->cur );
  811.       src->Register.Absolute = 1;
  812.    }
  813.  
  814.    if (!parse_register_src(ctx, &file, &bracket[0]))
  815.       return FALSE;
  816.    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
  817.       return FALSE;
  818.  
  819.    src->Register.File = file;
  820.    if (parsed_opt_brackets) {
  821.       src->Register.Dimension = 1;
  822.       src->Dimension.Indirect = 0;
  823.       src->Dimension.Dimension = 0;
  824.       src->Dimension.Index = bracket[0].index;
  825.       if (bracket[0].ind_file != TGSI_FILE_NULL) {
  826.          src->Dimension.Indirect = 1;
  827.          src->DimIndirect.File = bracket[0].ind_file;
  828.          src->DimIndirect.Index = bracket[0].ind_index;
  829.          src->DimIndirect.Swizzle = bracket[0].ind_comp;
  830.          src->DimIndirect.ArrayID = bracket[0].ind_array;
  831.       }
  832.       bracket[0] = bracket[1];
  833.    }
  834.    src->Register.Index = bracket[0].index;
  835.    if (bracket[0].ind_file != TGSI_FILE_NULL) {
  836.       src->Register.Indirect = 1;
  837.       src->Indirect.File = bracket[0].ind_file;
  838.       src->Indirect.Index = bracket[0].ind_index;
  839.       src->Indirect.Swizzle = bracket[0].ind_comp;
  840.       src->Indirect.ArrayID = bracket[0].ind_array;
  841.    }
  842.  
  843.    /* Parse optional swizzle.
  844.     */
  845.    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
  846.       if (parsed_swizzle) {
  847.          src->Register.SwizzleX = swizzle[0];
  848.          src->Register.SwizzleY = swizzle[1];
  849.          src->Register.SwizzleZ = swizzle[2];
  850.          src->Register.SwizzleW = swizzle[3];
  851.       }
  852.    }
  853.  
  854.    if (src->Register.Absolute) {
  855.       eat_opt_white( &ctx->cur );
  856.       if (*ctx->cur != '|') {
  857.          report_error( ctx, "Expected `|'" );
  858.          return FALSE;
  859.       }
  860.       ctx->cur++;
  861.    }
  862.  
  863.  
  864.    return TRUE;
  865. }
  866.  
  867. static boolean
  868. parse_texoffset_operand(
  869.    struct translate_ctx *ctx,
  870.    struct tgsi_texture_offset *src )
  871. {
  872.    uint file;
  873.    uint swizzle[3];
  874.    boolean parsed_swizzle;
  875.    struct parsed_bracket bracket;
  876.  
  877.    if (!parse_register_src(ctx, &file, &bracket))
  878.       return FALSE;
  879.  
  880.    src->File = file;
  881.    src->Index = bracket.index;
  882.  
  883.    /* Parse optional swizzle.
  884.     */
  885.    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) {
  886.       if (parsed_swizzle) {
  887.          src->SwizzleX = swizzle[0];
  888.          src->SwizzleY = swizzle[1];
  889.          src->SwizzleZ = swizzle[2];
  890.       }
  891.    }
  892.  
  893.    return TRUE;
  894. }
  895.  
  896. static boolean
  897. match_inst(const char **pcur,
  898.            unsigned *saturate,
  899.            const struct tgsi_opcode_info *info)
  900. {
  901.    const char *cur = *pcur;
  902.  
  903.    /* simple case: the whole string matches the instruction name */
  904.    if (str_match_nocase_whole(&cur, info->mnemonic)) {
  905.       *pcur = cur;
  906.       *saturate = TGSI_SAT_NONE;
  907.       return TRUE;
  908.    }
  909.  
  910.    if (str_match_no_case(&cur, info->mnemonic)) {
  911.       /* the instruction has a suffix, figure it out */
  912.       if (str_match_nocase_whole(&cur, "_SAT")) {
  913.          *pcur = cur;
  914.          *saturate = TGSI_SAT_ZERO_ONE;
  915.          return TRUE;
  916.       }
  917.  
  918.       if (str_match_nocase_whole(&cur, "_SATNV")) {
  919.          *pcur = cur;
  920.          *saturate = TGSI_SAT_MINUS_PLUS_ONE;
  921.          return TRUE;
  922.       }
  923.    }
  924.  
  925.    return FALSE;
  926. }
  927.  
  928. static boolean
  929. parse_instruction(
  930.    struct translate_ctx *ctx,
  931.    boolean has_label )
  932. {
  933.    uint i;
  934.    uint saturate = TGSI_SAT_NONE;
  935.    const struct tgsi_opcode_info *info;
  936.    struct tgsi_full_instruction inst;
  937.    const char *cur;
  938.    uint advance;
  939.  
  940.    inst = tgsi_default_full_instruction();
  941.  
  942.    /* Parse predicate.
  943.     */
  944.    eat_opt_white( &ctx->cur );
  945.    if (*ctx->cur == '(') {
  946.       uint file;
  947.       int index;
  948.       uint swizzle[4];
  949.       boolean parsed_swizzle;
  950.  
  951.       inst.Instruction.Predicate = 1;
  952.  
  953.       ctx->cur++;
  954.       if (*ctx->cur == '!') {
  955.          ctx->cur++;
  956.          inst.Predicate.Negate = 1;
  957.       }
  958.  
  959.       if (!parse_register_1d( ctx, &file, &index ))
  960.          return FALSE;
  961.  
  962.       if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
  963.          if (parsed_swizzle) {
  964.             inst.Predicate.SwizzleX = swizzle[0];
  965.             inst.Predicate.SwizzleY = swizzle[1];
  966.             inst.Predicate.SwizzleZ = swizzle[2];
  967.             inst.Predicate.SwizzleW = swizzle[3];
  968.          }
  969.       }
  970.  
  971.       if (*ctx->cur != ')') {
  972.          report_error( ctx, "Expected `)'" );
  973.          return FALSE;
  974.       }
  975.  
  976.       ctx->cur++;
  977.    }
  978.  
  979.    /* Parse instruction name.
  980.     */
  981.    eat_opt_white( &ctx->cur );
  982.    for (i = 0; i < TGSI_OPCODE_LAST; i++) {
  983.       cur = ctx->cur;
  984.  
  985.       info = tgsi_get_opcode_info( i );
  986.       if (match_inst(&cur, &saturate, info)) {
  987.          if (info->num_dst + info->num_src + info->is_tex == 0) {
  988.             ctx->cur = cur;
  989.             break;
  990.          }
  991.          else if (*cur == '\0' || eat_white( &cur )) {
  992.             ctx->cur = cur;
  993.             break;
  994.          }
  995.       }
  996.    }
  997.    if (i == TGSI_OPCODE_LAST) {
  998.       if (has_label)
  999.          report_error( ctx, "Unknown opcode" );
  1000.       else
  1001.          report_error( ctx, "Expected `DCL', `IMM' or a label" );
  1002.       return FALSE;
  1003.    }
  1004.  
  1005.    inst.Instruction.Opcode = i;
  1006.    inst.Instruction.Saturate = saturate;
  1007.    inst.Instruction.NumDstRegs = info->num_dst;
  1008.    inst.Instruction.NumSrcRegs = info->num_src;
  1009.  
  1010.    if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
  1011.       /*
  1012.        * These are not considered tex opcodes here (no additional
  1013.        * target argument) however we're required to set the Texture
  1014.        * bit so we can set the number of tex offsets.
  1015.        */
  1016.       inst.Instruction.Texture = 1;
  1017.       inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
  1018.    }
  1019.  
  1020.    /* Parse instruction operands.
  1021.     */
  1022.    for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
  1023.       if (i > 0) {
  1024.          eat_opt_white( &ctx->cur );
  1025.          if (*ctx->cur != ',') {
  1026.             report_error( ctx, "Expected `,'" );
  1027.             return FALSE;
  1028.          }
  1029.          ctx->cur++;
  1030.          eat_opt_white( &ctx->cur );
  1031.       }
  1032.  
  1033.       if (i < info->num_dst) {
  1034.          if (!parse_dst_operand( ctx, &inst.Dst[i] ))
  1035.             return FALSE;
  1036.       }
  1037.       else if (i < info->num_dst + info->num_src) {
  1038.          if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
  1039.             return FALSE;
  1040.       }
  1041.       else {
  1042.          uint j;
  1043.  
  1044.          for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
  1045.             if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
  1046.                inst.Instruction.Texture = 1;
  1047.                inst.Texture.Texture = j;
  1048.                break;
  1049.             }
  1050.          }
  1051.          if (j == TGSI_TEXTURE_COUNT) {
  1052.             report_error( ctx, "Expected texture target" );
  1053.             return FALSE;
  1054.          }
  1055.       }
  1056.    }
  1057.  
  1058.    cur = ctx->cur;
  1059.    eat_opt_white( &cur );
  1060.    for (i = 0; inst.Instruction.Texture && *cur == ','; i++) {
  1061.          cur++;
  1062.          eat_opt_white( &cur );
  1063.          ctx->cur = cur;
  1064.          if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))
  1065.             return FALSE;
  1066.          cur = ctx->cur;
  1067.          eat_opt_white( &cur );
  1068.    }
  1069.    inst.Texture.NumOffsets = i;
  1070.  
  1071.    cur = ctx->cur;
  1072.    eat_opt_white( &cur );
  1073.    if (info->is_branch && *cur == ':') {
  1074.       uint target;
  1075.  
  1076.       cur++;
  1077.       eat_opt_white( &cur );
  1078.       if (!parse_uint( &cur, &target )) {
  1079.          report_error( ctx, "Expected a label" );
  1080.          return FALSE;
  1081.       }
  1082.       inst.Instruction.Label = 1;
  1083.       inst.Label.Label = target;
  1084.       ctx->cur = cur;
  1085.    }
  1086.  
  1087.    advance = tgsi_build_full_instruction(
  1088.       &inst,
  1089.       ctx->tokens_cur,
  1090.       ctx->header,
  1091.       (uint) (ctx->tokens_end - ctx->tokens_cur) );
  1092.    if (advance == 0)
  1093.       return FALSE;
  1094.    ctx->tokens_cur += advance;
  1095.  
  1096.    return TRUE;
  1097. }
  1098.  
  1099. /* parses a 4-touple of the form {x, y, z, w}
  1100.  * where x, y, z, w are numbers */
  1101. static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
  1102.                                     union tgsi_immediate_data *values)
  1103. {
  1104.    unsigned i;
  1105.    int ret;
  1106.  
  1107.    eat_opt_white( &ctx->cur );
  1108.    if (*ctx->cur != '{') {
  1109.       report_error( ctx, "Expected `{'" );
  1110.       return FALSE;
  1111.    }
  1112.    ctx->cur++;
  1113.    for (i = 0; i < 4; i++) {
  1114.       eat_opt_white( &ctx->cur );
  1115.       if (i > 0) {
  1116.          if (*ctx->cur != ',') {
  1117.             report_error( ctx, "Expected `,'" );
  1118.             return FALSE;
  1119.          }
  1120.          ctx->cur++;
  1121.          eat_opt_white( &ctx->cur );
  1122.       }
  1123.  
  1124.       switch (type) {
  1125.       case TGSI_IMM_FLOAT64:
  1126.          ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
  1127.          i++;
  1128.          break;
  1129.       case TGSI_IMM_FLOAT32:
  1130.          ret = parse_float(&ctx->cur, &values[i].Float);
  1131.          break;
  1132.       case TGSI_IMM_UINT32:
  1133.          ret = parse_uint(&ctx->cur, &values[i].Uint);
  1134.          break;
  1135.       case TGSI_IMM_INT32:
  1136.          ret = parse_int(&ctx->cur, &values[i].Int);
  1137.          break;
  1138.       default:
  1139.          assert(0);
  1140.          ret = FALSE;
  1141.          break;
  1142.       }
  1143.  
  1144.       if (!ret) {
  1145.          report_error( ctx, "Expected immediate constant" );
  1146.          return FALSE;
  1147.       }
  1148.    }
  1149.    eat_opt_white( &ctx->cur );
  1150.    if (*ctx->cur != '}') {
  1151.       report_error( ctx, "Expected `}'" );
  1152.       return FALSE;
  1153.    }
  1154.    ctx->cur++;
  1155.  
  1156.    return TRUE;
  1157. }
  1158.  
  1159. static boolean parse_declaration( struct translate_ctx *ctx )
  1160. {
  1161.    struct tgsi_full_declaration decl;
  1162.    uint file;
  1163.    struct parsed_dcl_bracket brackets[2];
  1164.    int num_brackets;
  1165.    uint writemask;
  1166.    const char *cur, *cur2;
  1167.    uint advance;
  1168.    boolean is_vs_input;
  1169.  
  1170.    if (!eat_white( &ctx->cur )) {
  1171.       report_error( ctx, "Syntax error" );
  1172.       return FALSE;
  1173.    }
  1174.    if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
  1175.       return FALSE;
  1176.    if (!parse_opt_writemask( ctx, &writemask ))
  1177.       return FALSE;
  1178.  
  1179.    decl = tgsi_default_full_declaration();
  1180.    decl.Declaration.File = file;
  1181.    decl.Declaration.UsageMask = writemask;
  1182.  
  1183.    if (num_brackets == 1) {
  1184.       decl.Range.First = brackets[0].first;
  1185.       decl.Range.Last = brackets[0].last;
  1186.    } else {
  1187.       decl.Range.First = brackets[1].first;
  1188.       decl.Range.Last = brackets[1].last;
  1189.  
  1190.       decl.Declaration.Dimension = 1;
  1191.       decl.Dim.Index2D = brackets[0].first;
  1192.    }
  1193.  
  1194.    is_vs_input = (file == TGSI_FILE_INPUT &&
  1195.                   ctx->processor == TGSI_PROCESSOR_VERTEX);
  1196.  
  1197.    cur = ctx->cur;
  1198.    eat_opt_white( &cur );
  1199.    if (*cur == ',') {
  1200.       cur2 = cur;
  1201.       cur2++;
  1202.       eat_opt_white( &cur2 );
  1203.       if (str_match_nocase_whole( &cur2, "ARRAY" )) {
  1204.          int arrayid;
  1205.          if (*cur2 != '(') {
  1206.             report_error( ctx, "Expected `('" );
  1207.             return FALSE;
  1208.          }
  1209.          cur2++;
  1210.          eat_opt_white( &cur2 );
  1211.          if (!parse_int( &cur2, &arrayid )) {
  1212.             report_error( ctx, "Expected `,'" );
  1213.             return FALSE;
  1214.          }
  1215.          eat_opt_white( &cur2 );
  1216.          if (*cur2 != ')') {
  1217.             report_error( ctx, "Expected `)'" );
  1218.             return FALSE;
  1219.          }
  1220.          cur2++;
  1221.          decl.Declaration.Array = 1;
  1222.          decl.Array.ArrayID = arrayid;
  1223.          ctx->cur = cur = cur2;
  1224.       }
  1225.    }
  1226.  
  1227.    if (*cur == ',' && !is_vs_input) {
  1228.       uint i, j;
  1229.  
  1230.       cur++;
  1231.       eat_opt_white( &cur );
  1232.       if (file == TGSI_FILE_RESOURCE) {
  1233.          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
  1234.             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
  1235.                decl.Resource.Resource = i;
  1236.                break;
  1237.             }
  1238.          }
  1239.          if (i == TGSI_TEXTURE_COUNT) {
  1240.             report_error(ctx, "Expected texture target");
  1241.             return FALSE;
  1242.          }
  1243.  
  1244.          cur2 = cur;
  1245.          eat_opt_white(&cur2);
  1246.          while (*cur2 == ',') {
  1247.             cur2++;
  1248.             eat_opt_white(&cur2);
  1249.             if (str_match_nocase_whole(&cur2, "RAW")) {
  1250.                decl.Resource.Raw = 1;
  1251.  
  1252.             } else if (str_match_nocase_whole(&cur2, "WR")) {
  1253.                decl.Resource.Writable = 1;
  1254.  
  1255.             } else {
  1256.                break;
  1257.             }
  1258.             cur = cur2;
  1259.             eat_opt_white(&cur2);
  1260.          }
  1261.  
  1262.          ctx->cur = cur;
  1263.  
  1264.       } else if (file == TGSI_FILE_SAMPLER_VIEW) {
  1265.          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
  1266.             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
  1267.                decl.SamplerView.Resource = i;
  1268.                break;
  1269.             }
  1270.          }
  1271.          if (i == TGSI_TEXTURE_COUNT) {
  1272.             report_error(ctx, "Expected texture target");
  1273.             return FALSE;
  1274.          }
  1275.          eat_opt_white( &cur );
  1276.          if (*cur != ',') {
  1277.             report_error( ctx, "Expected `,'" );
  1278.             return FALSE;
  1279.          }
  1280.          ++cur;
  1281.          eat_opt_white( &cur );
  1282.          for (j = 0; j < 4; ++j) {
  1283.             for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) {
  1284.                if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) {
  1285.                   switch (j) {
  1286.                   case 0:
  1287.                      decl.SamplerView.ReturnTypeX = i;
  1288.                      break;
  1289.                   case 1:
  1290.                      decl.SamplerView.ReturnTypeY = i;
  1291.                      break;
  1292.                   case 2:
  1293.                      decl.SamplerView.ReturnTypeZ = i;
  1294.                      break;
  1295.                   case 3:
  1296.                      decl.SamplerView.ReturnTypeW = i;
  1297.                      break;
  1298.                   default:
  1299.                      assert(0);
  1300.                   }
  1301.                   break;
  1302.                }
  1303.             }
  1304.             if (i == TGSI_RETURN_TYPE_COUNT) {
  1305.                if (j == 0 || j >  2) {
  1306.                   report_error(ctx, "Expected type name");
  1307.                   return FALSE;
  1308.                }
  1309.                break;
  1310.             } else {
  1311.                cur2 = cur;
  1312.                eat_opt_white( &cur2 );
  1313.                if (*cur2 == ',') {
  1314.                   cur2++;
  1315.                   eat_opt_white( &cur2 );
  1316.                   cur = cur2;
  1317.                   continue;
  1318.                } else
  1319.                   break;
  1320.             }
  1321.          }
  1322.          if (j < 4) {
  1323.             decl.SamplerView.ReturnTypeY =
  1324.                decl.SamplerView.ReturnTypeZ =
  1325.                decl.SamplerView.ReturnTypeW =
  1326.                decl.SamplerView.ReturnTypeX;
  1327.          }
  1328.          ctx->cur = cur;
  1329.       } else {
  1330.          if (str_match_nocase_whole(&cur, "LOCAL")) {
  1331.             decl.Declaration.Local = 1;
  1332.             ctx->cur = cur;
  1333.          }
  1334.  
  1335.          cur = ctx->cur;
  1336.          eat_opt_white( &cur );
  1337.          if (*cur == ',') {
  1338.             cur++;
  1339.             eat_opt_white( &cur );
  1340.  
  1341.             for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
  1342.                if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
  1343.                   uint index;
  1344.  
  1345.                   cur2 = cur;
  1346.                   eat_opt_white( &cur2 );
  1347.                   if (*cur2 == '[') {
  1348.                      cur2++;
  1349.                      eat_opt_white( &cur2 );
  1350.                      if (!parse_uint( &cur2, &index )) {
  1351.                         report_error( ctx, "Expected literal integer" );
  1352.                         return FALSE;
  1353.                      }
  1354.                      eat_opt_white( &cur2 );
  1355.                      if (*cur2 != ']') {
  1356.                         report_error( ctx, "Expected `]'" );
  1357.                         return FALSE;
  1358.                      }
  1359.                      cur2++;
  1360.  
  1361.                      decl.Semantic.Index = index;
  1362.  
  1363.                      cur = cur2;
  1364.                   }
  1365.  
  1366.                   decl.Declaration.Semantic = 1;
  1367.                   decl.Semantic.Name = i;
  1368.  
  1369.                   ctx->cur = cur;
  1370.                   break;
  1371.                }
  1372.             }
  1373.          }
  1374.       }
  1375.    }
  1376.  
  1377.    cur = ctx->cur;
  1378.    eat_opt_white( &cur );
  1379.    if (*cur == ',' && !is_vs_input) {
  1380.       uint i;
  1381.  
  1382.       cur++;
  1383.       eat_opt_white( &cur );
  1384.       for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
  1385.          if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
  1386.             decl.Declaration.Interpolate = 1;
  1387.             decl.Interp.Interpolate = i;
  1388.  
  1389.             ctx->cur = cur;
  1390.             break;
  1391.          }
  1392.       }
  1393.       if (i == TGSI_INTERPOLATE_COUNT) {
  1394.          report_error( ctx, "Expected semantic or interpolate attribute" );
  1395.          return FALSE;
  1396.       }
  1397.    }
  1398.  
  1399.    cur = ctx->cur;
  1400.    eat_opt_white( &cur );
  1401.    if (*cur == ',' && !is_vs_input) {
  1402.       uint i;
  1403.  
  1404.       cur++;
  1405.       eat_opt_white( &cur );
  1406.       for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) {
  1407.          if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) {
  1408.             decl.Interp.Location = i;
  1409.  
  1410.             ctx->cur = cur;
  1411.             break;
  1412.          }
  1413.       }
  1414.    }
  1415.  
  1416.    advance = tgsi_build_full_declaration(
  1417.       &decl,
  1418.       ctx->tokens_cur,
  1419.       ctx->header,
  1420.       (uint) (ctx->tokens_end - ctx->tokens_cur) );
  1421.  
  1422.    if (advance == 0)
  1423.       return FALSE;
  1424.    ctx->tokens_cur += advance;
  1425.  
  1426.    return TRUE;
  1427. }
  1428.  
  1429. static boolean parse_immediate( struct translate_ctx *ctx )
  1430. {
  1431.    struct tgsi_full_immediate imm;
  1432.    uint advance;
  1433.    int type;
  1434.  
  1435.    if (*ctx->cur == '[') {
  1436.       uint uindex;
  1437.  
  1438.       ++ctx->cur;
  1439.  
  1440.       eat_opt_white( &ctx->cur );
  1441.       if (!parse_uint( &ctx->cur, &uindex )) {
  1442.          report_error( ctx, "Expected literal unsigned integer" );
  1443.          return FALSE;
  1444.       }
  1445.  
  1446.       if (uindex != ctx->num_immediates) {
  1447.          report_error( ctx, "Immediates must be sorted" );
  1448.          return FALSE;
  1449.       }
  1450.  
  1451.       eat_opt_white( &ctx->cur );
  1452.       if (*ctx->cur != ']') {
  1453.          report_error( ctx, "Expected `]'" );
  1454.          return FALSE;
  1455.       }
  1456.  
  1457.       ctx->cur++;
  1458.    }
  1459.  
  1460.    if (!eat_white( &ctx->cur )) {
  1461.       report_error( ctx, "Syntax error" );
  1462.       return FALSE;
  1463.    }
  1464.    for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) {
  1465.       if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
  1466.          break;
  1467.    }
  1468.    if (type == Elements(tgsi_immediate_type_names)) {
  1469.       report_error( ctx, "Expected immediate type" );
  1470.       return FALSE;
  1471.    }
  1472.  
  1473.    imm = tgsi_default_full_immediate();
  1474.    imm.Immediate.NrTokens += 4;
  1475.    imm.Immediate.DataType = type;
  1476.    parse_immediate_data(ctx, type, imm.u);
  1477.  
  1478.    advance = tgsi_build_full_immediate(
  1479.       &imm,
  1480.       ctx->tokens_cur,
  1481.       ctx->header,
  1482.       (uint) (ctx->tokens_end - ctx->tokens_cur) );
  1483.    if (advance == 0)
  1484.       return FALSE;
  1485.    ctx->tokens_cur += advance;
  1486.  
  1487.    ctx->num_immediates++;
  1488.  
  1489.    return TRUE;
  1490. }
  1491.  
  1492. static boolean
  1493. parse_primitive( const char **pcur, uint *primitive )
  1494. {
  1495.    uint i;
  1496.  
  1497.    for (i = 0; i < PIPE_PRIM_MAX; i++) {
  1498.       const char *cur = *pcur;
  1499.  
  1500.       if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
  1501.          *primitive = i;
  1502.          *pcur = cur;
  1503.          return TRUE;
  1504.       }
  1505.    }
  1506.    return FALSE;
  1507. }
  1508.  
  1509. static boolean
  1510. parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
  1511. {
  1512.    uint i;
  1513.  
  1514.    for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
  1515.       const char *cur = *pcur;
  1516.  
  1517.       if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
  1518.          *fs_coord_origin = i;
  1519.          *pcur = cur;
  1520.          return TRUE;
  1521.       }
  1522.    }
  1523.    return FALSE;
  1524. }
  1525.  
  1526. static boolean
  1527. parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
  1528. {
  1529.    uint i;
  1530.  
  1531.    for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
  1532.       const char *cur = *pcur;
  1533.  
  1534.       if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
  1535.          *fs_coord_pixel_center = i;
  1536.          *pcur = cur;
  1537.          return TRUE;
  1538.       }
  1539.    }
  1540.    return FALSE;
  1541. }
  1542.  
  1543.  
  1544. static boolean parse_property( struct translate_ctx *ctx )
  1545. {
  1546.    struct tgsi_full_property prop;
  1547.    uint property_name;
  1548.    uint values[8];
  1549.    uint advance;
  1550.    char id[64];
  1551.  
  1552.    if (!eat_white( &ctx->cur )) {
  1553.       report_error( ctx, "Syntax error" );
  1554.       return FALSE;
  1555.    }
  1556.    if (!parse_identifier( &ctx->cur, id )) {
  1557.       report_error( ctx, "Syntax error" );
  1558.       return FALSE;
  1559.    }
  1560.    for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
  1561.         ++property_name) {
  1562.       if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
  1563.          break;
  1564.       }
  1565.    }
  1566.    if (property_name >= TGSI_PROPERTY_COUNT) {
  1567.       debug_printf( "\nError: Unknown property : '%s'", id );
  1568.       return FALSE;
  1569.    }
  1570.  
  1571.    eat_opt_white( &ctx->cur );
  1572.    switch(property_name) {
  1573.    case TGSI_PROPERTY_GS_INPUT_PRIM:
  1574.    case TGSI_PROPERTY_GS_OUTPUT_PRIM:
  1575.       if (!parse_primitive(&ctx->cur, &values[0] )) {
  1576.          report_error( ctx, "Unknown primitive name as property!" );
  1577.          return FALSE;
  1578.       }
  1579.       if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
  1580.           ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
  1581.          ctx->implied_array_size = u_vertices_per_prim(values[0]);
  1582.       }
  1583.       break;
  1584.    case TGSI_PROPERTY_FS_COORD_ORIGIN:
  1585.       if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
  1586.          report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
  1587.          return FALSE;
  1588.       }
  1589.       break;
  1590.    case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
  1591.       if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
  1592.          report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
  1593.          return FALSE;
  1594.       }
  1595.       break;
  1596.    case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
  1597.    default:
  1598.       if (!parse_uint(&ctx->cur, &values[0] )) {
  1599.          report_error( ctx, "Expected unsigned integer as property!" );
  1600.          return FALSE;
  1601.       }
  1602.    }
  1603.  
  1604.    prop = tgsi_default_full_property();
  1605.    prop.Property.PropertyName = property_name;
  1606.    prop.Property.NrTokens += 1;
  1607.    prop.u[0].Data = values[0];
  1608.  
  1609.    advance = tgsi_build_full_property(
  1610.       &prop,
  1611.       ctx->tokens_cur,
  1612.       ctx->header,
  1613.       (uint) (ctx->tokens_end - ctx->tokens_cur) );
  1614.    if (advance == 0)
  1615.       return FALSE;
  1616.    ctx->tokens_cur += advance;
  1617.  
  1618.    return TRUE;
  1619. }
  1620.  
  1621.  
  1622. static boolean translate( struct translate_ctx *ctx )
  1623. {
  1624.    eat_opt_white( &ctx->cur );
  1625.    if (!parse_header( ctx ))
  1626.       return FALSE;
  1627.  
  1628.    while (*ctx->cur != '\0') {
  1629.       uint label_val = 0;
  1630.       if (!eat_white( &ctx->cur )) {
  1631.          report_error( ctx, "Syntax error" );
  1632.          return FALSE;
  1633.       }
  1634.  
  1635.       if (*ctx->cur == '\0')
  1636.          break;
  1637.       if (parse_label( ctx, &label_val )) {
  1638.          if (!parse_instruction( ctx, TRUE ))
  1639.             return FALSE;
  1640.       }
  1641.       else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
  1642.          if (!parse_declaration( ctx ))
  1643.             return FALSE;
  1644.       }
  1645.       else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
  1646.          if (!parse_immediate( ctx ))
  1647.             return FALSE;
  1648.       }
  1649.       else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
  1650.          if (!parse_property( ctx ))
  1651.             return FALSE;
  1652.       }
  1653.       else if (!parse_instruction( ctx, FALSE )) {
  1654.          return FALSE;
  1655.       }
  1656.    }
  1657.  
  1658.    return TRUE;
  1659. }
  1660.  
  1661. boolean
  1662. tgsi_text_translate(
  1663.    const char *text,
  1664.    struct tgsi_token *tokens,
  1665.    uint num_tokens )
  1666. {
  1667.    struct translate_ctx ctx = {0};
  1668.  
  1669.    ctx.text = text;
  1670.    ctx.cur = text;
  1671.    ctx.tokens = tokens;
  1672.    ctx.tokens_cur = tokens;
  1673.    ctx.tokens_end = tokens + num_tokens;
  1674.  
  1675.    if (!translate( &ctx ))
  1676.       return FALSE;
  1677.  
  1678.    return tgsi_sanity_check( tokens );
  1679. }
  1680.