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
42static boolean is_alpha_underscore( const char *cur )
43{
44   return
45      (*cur >= 'a' && *cur <= 'z') ||
46      (*cur >= 'A' && *cur <= 'Z') ||
47      *cur == '_';
48}
49
50static boolean is_digit( const char *cur )
51{
52   return *cur >= '0' && *cur <= '9';
53}
54
55static boolean is_digit_alpha_underscore( const char *cur )
56{
57   return is_digit( cur ) || is_alpha_underscore( cur );
58}
59
60static 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 */
71static int
72streq_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 */
89static 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 */
110static 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/* Return the array index that matches starting at *pcur, where the string at
123 * *pcur is terminated by a non-digit non-letter non-underscore.
124 * Returns -1 if no match is found.
125 *
126 * On success, the pointer to the first string is moved to the end of the read
127 * word.
128 */
129static int str_match_name_from_array(const char **pcur,
130                                     const char * const *array,
131                                     unsigned array_size)
132{
133   for (unsigned j = 0; j < array_size; ++j) {
134      if (str_match_nocase_whole(pcur, array[j]))
135         return j;
136   }
137   return -1;
138}
139
140/* Return the format corresponding to the name at *pcur.
141 * Returns -1 if there is no format name.
142 *
143 * On success, the pointer to the string is moved to the end of the read format
144 * name.
145 */
146static int str_match_format(const char **pcur)
147{
148   for (unsigned i = 0; i < PIPE_FORMAT_COUNT; i++) {
149      const struct util_format_description *desc =
150         util_format_description(i);
151      if (desc && str_match_nocase_whole(pcur, desc->name)) {
152         return i;
153      }
154   }
155   return -1;
156}
157
158/* Eat zero or more whitespaces.
159 */
160static void eat_opt_white( const char **pcur )
161{
162   while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
163      (*pcur)++;
164}
165
166/* Eat one or more whitespaces.
167 * Return TRUE if at least one whitespace eaten.
168 */
169static boolean eat_white( const char **pcur )
170{
171   const char *cur = *pcur;
172
173   eat_opt_white( pcur );
174   return *pcur > cur;
175}
176
177/* Parse unsigned integer.
178 * No checks for overflow.
179 */
180static boolean parse_uint( const char **pcur, uint *val )
181{
182   const char *cur = *pcur;
183
184   if (is_digit( cur )) {
185      *val = *cur++ - '0';
186      while (is_digit( cur ))
187         *val = *val * 10 + *cur++ - '0';
188      *pcur = cur;
189      return TRUE;
190   }
191   return FALSE;
192}
193
194static boolean parse_int( const char **pcur, int *val )
195{
196   const char *cur = *pcur;
197   int sign = (*cur == '-' ? -1 : 1);
198
199   if (*cur == '+' || *cur == '-')
200      cur++;
201
202   if (parse_uint(&cur, (uint *)val)) {
203      *val *= sign;
204      *pcur = cur;
205      return TRUE;
206   }
207
208   return FALSE;
209}
210
211static boolean parse_identifier( const char **pcur, char *ret, size_t len )
212{
213   const char *cur = *pcur;
214   size_t i = 0;
215   if (is_alpha_underscore( cur )) {
216      ret[i++] = *cur++;
217      while (is_alpha_underscore( cur ) || is_digit( cur )) {
218         if (i == len - 1)
219            return FALSE;
220         ret[i++] = *cur++;
221      }
222      ret[i++] = '\0';
223      *pcur = cur;
224      return TRUE;
225   }
226   return FALSE;
227}
228
229/* Parse floating point.
230 */
231static boolean parse_float( const char **pcur, float *val )
232{
233   const char *cur = *pcur;
234   boolean integral_part = FALSE;
235   boolean fractional_part = FALSE;
236
237   if (*cur == '0' && *(cur + 1) == 'x') {
238      union fi fi;
239      fi.ui = strtoul(cur, NULL, 16);
240      *val = fi.f;
241      cur += 10;
242      goto out;
243   }
244
245   *val = (float) atof( cur );
246   if (*cur == '-' || *cur == '+')
247      cur++;
248   if (is_digit( cur )) {
249      cur++;
250      integral_part = TRUE;
251      while (is_digit( cur ))
252         cur++;
253   }
254   if (*cur == '.') {
255      cur++;
256      if (is_digit( cur )) {
257         cur++;
258         fractional_part = TRUE;
259         while (is_digit( cur ))
260            cur++;
261      }
262   }
263   if (!integral_part && !fractional_part)
264      return FALSE;
265   if (uprcase( *cur ) == 'E') {
266      cur++;
267      if (*cur == '-' || *cur == '+')
268         cur++;
269      if (is_digit( cur )) {
270         cur++;
271         while (is_digit( cur ))
272            cur++;
273      }
274      else
275         return FALSE;
276   }
277
278out:
279   *pcur = cur;
280   return TRUE;
281}
282
283static boolean parse_double( const char **pcur, uint32_t *val0, uint32_t *val1)
284{
285   const char *cur = *pcur;
286   union {
287      double dval;
288      uint32_t uval[2];
289   } v;
290
291   v.dval = strtod(cur, (char**)pcur);
292   if (*pcur == cur)
293      return FALSE;
294
295   *val0 = v.uval[0];
296   *val1 = v.uval[1];
297
298   return TRUE;
299}
300
301static boolean parse_int64( const char **pcur, uint32_t *val0, uint32_t *val1)
302{
303   const char *cur = *pcur;
304   union {
305      int64_t i64val;
306      uint32_t uval[2];
307   } v;
308
309   v.i64val = strtoll(cur, (char**)pcur, 0);
310   if (*pcur == cur)
311      return FALSE;
312
313   *val0 = v.uval[0];
314   *val1 = v.uval[1];
315
316   return TRUE;
317}
318
319static boolean parse_uint64( const char **pcur, uint32_t *val0, uint32_t *val1)
320{
321   const char *cur = *pcur;
322   union {
323      uint64_t u64val;
324      uint32_t uval[2];
325   } v;
326
327   v.u64val = strtoull(cur, (char**)pcur, 0);
328   if (*pcur == cur)
329      return FALSE;
330
331   *val0 = v.uval[0];
332   *val1 = v.uval[1];
333
334   return TRUE;
335}
336
337struct translate_ctx
338{
339   const char *text;
340   const char *cur;
341   struct tgsi_token *tokens;
342   struct tgsi_token *tokens_cur;
343   struct tgsi_token *tokens_end;
344   struct tgsi_header *header;
345   unsigned processor : 4;
346   unsigned implied_array_size : 6;
347   unsigned num_immediates;
348};
349
350static void report_error( struct translate_ctx *ctx, const char *msg )
351{
352   int line = 1;
353   int column = 1;
354   const char *itr = ctx->text;
355
356   while (itr != ctx->cur) {
357      if (*itr == '\n') {
358         column = 1;
359         ++line;
360      }
361      ++column;
362      ++itr;
363   }
364
365   debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
366}
367
368/* Parse shader header.
369 * Return TRUE for one of the following headers.
370 *    FRAG
371 *    GEOM
372 *    VERT
373 */
374static boolean parse_header( struct translate_ctx *ctx )
375{
376   uint processor;
377
378   if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
379      processor = PIPE_SHADER_FRAGMENT;
380   else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
381      processor = PIPE_SHADER_VERTEX;
382   else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
383      processor = PIPE_SHADER_GEOMETRY;
384   else if (str_match_nocase_whole( &ctx->cur, "TESS_CTRL" ))
385      processor = PIPE_SHADER_TESS_CTRL;
386   else if (str_match_nocase_whole( &ctx->cur, "TESS_EVAL" ))
387      processor = PIPE_SHADER_TESS_EVAL;
388   else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
389      processor = PIPE_SHADER_COMPUTE;
390   else {
391      report_error( ctx, "Unknown header" );
392      return FALSE;
393   }
394
395   if (ctx->tokens_cur >= ctx->tokens_end)
396      return FALSE;
397   ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
398   *ctx->header = tgsi_build_header();
399
400   if (ctx->tokens_cur >= ctx->tokens_end)
401      return FALSE;
402   *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
403   ctx->processor = processor;
404
405   return TRUE;
406}
407
408static boolean parse_label( struct translate_ctx *ctx, uint *val )
409{
410   const char *cur = ctx->cur;
411
412   if (parse_uint( &cur, val )) {
413      eat_opt_white( &cur );
414      if (*cur == ':') {
415         cur++;
416         ctx->cur = cur;
417         return TRUE;
418      }
419   }
420   return FALSE;
421}
422
423static boolean
424parse_file( const char **pcur, uint *file )
425{
426   uint i;
427
428   for (i = 0; i < TGSI_FILE_COUNT; i++) {
429      const char *cur = *pcur;
430
431      if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
432         *pcur = cur;
433         *file = i;
434         return TRUE;
435      }
436   }
437   return FALSE;
438}
439
440static boolean
441parse_opt_writemask(
442   struct translate_ctx *ctx,
443   uint *writemask )
444{
445   const char *cur;
446
447   cur = ctx->cur;
448   eat_opt_white( &cur );
449   if (*cur == '.') {
450      cur++;
451      *writemask = TGSI_WRITEMASK_NONE;
452      eat_opt_white( &cur );
453      if (uprcase( *cur ) == 'X') {
454         cur++;
455         *writemask |= TGSI_WRITEMASK_X;
456      }
457      if (uprcase( *cur ) == 'Y') {
458         cur++;
459         *writemask |= TGSI_WRITEMASK_Y;
460      }
461      if (uprcase( *cur ) == 'Z') {
462         cur++;
463         *writemask |= TGSI_WRITEMASK_Z;
464      }
465      if (uprcase( *cur ) == 'W') {
466         cur++;
467         *writemask |= TGSI_WRITEMASK_W;
468      }
469
470      if (*writemask == TGSI_WRITEMASK_NONE) {
471         report_error( ctx, "Writemask expected" );
472         return FALSE;
473      }
474
475      ctx->cur = cur;
476   }
477   else {
478      *writemask = TGSI_WRITEMASK_XYZW;
479   }
480   return TRUE;
481}
482
483
484/* <register_file_bracket> ::= <file> `['
485 */
486static boolean
487parse_register_file_bracket(
488   struct translate_ctx *ctx,
489   uint *file )
490{
491   if (!parse_file( &ctx->cur, file )) {
492      report_error( ctx, "Unknown register file" );
493      return FALSE;
494   }
495   eat_opt_white( &ctx->cur );
496   if (*ctx->cur != '[') {
497      report_error( ctx, "Expected `['" );
498      return FALSE;
499   }
500   ctx->cur++;
501   return TRUE;
502}
503
504/* <register_file_bracket_index> ::= <register_file_bracket> <uint>
505 */
506static boolean
507parse_register_file_bracket_index(
508   struct translate_ctx *ctx,
509   uint *file,
510   int *index )
511{
512   uint uindex;
513
514   if (!parse_register_file_bracket( ctx, file ))
515      return FALSE;
516   eat_opt_white( &ctx->cur );
517   if (!parse_uint( &ctx->cur, &uindex )) {
518      report_error( ctx, "Expected literal unsigned integer" );
519      return FALSE;
520   }
521   *index = (int) uindex;
522   return TRUE;
523}
524
525/* Parse simple 1d register operand.
526 *    <register_dst> ::= <register_file_bracket_index> `]'
527 */
528static boolean
529parse_register_1d(struct translate_ctx *ctx,
530                  uint *file,
531                  int *index )
532{
533   if (!parse_register_file_bracket_index( ctx, file, index ))
534      return FALSE;
535   eat_opt_white( &ctx->cur );
536   if (*ctx->cur != ']') {
537      report_error( ctx, "Expected `]'" );
538      return FALSE;
539   }
540   ctx->cur++;
541   return TRUE;
542}
543
544struct parsed_bracket {
545   int index;
546
547   uint ind_file;
548   int ind_index;
549   uint ind_comp;
550   uint ind_array;
551};
552
553
554static boolean
555parse_register_bracket(
556   struct translate_ctx *ctx,
557   struct parsed_bracket *brackets)
558{
559   const char *cur;
560   uint uindex;
561
562   memset(brackets, 0, sizeof(struct parsed_bracket));
563
564   eat_opt_white( &ctx->cur );
565
566   cur = ctx->cur;
567   if (parse_file( &cur, &brackets->ind_file )) {
568      if (!parse_register_1d( ctx, &brackets->ind_file,
569                              &brackets->ind_index ))
570         return FALSE;
571      eat_opt_white( &ctx->cur );
572
573      if (*ctx->cur == '.') {
574         ctx->cur++;
575         eat_opt_white(&ctx->cur);
576
577         switch (uprcase(*ctx->cur)) {
578         case 'X':
579            brackets->ind_comp = TGSI_SWIZZLE_X;
580            break;
581         case 'Y':
582            brackets->ind_comp = TGSI_SWIZZLE_Y;
583            break;
584         case 'Z':
585            brackets->ind_comp = TGSI_SWIZZLE_Z;
586            break;
587         case 'W':
588            brackets->ind_comp = TGSI_SWIZZLE_W;
589            break;
590         default:
591            report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
592            return FALSE;
593         }
594         ctx->cur++;
595         eat_opt_white(&ctx->cur);
596      }
597
598      if (*ctx->cur == '+' || *ctx->cur == '-')
599         parse_int( &ctx->cur, &brackets->index );
600      else
601         brackets->index = 0;
602   }
603   else {
604      if (!parse_uint( &ctx->cur, &uindex )) {
605         report_error( ctx, "Expected literal unsigned integer" );
606         return FALSE;
607      }
608      brackets->index = (int) uindex;
609      brackets->ind_file = TGSI_FILE_NULL;
610      brackets->ind_index = 0;
611   }
612   eat_opt_white( &ctx->cur );
613   if (*ctx->cur != ']') {
614      report_error( ctx, "Expected `]'" );
615      return FALSE;
616   }
617   ctx->cur++;
618   if (*ctx->cur == '(') {
619      ctx->cur++;
620      eat_opt_white( &ctx->cur );
621      if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
622         report_error( ctx, "Expected literal unsigned integer" );
623         return FALSE;
624      }
625      eat_opt_white( &ctx->cur );
626      if (*ctx->cur != ')') {
627         report_error( ctx, "Expected `)'" );
628         return FALSE;
629      }
630      ctx->cur++;
631   }
632   return TRUE;
633}
634
635static boolean
636parse_opt_register_src_bracket(
637   struct translate_ctx *ctx,
638   struct parsed_bracket *brackets,
639   int *parsed_brackets)
640{
641   const char *cur = ctx->cur;
642
643   *parsed_brackets = 0;
644
645   eat_opt_white( &cur );
646   if (cur[0] == '[') {
647      ++cur;
648      ctx->cur = cur;
649
650      if (!parse_register_bracket(ctx, brackets))
651         return FALSE;
652
653      *parsed_brackets = 1;
654   }
655
656   return TRUE;
657}
658
659
660/* Parse source register operand.
661 *    <register_src> ::= <register_file_bracket_index> `]' |
662 *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
663 *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
664 *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
665 */
666static boolean
667parse_register_src(
668   struct translate_ctx *ctx,
669   uint *file,
670   struct parsed_bracket *brackets)
671{
672   brackets->ind_comp = TGSI_SWIZZLE_X;
673   if (!parse_register_file_bracket( ctx, file ))
674      return FALSE;
675   if (!parse_register_bracket( ctx, brackets ))
676       return FALSE;
677
678   return TRUE;
679}
680
681struct parsed_dcl_bracket {
682   uint first;
683   uint last;
684};
685
686static boolean
687parse_register_dcl_bracket(
688   struct translate_ctx *ctx,
689   struct parsed_dcl_bracket *bracket)
690{
691   uint uindex;
692   memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
693
694   eat_opt_white( &ctx->cur );
695
696   if (!parse_uint( &ctx->cur, &uindex )) {
697      /* it can be an empty bracket [] which means its range
698       * is from 0 to some implied size */
699      if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
700         bracket->first = 0;
701         bracket->last = ctx->implied_array_size - 1;
702         goto cleanup;
703      }
704      report_error( ctx, "Expected literal unsigned integer" );
705      return FALSE;
706   }
707   bracket->first = uindex;
708
709   eat_opt_white( &ctx->cur );
710
711   if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
712      uint uindex;
713
714      ctx->cur += 2;
715      eat_opt_white( &ctx->cur );
716      if (!parse_uint( &ctx->cur, &uindex )) {
717         report_error( ctx, "Expected literal integer" );
718         return FALSE;
719      }
720      bracket->last = (int) uindex;
721      eat_opt_white( &ctx->cur );
722   }
723   else {
724      bracket->last = bracket->first;
725   }
726
727cleanup:
728   if (*ctx->cur != ']') {
729      report_error( ctx, "Expected `]' or `..'" );
730      return FALSE;
731   }
732   ctx->cur++;
733   return TRUE;
734}
735
736/* Parse register declaration.
737 *    <register_dcl> ::= <register_file_bracket_index> `]' |
738 *                       <register_file_bracket_index> `..' <index> `]'
739 */
740static boolean
741parse_register_dcl(
742   struct translate_ctx *ctx,
743   uint *file,
744   struct parsed_dcl_bracket *brackets,
745   int *num_brackets)
746{
747   const char *cur;
748
749   *num_brackets = 0;
750
751   if (!parse_register_file_bracket( ctx, file ))
752      return FALSE;
753   if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
754      return FALSE;
755
756   *num_brackets = 1;
757
758   cur = ctx->cur;
759   eat_opt_white( &cur );
760
761   if (cur[0] == '[') {
762      bool is_in = *file == TGSI_FILE_INPUT;
763      bool is_out = *file == TGSI_FILE_OUTPUT;
764
765      ++cur;
766      ctx->cur = cur;
767      if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
768         return FALSE;
769      /* for geometry shader we don't really care about
770       * the first brackets it's always the size of the
771       * input primitive. so we want to declare just
772       * the index relevant to the semantics which is in
773       * the second bracket */
774
775      /* tessellation has similar constraints to geometry shader */
776      if ((ctx->processor == PIPE_SHADER_GEOMETRY && is_in) ||
777          (ctx->processor == PIPE_SHADER_TESS_EVAL && is_in) ||
778          (ctx->processor == PIPE_SHADER_TESS_CTRL && (is_in || is_out))) {
779         brackets[0] = brackets[1];
780         *num_brackets = 1;
781      } else {
782         *num_brackets = 2;
783      }
784   }
785
786   return TRUE;
787}
788
789
790/* Parse destination register operand.*/
791static boolean
792parse_register_dst(
793   struct translate_ctx *ctx,
794   uint *file,
795   struct parsed_bracket *brackets)
796{
797   brackets->ind_comp = TGSI_SWIZZLE_X;
798   if (!parse_register_file_bracket( ctx, file ))
799      return FALSE;
800   if (!parse_register_bracket( ctx, brackets ))
801       return FALSE;
802
803   return TRUE;
804}
805
806static boolean
807parse_dst_operand(
808   struct translate_ctx *ctx,
809   struct tgsi_full_dst_register *dst )
810{
811   uint file;
812   uint writemask;
813   const char *cur;
814   struct parsed_bracket bracket[2];
815   int parsed_opt_brackets;
816
817   if (!parse_register_dst( ctx, &file, &bracket[0] ))
818      return FALSE;
819   if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
820      return FALSE;
821
822   cur = ctx->cur;
823   eat_opt_white( &cur );
824
825   if (!parse_opt_writemask( ctx, &writemask ))
826      return FALSE;
827
828   dst->Register.File = file;
829   if (parsed_opt_brackets) {
830      dst->Register.Dimension = 1;
831      dst->Dimension.Indirect = 0;
832      dst->Dimension.Dimension = 0;
833      dst->Dimension.Index = bracket[0].index;
834
835      if (bracket[0].ind_file != TGSI_FILE_NULL) {
836         dst->Dimension.Indirect = 1;
837         dst->DimIndirect.File = bracket[0].ind_file;
838         dst->DimIndirect.Index = bracket[0].ind_index;
839         dst->DimIndirect.Swizzle = bracket[0].ind_comp;
840         dst->DimIndirect.ArrayID = bracket[0].ind_array;
841      }
842      bracket[0] = bracket[1];
843   }
844   dst->Register.Index = bracket[0].index;
845   dst->Register.WriteMask = writemask;
846   if (bracket[0].ind_file != TGSI_FILE_NULL) {
847      dst->Register.Indirect = 1;
848      dst->Indirect.File = bracket[0].ind_file;
849      dst->Indirect.Index = bracket[0].ind_index;
850      dst->Indirect.Swizzle = bracket[0].ind_comp;
851      dst->Indirect.ArrayID = bracket[0].ind_array;
852   }
853   return TRUE;
854}
855
856static boolean
857parse_optional_swizzle(
858   struct translate_ctx *ctx,
859   uint *swizzle,
860   boolean *parsed_swizzle,
861   int components)
862{
863   const char *cur = ctx->cur;
864
865   *parsed_swizzle = FALSE;
866
867   eat_opt_white( &cur );
868   if (*cur == '.') {
869      int i;
870
871      cur++;
872      eat_opt_white( &cur );
873      for (i = 0; i < components; i++) {
874         if (uprcase( *cur ) == 'X')
875            swizzle[i] = TGSI_SWIZZLE_X;
876         else if (uprcase( *cur ) == 'Y')
877            swizzle[i] = TGSI_SWIZZLE_Y;
878         else if (uprcase( *cur ) == 'Z')
879            swizzle[i] = TGSI_SWIZZLE_Z;
880         else if (uprcase( *cur ) == 'W')
881            swizzle[i] = TGSI_SWIZZLE_W;
882         else {
883	    report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
884	    return FALSE;
885         }
886         cur++;
887      }
888      *parsed_swizzle = TRUE;
889      ctx->cur = cur;
890   }
891   return TRUE;
892}
893
894static boolean
895parse_src_operand(
896   struct translate_ctx *ctx,
897   struct tgsi_full_src_register *src )
898{
899   uint file;
900   uint swizzle[4];
901   boolean parsed_swizzle;
902   struct parsed_bracket bracket[2];
903   int parsed_opt_brackets;
904
905   if (*ctx->cur == '-') {
906      ctx->cur++;
907      eat_opt_white( &ctx->cur );
908      src->Register.Negate = 1;
909   }
910
911   if (*ctx->cur == '|') {
912      ctx->cur++;
913      eat_opt_white( &ctx->cur );
914      src->Register.Absolute = 1;
915   }
916
917   if (!parse_register_src(ctx, &file, &bracket[0]))
918      return FALSE;
919   if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
920      return FALSE;
921
922   src->Register.File = file;
923   if (parsed_opt_brackets) {
924      src->Register.Dimension = 1;
925      src->Dimension.Indirect = 0;
926      src->Dimension.Dimension = 0;
927      src->Dimension.Index = bracket[0].index;
928      if (bracket[0].ind_file != TGSI_FILE_NULL) {
929         src->Dimension.Indirect = 1;
930         src->DimIndirect.File = bracket[0].ind_file;
931         src->DimIndirect.Index = bracket[0].ind_index;
932         src->DimIndirect.Swizzle = bracket[0].ind_comp;
933         src->DimIndirect.ArrayID = bracket[0].ind_array;
934      }
935      bracket[0] = bracket[1];
936   }
937   src->Register.Index = bracket[0].index;
938   if (bracket[0].ind_file != TGSI_FILE_NULL) {
939      src->Register.Indirect = 1;
940      src->Indirect.File = bracket[0].ind_file;
941      src->Indirect.Index = bracket[0].ind_index;
942      src->Indirect.Swizzle = bracket[0].ind_comp;
943      src->Indirect.ArrayID = bracket[0].ind_array;
944   }
945
946   /* Parse optional swizzle.
947    */
948   if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) {
949      if (parsed_swizzle) {
950         src->Register.SwizzleX = swizzle[0];
951         src->Register.SwizzleY = swizzle[1];
952         src->Register.SwizzleZ = swizzle[2];
953         src->Register.SwizzleW = swizzle[3];
954      }
955   }
956
957   if (src->Register.Absolute) {
958      eat_opt_white( &ctx->cur );
959      if (*ctx->cur != '|') {
960         report_error( ctx, "Expected `|'" );
961         return FALSE;
962      }
963      ctx->cur++;
964   }
965
966
967   return TRUE;
968}
969
970static boolean
971parse_texoffset_operand(
972   struct translate_ctx *ctx,
973   struct tgsi_texture_offset *src )
974{
975   uint file;
976   uint swizzle[3];
977   boolean parsed_swizzle;
978   struct parsed_bracket bracket;
979
980   if (!parse_register_src(ctx, &file, &bracket))
981      return FALSE;
982
983   src->File = file;
984   src->Index = bracket.index;
985
986   /* Parse optional swizzle.
987    */
988   if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 3 )) {
989      if (parsed_swizzle) {
990         src->SwizzleX = swizzle[0];
991         src->SwizzleY = swizzle[1];
992         src->SwizzleZ = swizzle[2];
993      }
994   }
995
996   return TRUE;
997}
998
999static boolean
1000match_inst(const char **pcur,
1001           unsigned *saturate,
1002           unsigned *precise,
1003           const struct tgsi_opcode_info *info)
1004{
1005   const char *cur = *pcur;
1006   const char *mnemonic = tgsi_get_opcode_name(info->opcode);
1007
1008   /* simple case: the whole string matches the instruction name */
1009   if (str_match_nocase_whole(&cur, mnemonic)) {
1010      *pcur = cur;
1011      *saturate = 0;
1012      *precise = 0;
1013      return TRUE;
1014   }
1015
1016   if (str_match_no_case(&cur, mnemonic)) {
1017      /* the instruction has a suffix, figure it out */
1018      if (str_match_no_case(&cur, "_SAT")) {
1019         *pcur = cur;
1020         *saturate = 1;
1021      }
1022
1023      if (str_match_no_case(&cur, "_PRECISE")) {
1024         *pcur = cur;
1025         *precise = 1;
1026      }
1027
1028      if (!is_digit_alpha_underscore(cur))
1029         return TRUE;
1030   }
1031
1032   return FALSE;
1033}
1034
1035static boolean
1036parse_instruction(
1037   struct translate_ctx *ctx,
1038   boolean has_label )
1039{
1040   int i;
1041   uint saturate = 0;
1042   uint precise = 0;
1043   const struct tgsi_opcode_info *info;
1044   struct tgsi_full_instruction inst;
1045   const char *cur;
1046   uint advance;
1047
1048   inst = tgsi_default_full_instruction();
1049
1050   /* Parse instruction name.
1051    */
1052   eat_opt_white( &ctx->cur );
1053   for (i = 0; i < TGSI_OPCODE_LAST; i++) {
1054      cur = ctx->cur;
1055
1056      info = tgsi_get_opcode_info( i );
1057      if (match_inst(&cur, &saturate, &precise, info)) {
1058         if (info->num_dst + info->num_src + info->is_tex == 0) {
1059            ctx->cur = cur;
1060            break;
1061         }
1062         else if (*cur == '\0' || eat_white( &cur )) {
1063            ctx->cur = cur;
1064            break;
1065         }
1066      }
1067   }
1068   if (i == TGSI_OPCODE_LAST) {
1069      if (has_label)
1070         report_error( ctx, "Unknown opcode" );
1071      else
1072         report_error( ctx, "Expected `DCL', `IMM' or a label" );
1073      return FALSE;
1074   }
1075
1076   inst.Instruction.Opcode = i;
1077   inst.Instruction.Saturate = saturate;
1078   inst.Instruction.Precise = precise;
1079   inst.Instruction.NumDstRegs = info->num_dst;
1080   inst.Instruction.NumSrcRegs = info->num_src;
1081
1082   if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
1083      /*
1084       * These are not considered tex opcodes here (no additional
1085       * target argument) however we're required to set the Texture
1086       * bit so we can set the number of tex offsets.
1087       */
1088      inst.Instruction.Texture = 1;
1089      inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
1090   }
1091
1092   if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) ||
1093       i == TGSI_OPCODE_RESQ) {
1094      inst.Instruction.Memory = 1;
1095      inst.Memory.Qualifier = 0;
1096   }
1097
1098   assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS);
1099   assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS);
1100
1101   /* Parse instruction operands.
1102    */
1103   for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
1104      if (i > 0) {
1105         eat_opt_white( &ctx->cur );
1106         if (*ctx->cur != ',') {
1107            report_error( ctx, "Expected `,'" );
1108            return FALSE;
1109         }
1110         ctx->cur++;
1111         eat_opt_white( &ctx->cur );
1112      }
1113
1114      if (i < info->num_dst) {
1115         if (!parse_dst_operand( ctx, &inst.Dst[i] ))
1116            return FALSE;
1117      }
1118      else if (i < info->num_dst + info->num_src) {
1119         if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
1120            return FALSE;
1121      }
1122      else {
1123         uint j;
1124
1125         for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
1126            if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
1127               inst.Instruction.Texture = 1;
1128               inst.Texture.Texture = j;
1129               break;
1130            }
1131         }
1132         if (j == TGSI_TEXTURE_COUNT) {
1133            report_error( ctx, "Expected texture target" );
1134            return FALSE;
1135         }
1136      }
1137   }
1138
1139   cur = ctx->cur;
1140   eat_opt_white( &cur );
1141   for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) {
1142         cur++;
1143         eat_opt_white( &cur );
1144         ctx->cur = cur;
1145         if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] ))
1146            return FALSE;
1147         cur = ctx->cur;
1148         eat_opt_white( &cur );
1149   }
1150   inst.Texture.NumOffsets = i;
1151
1152   cur = ctx->cur;
1153   eat_opt_white(&cur);
1154
1155   for (; inst.Instruction.Memory && *cur == ',';
1156        ctx->cur = cur, eat_opt_white(&cur)) {
1157      int j;
1158
1159      cur++;
1160      eat_opt_white(&cur);
1161
1162      j = str_match_name_from_array(&cur, tgsi_memory_names,
1163                                    ARRAY_SIZE(tgsi_memory_names));
1164      if (j >= 0) {
1165         inst.Memory.Qualifier |= 1U << j;
1166         continue;
1167      }
1168
1169      j = str_match_name_from_array(&cur, tgsi_texture_names,
1170                                    ARRAY_SIZE(tgsi_texture_names));
1171      if (j >= 0) {
1172         inst.Memory.Texture = j;
1173         continue;
1174      }
1175
1176      j = str_match_format(&cur);
1177      if (j >= 0) {
1178         inst.Memory.Format = j;
1179         continue;
1180      }
1181
1182      ctx->cur = cur;
1183      report_error(ctx, "Expected memory qualifier, texture target, or format\n");
1184      return FALSE;
1185   }
1186
1187   cur = ctx->cur;
1188   eat_opt_white( &cur );
1189   if (info->is_branch && *cur == ':') {
1190      uint target;
1191
1192      cur++;
1193      eat_opt_white( &cur );
1194      if (!parse_uint( &cur, &target )) {
1195         report_error( ctx, "Expected a label" );
1196         return FALSE;
1197      }
1198      inst.Instruction.Label = 1;
1199      inst.Label.Label = target;
1200      ctx->cur = cur;
1201   }
1202
1203   advance = tgsi_build_full_instruction(
1204      &inst,
1205      ctx->tokens_cur,
1206      ctx->header,
1207      (uint) (ctx->tokens_end - ctx->tokens_cur) );
1208   if (advance == 0)
1209      return FALSE;
1210   ctx->tokens_cur += advance;
1211
1212   return TRUE;
1213}
1214
1215/* parses a 4-touple of the form {x, y, z, w}
1216 * where x, y, z, w are numbers */
1217static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
1218                                    union tgsi_immediate_data *values)
1219{
1220   unsigned i;
1221   int ret;
1222
1223   eat_opt_white( &ctx->cur );
1224   if (*ctx->cur != '{') {
1225      report_error( ctx, "Expected `{'" );
1226      return FALSE;
1227   }
1228   ctx->cur++;
1229   for (i = 0; i < 4; i++) {
1230      eat_opt_white( &ctx->cur );
1231      if (i > 0) {
1232         if (*ctx->cur != ',') {
1233            report_error( ctx, "Expected `,'" );
1234            return FALSE;
1235         }
1236         ctx->cur++;
1237         eat_opt_white( &ctx->cur );
1238      }
1239
1240      switch (type) {
1241      case TGSI_IMM_FLOAT64:
1242         ret = parse_double(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1243         i++;
1244         break;
1245      case TGSI_IMM_INT64:
1246         ret = parse_int64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1247         i++;
1248         break;
1249      case TGSI_IMM_UINT64:
1250         ret = parse_uint64(&ctx->cur, &values[i].Uint, &values[i+1].Uint);
1251         i++;
1252         break;
1253      case TGSI_IMM_FLOAT32:
1254         ret = parse_float(&ctx->cur, &values[i].Float);
1255         break;
1256      case TGSI_IMM_UINT32:
1257         ret = parse_uint(&ctx->cur, &values[i].Uint);
1258         break;
1259      case TGSI_IMM_INT32:
1260         ret = parse_int(&ctx->cur, &values[i].Int);
1261         break;
1262      default:
1263         assert(0);
1264         ret = FALSE;
1265         break;
1266      }
1267
1268      if (!ret) {
1269         report_error( ctx, "Expected immediate constant" );
1270         return FALSE;
1271      }
1272   }
1273   eat_opt_white( &ctx->cur );
1274   if (*ctx->cur != '}') {
1275      report_error( ctx, "Expected `}'" );
1276      return FALSE;
1277   }
1278   ctx->cur++;
1279
1280   return TRUE;
1281}
1282
1283static boolean parse_declaration( struct translate_ctx *ctx )
1284{
1285   struct tgsi_full_declaration decl;
1286   uint file;
1287   struct parsed_dcl_bracket brackets[2];
1288   int num_brackets;
1289   uint writemask;
1290   const char *cur, *cur2;
1291   uint advance;
1292   boolean is_vs_input;
1293
1294   if (!eat_white( &ctx->cur )) {
1295      report_error( ctx, "Syntax error" );
1296      return FALSE;
1297   }
1298   if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1299      return FALSE;
1300   if (!parse_opt_writemask( ctx, &writemask ))
1301      return FALSE;
1302
1303   decl = tgsi_default_full_declaration();
1304   decl.Declaration.File = file;
1305   decl.Declaration.UsageMask = writemask;
1306
1307   if (num_brackets == 1) {
1308      decl.Range.First = brackets[0].first;
1309      decl.Range.Last = brackets[0].last;
1310   } else {
1311      decl.Range.First = brackets[1].first;
1312      decl.Range.Last = brackets[1].last;
1313
1314      decl.Declaration.Dimension = 1;
1315      decl.Dim.Index2D = brackets[0].first;
1316   }
1317
1318   is_vs_input = (file == TGSI_FILE_INPUT &&
1319                  ctx->processor == PIPE_SHADER_VERTEX);
1320
1321   cur = ctx->cur;
1322   eat_opt_white( &cur );
1323   if (*cur == ',') {
1324      cur2 = cur;
1325      cur2++;
1326      eat_opt_white( &cur2 );
1327      if (str_match_nocase_whole( &cur2, "ARRAY" )) {
1328         int arrayid;
1329         if (*cur2 != '(') {
1330            report_error( ctx, "Expected `('" );
1331            return FALSE;
1332         }
1333         cur2++;
1334         eat_opt_white( &cur2 );
1335         if (!parse_int( &cur2, &arrayid )) {
1336            report_error( ctx, "Expected `,'" );
1337            return FALSE;
1338         }
1339         eat_opt_white( &cur2 );
1340         if (*cur2 != ')') {
1341            report_error( ctx, "Expected `)'" );
1342            return FALSE;
1343         }
1344         cur2++;
1345         decl.Declaration.Array = 1;
1346         decl.Array.ArrayID = arrayid;
1347         ctx->cur = cur = cur2;
1348      }
1349   }
1350
1351   if (*cur == ',' && !is_vs_input) {
1352      uint i, j;
1353
1354      cur++;
1355      eat_opt_white( &cur );
1356      if (file == TGSI_FILE_IMAGE) {
1357         for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1358            if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1359               decl.Image.Resource = i;
1360               break;
1361            }
1362         }
1363         if (i == TGSI_TEXTURE_COUNT) {
1364            report_error(ctx, "Expected texture target");
1365            return FALSE;
1366         }
1367
1368         cur2 = cur;
1369         eat_opt_white(&cur2);
1370         while (*cur2 == ',') {
1371            cur2++;
1372            eat_opt_white(&cur2);
1373            if (str_match_nocase_whole(&cur2, "RAW")) {
1374               decl.Image.Raw = 1;
1375
1376            } else if (str_match_nocase_whole(&cur2, "WR")) {
1377               decl.Image.Writable = 1;
1378
1379            } else {
1380               int format = str_match_format(&cur2);
1381               if (format < 0)
1382                  break;
1383
1384               decl.Image.Format = format;
1385            }
1386            cur = cur2;
1387            eat_opt_white(&cur2);
1388         }
1389
1390         ctx->cur = cur;
1391
1392      } else if (file == TGSI_FILE_SAMPLER_VIEW) {
1393         for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1394            if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1395               decl.SamplerView.Resource = i;
1396               break;
1397            }
1398         }
1399         if (i == TGSI_TEXTURE_COUNT) {
1400            report_error(ctx, "Expected texture target");
1401            return FALSE;
1402         }
1403         eat_opt_white( &cur );
1404         if (*cur != ',') {
1405            report_error( ctx, "Expected `,'" );
1406            return FALSE;
1407         }
1408         ++cur;
1409         eat_opt_white( &cur );
1410         for (j = 0; j < 4; ++j) {
1411            for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) {
1412               if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) {
1413                  switch (j) {
1414                  case 0:
1415                     decl.SamplerView.ReturnTypeX = i;
1416                     break;
1417                  case 1:
1418                     decl.SamplerView.ReturnTypeY = i;
1419                     break;
1420                  case 2:
1421                     decl.SamplerView.ReturnTypeZ = i;
1422                     break;
1423                  case 3:
1424                     decl.SamplerView.ReturnTypeW = i;
1425                     break;
1426                  default:
1427                     assert(0);
1428                  }
1429                  break;
1430               }
1431            }
1432            if (i == TGSI_RETURN_TYPE_COUNT) {
1433               if (j == 0 || j >  2) {
1434                  report_error(ctx, "Expected type name");
1435                  return FALSE;
1436               }
1437               break;
1438            } else {
1439               cur2 = cur;
1440               eat_opt_white( &cur2 );
1441               if (*cur2 == ',') {
1442                  cur2++;
1443                  eat_opt_white( &cur2 );
1444                  cur = cur2;
1445                  continue;
1446               } else
1447                  break;
1448            }
1449         }
1450         if (j < 4) {
1451            decl.SamplerView.ReturnTypeY =
1452               decl.SamplerView.ReturnTypeZ =
1453               decl.SamplerView.ReturnTypeW =
1454               decl.SamplerView.ReturnTypeX;
1455         }
1456         ctx->cur = cur;
1457      } else if (file == TGSI_FILE_BUFFER) {
1458         if (str_match_nocase_whole(&cur, "ATOMIC")) {
1459            decl.Declaration.Atomic = 1;
1460            ctx->cur = cur;
1461         }
1462      } else if (file == TGSI_FILE_MEMORY) {
1463         if (str_match_nocase_whole(&cur, "GLOBAL")) {
1464            /* Note this is a no-op global is the default */
1465            decl.Declaration.MemType = TGSI_MEMORY_TYPE_GLOBAL;
1466            ctx->cur = cur;
1467         } else if (str_match_nocase_whole(&cur, "SHARED")) {
1468            decl.Declaration.MemType = TGSI_MEMORY_TYPE_SHARED;
1469            ctx->cur = cur;
1470         } else if (str_match_nocase_whole(&cur, "PRIVATE")) {
1471            decl.Declaration.MemType = TGSI_MEMORY_TYPE_PRIVATE;
1472            ctx->cur = cur;
1473         } else if (str_match_nocase_whole(&cur, "INPUT")) {
1474            decl.Declaration.MemType = TGSI_MEMORY_TYPE_INPUT;
1475            ctx->cur = cur;
1476         }
1477      } else {
1478         if (str_match_nocase_whole(&cur, "LOCAL")) {
1479            decl.Declaration.Local = 1;
1480            ctx->cur = cur;
1481         }
1482
1483         cur = ctx->cur;
1484         eat_opt_white( &cur );
1485         if (*cur == ',') {
1486            cur++;
1487            eat_opt_white( &cur );
1488
1489            for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1490               if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
1491                  uint index;
1492
1493                  cur2 = cur;
1494                  eat_opt_white( &cur2 );
1495                  if (*cur2 == '[') {
1496                     cur2++;
1497                     eat_opt_white( &cur2 );
1498                     if (!parse_uint( &cur2, &index )) {
1499                        report_error( ctx, "Expected literal integer" );
1500                        return FALSE;
1501                     }
1502                     eat_opt_white( &cur2 );
1503                     if (*cur2 != ']') {
1504                        report_error( ctx, "Expected `]'" );
1505                        return FALSE;
1506                     }
1507                     cur2++;
1508
1509                     decl.Semantic.Index = index;
1510
1511                     cur = cur2;
1512                  }
1513
1514                  decl.Declaration.Semantic = 1;
1515                  decl.Semantic.Name = i;
1516
1517                  ctx->cur = cur;
1518                  break;
1519               }
1520            }
1521         }
1522      }
1523   }
1524
1525   cur = ctx->cur;
1526   eat_opt_white( &cur );
1527   if (*cur == ',' &&
1528       file == TGSI_FILE_OUTPUT && ctx->processor == PIPE_SHADER_GEOMETRY) {
1529      cur++;
1530      eat_opt_white(&cur);
1531      if (str_match_nocase_whole(&cur, "STREAM")) {
1532         uint stream[4];
1533
1534         eat_opt_white(&cur);
1535         if (*cur != '(') {
1536            report_error(ctx, "Expected '('");
1537            return FALSE;
1538         }
1539         cur++;
1540
1541         for (int i = 0; i < 4; ++i) {
1542            eat_opt_white(&cur);
1543            if (!parse_uint(&cur, &stream[i])) {
1544               report_error(ctx, "Expected literal integer");
1545               return FALSE;
1546            }
1547
1548            eat_opt_white(&cur);
1549            if (i < 3) {
1550               if (*cur != ',') {
1551                  report_error(ctx, "Expected ','");
1552                  return FALSE;
1553               }
1554               cur++;
1555            }
1556         }
1557
1558         if (*cur != ')') {
1559            report_error(ctx, "Expected ')'");
1560            return FALSE;
1561         }
1562         cur++;
1563
1564         decl.Semantic.StreamX = stream[0];
1565         decl.Semantic.StreamY = stream[1];
1566         decl.Semantic.StreamZ = stream[2];
1567         decl.Semantic.StreamW = stream[3];
1568
1569         ctx->cur = cur;
1570      }
1571   }
1572
1573   cur = ctx->cur;
1574   eat_opt_white( &cur );
1575   if (*cur == ',' && !is_vs_input) {
1576      uint i;
1577
1578      cur++;
1579      eat_opt_white( &cur );
1580      for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1581         if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
1582            decl.Declaration.Interpolate = 1;
1583            decl.Interp.Interpolate = i;
1584
1585            ctx->cur = cur;
1586            break;
1587         }
1588      }
1589   }
1590
1591   cur = ctx->cur;
1592   eat_opt_white( &cur );
1593   if (*cur == ',' && !is_vs_input) {
1594      uint i;
1595
1596      cur++;
1597      eat_opt_white( &cur );
1598      for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) {
1599         if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) {
1600            decl.Interp.Location = i;
1601
1602            ctx->cur = cur;
1603            break;
1604         }
1605      }
1606   }
1607
1608   cur = ctx->cur;
1609   eat_opt_white( &cur );
1610   if (*cur == ',' && !is_vs_input) {
1611      cur++;
1612      eat_opt_white( &cur );
1613      if (str_match_nocase_whole( &cur, tgsi_invariant_name )) {
1614         decl.Declaration.Invariant = 1;
1615         ctx->cur = cur;
1616      } else {
1617         report_error( ctx, "Expected semantic, interpolate attribute, or invariant ");
1618         return FALSE;
1619      }
1620   }
1621
1622   advance = tgsi_build_full_declaration(
1623      &decl,
1624      ctx->tokens_cur,
1625      ctx->header,
1626      (uint) (ctx->tokens_end - ctx->tokens_cur) );
1627
1628   if (advance == 0)
1629      return FALSE;
1630   ctx->tokens_cur += advance;
1631
1632   return TRUE;
1633}
1634
1635static boolean parse_immediate( struct translate_ctx *ctx )
1636{
1637   struct tgsi_full_immediate imm;
1638   uint advance;
1639   uint type;
1640
1641   if (*ctx->cur == '[') {
1642      uint uindex;
1643
1644      ++ctx->cur;
1645
1646      eat_opt_white( &ctx->cur );
1647      if (!parse_uint( &ctx->cur, &uindex )) {
1648         report_error( ctx, "Expected literal unsigned integer" );
1649         return FALSE;
1650      }
1651
1652      if (uindex != ctx->num_immediates) {
1653         report_error( ctx, "Immediates must be sorted" );
1654         return FALSE;
1655      }
1656
1657      eat_opt_white( &ctx->cur );
1658      if (*ctx->cur != ']') {
1659         report_error( ctx, "Expected `]'" );
1660         return FALSE;
1661      }
1662
1663      ctx->cur++;
1664   }
1665
1666   if (!eat_white( &ctx->cur )) {
1667      report_error( ctx, "Syntax error" );
1668      return FALSE;
1669   }
1670   for (type = 0; type < ARRAY_SIZE(tgsi_immediate_type_names); ++type) {
1671      if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
1672         break;
1673   }
1674   if (type == ARRAY_SIZE(tgsi_immediate_type_names)) {
1675      report_error( ctx, "Expected immediate type" );
1676      return FALSE;
1677   }
1678
1679   imm = tgsi_default_full_immediate();
1680   imm.Immediate.NrTokens += 4;
1681   imm.Immediate.DataType = type;
1682   parse_immediate_data(ctx, type, imm.u);
1683
1684   advance = tgsi_build_full_immediate(
1685      &imm,
1686      ctx->tokens_cur,
1687      ctx->header,
1688      (uint) (ctx->tokens_end - ctx->tokens_cur) );
1689   if (advance == 0)
1690      return FALSE;
1691   ctx->tokens_cur += advance;
1692
1693   ctx->num_immediates++;
1694
1695   return TRUE;
1696}
1697
1698static boolean
1699parse_primitive( const char **pcur, uint *primitive )
1700{
1701   uint i;
1702
1703   for (i = 0; i < PIPE_PRIM_MAX; i++) {
1704      const char *cur = *pcur;
1705
1706      if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
1707         *primitive = i;
1708         *pcur = cur;
1709         return TRUE;
1710      }
1711   }
1712   return FALSE;
1713}
1714
1715static boolean
1716parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1717{
1718   uint i;
1719
1720   for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_origin_names); i++) {
1721      const char *cur = *pcur;
1722
1723      if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
1724         *fs_coord_origin = i;
1725         *pcur = cur;
1726         return TRUE;
1727      }
1728   }
1729   return FALSE;
1730}
1731
1732static boolean
1733parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1734{
1735   uint i;
1736
1737   for (i = 0; i < ARRAY_SIZE(tgsi_fs_coord_pixel_center_names); i++) {
1738      const char *cur = *pcur;
1739
1740      if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1741         *fs_coord_pixel_center = i;
1742         *pcur = cur;
1743         return TRUE;
1744      }
1745   }
1746   return FALSE;
1747}
1748
1749static boolean
1750parse_property_next_shader( const char **pcur, uint *next_shader )
1751{
1752   uint i;
1753
1754   for (i = 0; i < ARRAY_SIZE(tgsi_processor_type_names); i++) {
1755      const char *cur = *pcur;
1756
1757      if (str_match_nocase_whole( &cur, tgsi_processor_type_names[i])) {
1758         *next_shader = i;
1759         *pcur = cur;
1760         return TRUE;
1761      }
1762   }
1763   return FALSE;
1764}
1765
1766static boolean parse_property( struct translate_ctx *ctx )
1767{
1768   struct tgsi_full_property prop;
1769   uint property_name;
1770   uint values[8];
1771   uint advance;
1772   char id[64];
1773
1774   if (!eat_white( &ctx->cur )) {
1775      report_error( ctx, "Syntax error" );
1776      return FALSE;
1777   }
1778   if (!parse_identifier( &ctx->cur, id, sizeof(id) )) {
1779      report_error( ctx, "Syntax error" );
1780      return FALSE;
1781   }
1782   for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1783        ++property_name) {
1784      if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1785         break;
1786      }
1787   }
1788   if (property_name >= TGSI_PROPERTY_COUNT) {
1789      debug_printf( "\nError: Unknown property : '%s'", id );
1790      return FALSE;
1791   }
1792
1793   eat_opt_white( &ctx->cur );
1794   switch(property_name) {
1795   case TGSI_PROPERTY_GS_INPUT_PRIM:
1796   case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1797      if (!parse_primitive(&ctx->cur, &values[0] )) {
1798         report_error( ctx, "Unknown primitive name as property!" );
1799         return FALSE;
1800      }
1801      if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1802          ctx->processor == PIPE_SHADER_GEOMETRY) {
1803         ctx->implied_array_size = u_vertices_per_prim(values[0]);
1804      }
1805      break;
1806   case TGSI_PROPERTY_FS_COORD_ORIGIN:
1807      if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1808         report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1809         return FALSE;
1810      }
1811      break;
1812   case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1813      if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1814         report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1815         return FALSE;
1816      }
1817      break;
1818   case TGSI_PROPERTY_NEXT_SHADER:
1819      if (!parse_property_next_shader(&ctx->cur, &values[0] )) {
1820         report_error( ctx, "Unknown next shader property value." );
1821         return FALSE;
1822      }
1823      break;
1824   case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1825   default:
1826      if (!parse_uint(&ctx->cur, &values[0] )) {
1827         report_error( ctx, "Expected unsigned integer as property!" );
1828         return FALSE;
1829      }
1830   }
1831
1832   prop = tgsi_default_full_property();
1833   prop.Property.PropertyName = property_name;
1834   prop.Property.NrTokens += 1;
1835   prop.u[0].Data = values[0];
1836
1837   advance = tgsi_build_full_property(
1838      &prop,
1839      ctx->tokens_cur,
1840      ctx->header,
1841      (uint) (ctx->tokens_end - ctx->tokens_cur) );
1842   if (advance == 0)
1843      return FALSE;
1844   ctx->tokens_cur += advance;
1845
1846   return TRUE;
1847}
1848
1849
1850static boolean translate( struct translate_ctx *ctx )
1851{
1852   eat_opt_white( &ctx->cur );
1853   if (!parse_header( ctx ))
1854      return FALSE;
1855
1856   if (ctx->processor == PIPE_SHADER_TESS_CTRL ||
1857       ctx->processor == PIPE_SHADER_TESS_EVAL)
1858       ctx->implied_array_size = 32;
1859
1860   while (*ctx->cur != '\0') {
1861      uint label_val = 0;
1862      if (!eat_white( &ctx->cur )) {
1863         report_error( ctx, "Syntax error" );
1864         return FALSE;
1865      }
1866
1867      if (*ctx->cur == '\0')
1868         break;
1869      if (parse_label( ctx, &label_val )) {
1870         if (!parse_instruction( ctx, TRUE ))
1871            return FALSE;
1872      }
1873      else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
1874         if (!parse_declaration( ctx ))
1875            return FALSE;
1876      }
1877      else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
1878         if (!parse_immediate( ctx ))
1879            return FALSE;
1880      }
1881      else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
1882         if (!parse_property( ctx ))
1883            return FALSE;
1884      }
1885      else if (!parse_instruction( ctx, FALSE )) {
1886         return FALSE;
1887      }
1888   }
1889
1890   return TRUE;
1891}
1892
1893boolean
1894tgsi_text_translate(
1895   const char *text,
1896   struct tgsi_token *tokens,
1897   uint num_tokens )
1898{
1899   struct translate_ctx ctx = {0};
1900
1901   ctx.text = text;
1902   ctx.cur = text;
1903   ctx.tokens = tokens;
1904   ctx.tokens_cur = tokens;
1905   ctx.tokens_end = tokens + num_tokens;
1906
1907   if (!translate( &ctx ))
1908      return FALSE;
1909
1910   return tgsi_sanity_check( tokens );
1911}
1912