OSDN Git Service

u_vbuf: fix index buffer leak
[android-x86/external-mesa.git] / src / gallium / auxiliary / tgsi / tgsi_text.c
1 /**************************************************************************
2  * 
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 struct translate_ctx
236 {
237    const char *text;
238    const char *cur;
239    struct tgsi_token *tokens;
240    struct tgsi_token *tokens_cur;
241    struct tgsi_token *tokens_end;
242    struct tgsi_header *header;
243    unsigned processor : 4;
244    int implied_array_size : 5;
245    unsigned num_immediates;
246 };
247
248 static void report_error( struct translate_ctx *ctx, const char *msg )
249 {
250    int line = 1;
251    int column = 1;
252    const char *itr = ctx->text;
253
254    while (itr != ctx->cur) {
255       if (*itr == '\n') {
256          column = 1;
257          ++line;
258       }
259       ++column;
260       ++itr;
261    }
262
263    debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
264 }
265
266 /* Parse shader header.
267  * Return TRUE for one of the following headers.
268  *    FRAG
269  *    GEOM
270  *    VERT
271  */
272 static boolean parse_header( struct translate_ctx *ctx )
273 {
274    uint processor;
275
276    if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
277       processor = TGSI_PROCESSOR_FRAGMENT;
278    else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
279       processor = TGSI_PROCESSOR_VERTEX;
280    else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
281       processor = TGSI_PROCESSOR_GEOMETRY;
282    else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
283       processor = TGSI_PROCESSOR_COMPUTE;
284    else {
285       report_error( ctx, "Unknown header" );
286       return FALSE;
287    }
288
289    if (ctx->tokens_cur >= ctx->tokens_end)
290       return FALSE;
291    ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
292    *ctx->header = tgsi_build_header();
293
294    if (ctx->tokens_cur >= ctx->tokens_end)
295       return FALSE;
296    *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
297    ctx->processor = processor;
298
299    return TRUE;
300 }
301
302 static boolean parse_label( struct translate_ctx *ctx, uint *val )
303 {
304    const char *cur = ctx->cur;
305
306    if (parse_uint( &cur, val )) {
307       eat_opt_white( &cur );
308       if (*cur == ':') {
309          cur++;
310          ctx->cur = cur;
311          return TRUE;
312       }
313    }
314    return FALSE;
315 }
316
317 static boolean
318 parse_file( const char **pcur, uint *file )
319 {
320    uint i;
321
322    for (i = 0; i < TGSI_FILE_COUNT; i++) {
323       const char *cur = *pcur;
324
325       if (str_match_nocase_whole( &cur, tgsi_file_names[i] )) {
326          *pcur = cur;
327          *file = i;
328          return TRUE;
329       }
330    }
331    return FALSE;
332 }
333
334 static boolean
335 parse_opt_writemask(
336    struct translate_ctx *ctx,
337    uint *writemask )
338 {
339    const char *cur;
340
341    cur = ctx->cur;
342    eat_opt_white( &cur );
343    if (*cur == '.') {
344       cur++;
345       *writemask = TGSI_WRITEMASK_NONE;
346       eat_opt_white( &cur );
347       if (uprcase( *cur ) == 'X') {
348          cur++;
349          *writemask |= TGSI_WRITEMASK_X;
350       }
351       if (uprcase( *cur ) == 'Y') {
352          cur++;
353          *writemask |= TGSI_WRITEMASK_Y;
354       }
355       if (uprcase( *cur ) == 'Z') {
356          cur++;
357          *writemask |= TGSI_WRITEMASK_Z;
358       }
359       if (uprcase( *cur ) == 'W') {
360          cur++;
361          *writemask |= TGSI_WRITEMASK_W;
362       }
363
364       if (*writemask == TGSI_WRITEMASK_NONE) {
365          report_error( ctx, "Writemask expected" );
366          return FALSE;
367       }
368
369       ctx->cur = cur;
370    }
371    else {
372       *writemask = TGSI_WRITEMASK_XYZW;
373    }
374    return TRUE;
375 }
376
377
378 /* <register_file_bracket> ::= <file> `['
379  */
380 static boolean
381 parse_register_file_bracket(
382    struct translate_ctx *ctx,
383    uint *file )
384 {
385    if (!parse_file( &ctx->cur, file )) {
386       report_error( ctx, "Unknown register file" );
387       return FALSE;
388    }
389    eat_opt_white( &ctx->cur );
390    if (*ctx->cur != '[') {
391       report_error( ctx, "Expected `['" );
392       return FALSE;
393    }
394    ctx->cur++;
395    return TRUE;
396 }
397
398 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
399  */
400 static boolean
401 parse_register_file_bracket_index(
402    struct translate_ctx *ctx,
403    uint *file,
404    int *index )
405 {
406    uint uindex;
407
408    if (!parse_register_file_bracket( ctx, file ))
409       return FALSE;
410    eat_opt_white( &ctx->cur );
411    if (!parse_uint( &ctx->cur, &uindex )) {
412       report_error( ctx, "Expected literal unsigned integer" );
413       return FALSE;
414    }
415    *index = (int) uindex;
416    return TRUE;
417 }
418
419 /* Parse simple 1d register operand.
420  *    <register_dst> ::= <register_file_bracket_index> `]'
421  */
422 static boolean
423 parse_register_1d(struct translate_ctx *ctx,
424                   uint *file,
425                   int *index )
426 {
427    if (!parse_register_file_bracket_index( ctx, file, index ))
428       return FALSE;
429    eat_opt_white( &ctx->cur );
430    if (*ctx->cur != ']') {
431       report_error( ctx, "Expected `]'" );
432       return FALSE;
433    }
434    ctx->cur++;
435    return TRUE;
436 }
437
438 struct parsed_bracket {
439    int index;
440
441    uint ind_file;
442    int ind_index;
443    uint ind_comp;
444    uint ind_array;
445 };
446
447
448 static boolean
449 parse_register_bracket(
450    struct translate_ctx *ctx,
451    struct parsed_bracket *brackets)
452 {
453    const char *cur;
454    uint uindex;
455
456    memset(brackets, 0, sizeof(struct parsed_bracket));
457
458    eat_opt_white( &ctx->cur );
459
460    cur = ctx->cur;
461    if (parse_file( &cur, &brackets->ind_file )) {
462       if (!parse_register_1d( ctx, &brackets->ind_file,
463                               &brackets->ind_index ))
464          return FALSE;
465       eat_opt_white( &ctx->cur );
466
467       if (*ctx->cur == '.') {
468          ctx->cur++;
469          eat_opt_white(&ctx->cur);
470
471          switch (uprcase(*ctx->cur)) {
472          case 'X':
473             brackets->ind_comp = TGSI_SWIZZLE_X;
474             break;
475          case 'Y':
476             brackets->ind_comp = TGSI_SWIZZLE_Y;
477             break;
478          case 'Z':
479             brackets->ind_comp = TGSI_SWIZZLE_Z;
480             break;
481          case 'W':
482             brackets->ind_comp = TGSI_SWIZZLE_W;
483             break;
484          default:
485             report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
486             return FALSE;
487          }
488          ctx->cur++;
489          eat_opt_white(&ctx->cur);
490       }
491
492       if (*ctx->cur == '+' || *ctx->cur == '-')
493          parse_int( &ctx->cur, &brackets->index );
494       else
495          brackets->index = 0;
496    }
497    else {
498       if (!parse_uint( &ctx->cur, &uindex )) {
499          report_error( ctx, "Expected literal unsigned integer" );
500          return FALSE;
501       }
502       brackets->index = (int) uindex;
503       brackets->ind_file = TGSI_FILE_NULL;
504       brackets->ind_index = 0;
505    }
506    eat_opt_white( &ctx->cur );
507    if (*ctx->cur != ']') {
508       report_error( ctx, "Expected `]'" );
509       return FALSE;
510    }
511    ctx->cur++;
512    if (*ctx->cur == '(') {
513       ctx->cur++;
514       eat_opt_white( &ctx->cur );
515       if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
516          report_error( ctx, "Expected literal unsigned integer" );
517          return FALSE;
518       }
519       eat_opt_white( &ctx->cur );
520       if (*ctx->cur != ')') {
521          report_error( ctx, "Expected `)'" );
522          return FALSE;
523       }
524       ctx->cur++;
525    }
526    return TRUE;
527 }
528
529 static boolean
530 parse_opt_register_src_bracket(
531    struct translate_ctx *ctx,
532    struct parsed_bracket *brackets,
533    int *parsed_brackets)
534 {
535    const char *cur = ctx->cur;
536
537    *parsed_brackets = 0;
538
539    eat_opt_white( &cur );
540    if (cur[0] == '[') {
541       ++cur;
542       ctx->cur = cur;
543
544       if (!parse_register_bracket(ctx, brackets))
545          return FALSE;
546
547       *parsed_brackets = 1;
548    }
549
550    return TRUE;
551 }
552
553
554 /* Parse source register operand.
555  *    <register_src> ::= <register_file_bracket_index> `]' |
556  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
557  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
558  *                       <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
559  */
560 static boolean
561 parse_register_src(
562    struct translate_ctx *ctx,
563    uint *file,
564    struct parsed_bracket *brackets)
565 {
566    brackets->ind_comp = TGSI_SWIZZLE_X;
567    if (!parse_register_file_bracket( ctx, file ))
568       return FALSE;
569    if (!parse_register_bracket( ctx, brackets ))
570        return FALSE;
571
572    return TRUE;
573 }
574
575 struct parsed_dcl_bracket {
576    uint first;
577    uint last;
578 };
579
580 static boolean
581 parse_register_dcl_bracket(
582    struct translate_ctx *ctx,
583    struct parsed_dcl_bracket *bracket)
584 {
585    uint uindex;
586    memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
587
588    eat_opt_white( &ctx->cur );
589
590    if (!parse_uint( &ctx->cur, &uindex )) {
591       /* it can be an empty bracket [] which means its range
592        * is from 0 to some implied size */
593       if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
594          bracket->first = 0;
595          bracket->last = ctx->implied_array_size - 1;
596          goto cleanup;
597       }
598       report_error( ctx, "Expected literal unsigned integer" );
599       return FALSE;
600    }
601    bracket->first = uindex;
602
603    eat_opt_white( &ctx->cur );
604
605    if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
606       uint uindex;
607
608       ctx->cur += 2;
609       eat_opt_white( &ctx->cur );
610       if (!parse_uint( &ctx->cur, &uindex )) {
611          report_error( ctx, "Expected literal integer" );
612          return FALSE;
613       }
614       bracket->last = (int) uindex;
615       eat_opt_white( &ctx->cur );
616    }
617    else {
618       bracket->last = bracket->first;
619    }
620
621 cleanup:
622    if (*ctx->cur != ']') {
623       report_error( ctx, "Expected `]' or `..'" );
624       return FALSE;
625    }
626    ctx->cur++;
627    return TRUE;
628 }
629
630 /* Parse register declaration.
631  *    <register_dcl> ::= <register_file_bracket_index> `]' |
632  *                       <register_file_bracket_index> `..' <index> `]'
633  */
634 static boolean
635 parse_register_dcl(
636    struct translate_ctx *ctx,
637    uint *file,
638    struct parsed_dcl_bracket *brackets,
639    int *num_brackets)
640 {
641    const char *cur;
642
643    *num_brackets = 0;
644
645    if (!parse_register_file_bracket( ctx, file ))
646       return FALSE;
647    if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
648       return FALSE;
649
650    *num_brackets = 1;
651
652    cur = ctx->cur;
653    eat_opt_white( &cur );
654
655    if (cur[0] == '[') {
656       ++cur;
657       ctx->cur = cur;
658       if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
659          return FALSE;
660       /* for geometry shader we don't really care about
661        * the first brackets it's always the size of the
662        * input primitive. so we want to declare just
663        * the index relevant to the semantics which is in
664        * the second bracket */
665       if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
666          brackets[0] = brackets[1];
667          *num_brackets = 1;
668       } else {
669          *num_brackets = 2;
670       }
671    }
672
673    return TRUE;
674 }
675
676
677 /* Parse destination register operand.*/
678 static boolean
679 parse_register_dst(
680    struct translate_ctx *ctx,
681    uint *file,
682    struct parsed_bracket *brackets)
683 {
684    brackets->ind_comp = TGSI_SWIZZLE_X;
685    if (!parse_register_file_bracket( ctx, file ))
686       return FALSE;
687    if (!parse_register_bracket( ctx, brackets ))
688        return FALSE;
689
690    return TRUE;
691 }
692
693 static boolean
694 parse_dst_operand(
695    struct translate_ctx *ctx,
696    struct tgsi_full_dst_register *dst )
697 {
698    uint file;
699    uint writemask;
700    const char *cur;
701    struct parsed_bracket bracket[2];
702    int parsed_opt_brackets;
703
704    if (!parse_register_dst( ctx, &file, &bracket[0] ))
705       return FALSE;
706    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
707       return FALSE;
708
709    cur = ctx->cur;
710    eat_opt_white( &cur );
711
712    if (!parse_opt_writemask( ctx, &writemask ))
713       return FALSE;
714
715    dst->Register.File = file;
716    if (parsed_opt_brackets) {
717       dst->Register.Dimension = 1;
718       dst->Dimension.Indirect = 0;
719       dst->Dimension.Dimension = 0;
720       dst->Dimension.Index = bracket[0].index;
721       bracket[0] = bracket[1];
722    }
723    dst->Register.Index = bracket[0].index;
724    dst->Register.WriteMask = writemask;
725    if (bracket[0].ind_file != TGSI_FILE_NULL) {
726       dst->Register.Indirect = 1;
727       dst->Indirect.File = bracket[0].ind_file;
728       dst->Indirect.Index = bracket[0].ind_index;
729       dst->Indirect.Swizzle = bracket[0].ind_comp;
730       dst->Indirect.ArrayID = bracket[0].ind_array;
731    }
732    return TRUE;
733 }
734
735 static boolean
736 parse_optional_swizzle(
737    struct translate_ctx *ctx,
738    uint swizzle[4],
739    boolean *parsed_swizzle )
740 {
741    const char *cur = ctx->cur;
742
743    *parsed_swizzle = FALSE;
744
745    eat_opt_white( &cur );
746    if (*cur == '.') {
747       uint i;
748
749       cur++;
750       eat_opt_white( &cur );
751       for (i = 0; i < 4; i++) {
752          if (uprcase( *cur ) == 'X')
753             swizzle[i] = TGSI_SWIZZLE_X;
754          else if (uprcase( *cur ) == 'Y')
755             swizzle[i] = TGSI_SWIZZLE_Y;
756          else if (uprcase( *cur ) == 'Z')
757             swizzle[i] = TGSI_SWIZZLE_Z;
758          else if (uprcase( *cur ) == 'W')
759             swizzle[i] = TGSI_SWIZZLE_W;
760          else {
761             report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
762             return FALSE;
763          }
764          cur++;
765       }
766       *parsed_swizzle = TRUE;
767       ctx->cur = cur;
768    }
769    return TRUE;
770 }
771
772 static boolean
773 parse_src_operand(
774    struct translate_ctx *ctx,
775    struct tgsi_full_src_register *src )
776 {
777    uint file;
778    uint swizzle[4];
779    boolean parsed_swizzle;
780    struct parsed_bracket bracket[2];
781    int parsed_opt_brackets;
782
783    if (*ctx->cur == '-') {
784       ctx->cur++;
785       eat_opt_white( &ctx->cur );
786       src->Register.Negate = 1;
787    }
788
789    if (*ctx->cur == '|') {
790       ctx->cur++;
791       eat_opt_white( &ctx->cur );
792       src->Register.Absolute = 1;
793    }
794
795    if (!parse_register_src(ctx, &file, &bracket[0]))
796       return FALSE;
797    if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
798       return FALSE;
799
800    src->Register.File = file;
801    if (parsed_opt_brackets) {
802       src->Register.Dimension = 1;
803       src->Dimension.Indirect = 0;
804       src->Dimension.Dimension = 0;
805       src->Dimension.Index = bracket[0].index;
806       bracket[0] = bracket[1];
807    }
808    src->Register.Index = bracket[0].index;
809    if (bracket[0].ind_file != TGSI_FILE_NULL) {
810       src->Register.Indirect = 1;
811       src->Indirect.File = bracket[0].ind_file;
812       src->Indirect.Index = bracket[0].ind_index;
813       src->Indirect.Swizzle = bracket[0].ind_comp;
814       src->Indirect.ArrayID = bracket[0].ind_array;
815    }
816
817    /* Parse optional swizzle.
818     */
819    if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
820       if (parsed_swizzle) {
821          src->Register.SwizzleX = swizzle[0];
822          src->Register.SwizzleY = swizzle[1];
823          src->Register.SwizzleZ = swizzle[2];
824          src->Register.SwizzleW = swizzle[3];
825       }
826    }
827
828    if (src->Register.Absolute) {
829       eat_opt_white( &ctx->cur );
830       if (*ctx->cur != '|') {
831          report_error( ctx, "Expected `|'" );
832          return FALSE;
833       }
834       ctx->cur++;
835    }
836
837
838    return TRUE;
839 }
840
841 static boolean
842 match_inst(const char **pcur,
843            unsigned *saturate,
844            const struct tgsi_opcode_info *info)
845 {
846    const char *cur = *pcur;
847
848    /* simple case: the whole string matches the instruction name */
849    if (str_match_nocase_whole(&cur, info->mnemonic)) {
850       *pcur = cur;
851       *saturate = TGSI_SAT_NONE;
852       return TRUE;
853    }
854
855    if (str_match_no_case(&cur, info->mnemonic)) {
856       /* the instruction has a suffix, figure it out */
857       if (str_match_nocase_whole(&cur, "_SAT")) {
858          *pcur = cur;
859          *saturate = TGSI_SAT_ZERO_ONE;
860          return TRUE;
861       }
862
863       if (str_match_nocase_whole(&cur, "_SATNV")) {
864          *pcur = cur;
865          *saturate = TGSI_SAT_MINUS_PLUS_ONE;
866          return TRUE;
867       }
868    }
869
870    return FALSE;
871 }
872
873 static boolean
874 parse_instruction(
875    struct translate_ctx *ctx,
876    boolean has_label )
877 {
878    uint i;
879    uint saturate = TGSI_SAT_NONE;
880    const struct tgsi_opcode_info *info;
881    struct tgsi_full_instruction inst;
882    const char *cur;
883    uint advance;
884
885    inst = tgsi_default_full_instruction();
886
887    /* Parse predicate.
888     */
889    eat_opt_white( &ctx->cur );
890    if (*ctx->cur == '(') {
891       uint file;
892       int index;
893       uint swizzle[4];
894       boolean parsed_swizzle;
895
896       inst.Instruction.Predicate = 1;
897
898       ctx->cur++;
899       if (*ctx->cur == '!') {
900          ctx->cur++;
901          inst.Predicate.Negate = 1;
902       }
903
904       if (!parse_register_1d( ctx, &file, &index ))
905          return FALSE;
906
907       if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
908          if (parsed_swizzle) {
909             inst.Predicate.SwizzleX = swizzle[0];
910             inst.Predicate.SwizzleY = swizzle[1];
911             inst.Predicate.SwizzleZ = swizzle[2];
912             inst.Predicate.SwizzleW = swizzle[3];
913          }
914       }
915
916       if (*ctx->cur != ')') {
917          report_error( ctx, "Expected `)'" );
918          return FALSE;
919       }
920
921       ctx->cur++;
922    }
923
924    /* Parse instruction name.
925     */
926    eat_opt_white( &ctx->cur );
927    for (i = 0; i < TGSI_OPCODE_LAST; i++) {
928       cur = ctx->cur;
929
930       info = tgsi_get_opcode_info( i );
931       if (match_inst(&cur, &saturate, info)) {
932          if (info->num_dst + info->num_src + info->is_tex == 0) {
933             ctx->cur = cur;
934             break;
935          }
936          else if (*cur == '\0' || eat_white( &cur )) {
937             ctx->cur = cur;
938             break;
939          }
940       }
941    }
942    if (i == TGSI_OPCODE_LAST) {
943       if (has_label)
944          report_error( ctx, "Unknown opcode" );
945       else
946          report_error( ctx, "Expected `DCL', `IMM' or a label" );
947       return FALSE;
948    }
949
950    inst.Instruction.Opcode = i;
951    inst.Instruction.Saturate = saturate;
952    inst.Instruction.NumDstRegs = info->num_dst;
953    inst.Instruction.NumSrcRegs = info->num_src;
954
955    if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
956       /*
957        * These are not considered tex opcodes here (no additional
958        * target argument) however we're required to set the Texture
959        * bit so we can set the number of tex offsets (offsets aren't
960        * actually handled here yet in any case).
961        */
962       inst.Instruction.Texture = 1;
963       inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
964    }
965
966    /* Parse instruction operands.
967     */
968    for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
969       if (i > 0) {
970          eat_opt_white( &ctx->cur );
971          if (*ctx->cur != ',') {
972             report_error( ctx, "Expected `,'" );
973             return FALSE;
974          }
975          ctx->cur++;
976          eat_opt_white( &ctx->cur );
977       }
978
979       if (i < info->num_dst) {
980          if (!parse_dst_operand( ctx, &inst.Dst[i] ))
981             return FALSE;
982       }
983       else if (i < info->num_dst + info->num_src) {
984          if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
985             return FALSE;
986       }
987       else {
988          uint j;
989
990          for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
991             if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
992                inst.Instruction.Texture = 1;
993                inst.Texture.Texture = j;
994                break;
995             }
996          }
997          if (j == TGSI_TEXTURE_COUNT) {
998             report_error( ctx, "Expected texture target" );
999             return FALSE;
1000          }
1001       }
1002    }
1003
1004    cur = ctx->cur;
1005    eat_opt_white( &cur );
1006    if (info->is_branch && *cur == ':') {
1007       uint target;
1008
1009       cur++;
1010       eat_opt_white( &cur );
1011       if (!parse_uint( &cur, &target )) {
1012          report_error( ctx, "Expected a label" );
1013          return FALSE;
1014       }
1015       inst.Instruction.Label = 1;
1016       inst.Label.Label = target;
1017       ctx->cur = cur;
1018    }
1019
1020    advance = tgsi_build_full_instruction(
1021       &inst,
1022       ctx->tokens_cur,
1023       ctx->header,
1024       (uint) (ctx->tokens_end - ctx->tokens_cur) );
1025    if (advance == 0)
1026       return FALSE;
1027    ctx->tokens_cur += advance;
1028
1029    return TRUE;
1030 }
1031
1032 /* parses a 4-touple of the form {x, y, z, w}
1033  * where x, y, z, w are numbers */
1034 static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
1035                                     union tgsi_immediate_data *values)
1036 {
1037    unsigned i;
1038    int ret;
1039
1040    eat_opt_white( &ctx->cur );
1041    if (*ctx->cur != '{') {
1042       report_error( ctx, "Expected `{'" );
1043       return FALSE;
1044    }
1045    ctx->cur++;
1046    for (i = 0; i < 4; i++) {
1047       eat_opt_white( &ctx->cur );
1048       if (i > 0) {
1049          if (*ctx->cur != ',') {
1050             report_error( ctx, "Expected `,'" );
1051             return FALSE;
1052          }
1053          ctx->cur++;
1054          eat_opt_white( &ctx->cur );
1055       }
1056
1057       switch (type) {
1058       case TGSI_IMM_FLOAT32:
1059          ret = parse_float(&ctx->cur, &values[i].Float);
1060          break;
1061       case TGSI_IMM_UINT32:
1062          ret = parse_uint(&ctx->cur, &values[i].Uint);
1063          break;
1064       case TGSI_IMM_INT32:
1065          ret = parse_int(&ctx->cur, &values[i].Int);
1066          break;
1067       default:
1068          assert(0);
1069          ret = FALSE;
1070          break;
1071       }
1072
1073       if (!ret) {
1074          report_error( ctx, "Expected immediate constant" );
1075          return FALSE;
1076       }
1077    }
1078    eat_opt_white( &ctx->cur );
1079    if (*ctx->cur != '}') {
1080       report_error( ctx, "Expected `}'" );
1081       return FALSE;
1082    }
1083    ctx->cur++;
1084
1085    return TRUE;
1086 }
1087
1088 static boolean parse_declaration( struct translate_ctx *ctx )
1089 {
1090    struct tgsi_full_declaration decl;
1091    uint file;
1092    struct parsed_dcl_bracket brackets[2];
1093    int num_brackets;
1094    uint writemask;
1095    const char *cur, *cur2;
1096    uint advance;
1097    boolean is_vs_input;
1098
1099    if (!eat_white( &ctx->cur )) {
1100       report_error( ctx, "Syntax error" );
1101       return FALSE;
1102    }
1103    if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
1104       return FALSE;
1105    if (!parse_opt_writemask( ctx, &writemask ))
1106       return FALSE;
1107
1108    decl = tgsi_default_full_declaration();
1109    decl.Declaration.File = file;
1110    decl.Declaration.UsageMask = writemask;
1111
1112    if (num_brackets == 1) {
1113       decl.Range.First = brackets[0].first;
1114       decl.Range.Last = brackets[0].last;
1115    } else {
1116       decl.Range.First = brackets[1].first;
1117       decl.Range.Last = brackets[1].last;
1118
1119       decl.Declaration.Dimension = 1;
1120       decl.Dim.Index2D = brackets[0].first;
1121    }
1122
1123    is_vs_input = (file == TGSI_FILE_INPUT &&
1124                   ctx->processor == TGSI_PROCESSOR_VERTEX);
1125
1126    cur = ctx->cur;
1127    eat_opt_white( &cur );
1128    if (*cur == ',') {
1129       cur2 = cur;
1130       cur2++;
1131       eat_opt_white( &cur2 );
1132       if (str_match_nocase_whole( &cur2, "ARRAY(" )) {
1133          int arrayid;
1134          eat_opt_white( &cur2 );
1135          if (!parse_int( &cur2, &arrayid )) {
1136             report_error( ctx, "Expected `,'" );
1137             return FALSE;
1138          }
1139          eat_opt_white( &cur2 );
1140          if (*cur2 != ')') {
1141             report_error( ctx, "Expected `,'" );
1142             return FALSE;
1143          }
1144          decl.Declaration.Array = 1;
1145          decl.Array.ArrayID = arrayid;
1146          cur = cur2;
1147       }
1148    }
1149
1150    if (*cur == ',' && !is_vs_input) {
1151       uint i, j;
1152
1153       cur++;
1154       eat_opt_white( &cur );
1155       if (file == TGSI_FILE_RESOURCE) {
1156          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1157             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1158                decl.Resource.Resource = i;
1159                break;
1160             }
1161          }
1162          if (i == TGSI_TEXTURE_COUNT) {
1163             report_error(ctx, "Expected texture target");
1164             return FALSE;
1165          }
1166
1167          cur2 = cur;
1168          eat_opt_white(&cur2);
1169          while (*cur2 == ',') {
1170             cur2++;
1171             eat_opt_white(&cur2);
1172             if (str_match_nocase_whole(&cur2, "RAW")) {
1173                decl.Resource.Raw = 1;
1174
1175             } else if (str_match_nocase_whole(&cur2, "WR")) {
1176                decl.Resource.Writable = 1;
1177
1178             } else {
1179                break;
1180             }
1181             cur = cur2;
1182             eat_opt_white(&cur2);
1183          }
1184
1185          ctx->cur = cur;
1186
1187       } else if (file == TGSI_FILE_SAMPLER_VIEW) {
1188          for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
1189             if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
1190                decl.SamplerView.Resource = i;
1191                break;
1192             }
1193          }
1194          if (i == TGSI_TEXTURE_COUNT) {
1195             report_error(ctx, "Expected texture target");
1196             return FALSE;
1197          }
1198          eat_opt_white( &cur );
1199          if (*cur != ',') {
1200             report_error( ctx, "Expected `,'" );
1201             return FALSE;
1202          }
1203          ++cur;
1204          eat_opt_white( &cur );
1205          for (j = 0; j < 4; ++j) {
1206             for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
1207                if (str_match_nocase_whole(&cur, tgsi_type_names[i])) {
1208                   switch (j) {
1209                   case 0:
1210                      decl.SamplerView.ReturnTypeX = i;
1211                      break;
1212                   case 1:
1213                      decl.SamplerView.ReturnTypeY = i;
1214                      break;
1215                   case 2:
1216                      decl.SamplerView.ReturnTypeZ = i;
1217                      break;
1218                   case 3:
1219                      decl.SamplerView.ReturnTypeW = i;
1220                      break;
1221                   default:
1222                      assert(0);
1223                   }
1224                   break;
1225                }
1226             }
1227             if (i == PIPE_TYPE_COUNT) {
1228                if (j == 0 || j >  2) {
1229                   report_error(ctx, "Expected type name");
1230                   return FALSE;
1231                }
1232                break;
1233             } else {
1234                cur2 = cur;
1235                eat_opt_white( &cur2 );
1236                if (*cur2 == ',') {
1237                   cur2++;
1238                   eat_opt_white( &cur2 );
1239                   cur = cur2;
1240                   continue;
1241                } else
1242                   break;
1243             }
1244          }
1245          if (j < 4) {
1246             decl.SamplerView.ReturnTypeY =
1247                decl.SamplerView.ReturnTypeZ =
1248                decl.SamplerView.ReturnTypeW =
1249                decl.SamplerView.ReturnTypeX;
1250          }
1251          ctx->cur = cur;
1252       } else {
1253          if (str_match_nocase_whole(&cur, "LOCAL")) {
1254             decl.Declaration.Local = 1;
1255             ctx->cur = cur;
1256          }
1257
1258          cur = ctx->cur;
1259          eat_opt_white( &cur );
1260          if (*cur == ',') {
1261             cur++;
1262             eat_opt_white( &cur );
1263
1264             for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
1265                if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
1266                   uint index;
1267
1268                   cur2 = cur;
1269                   eat_opt_white( &cur2 );
1270                   if (*cur2 == '[') {
1271                      cur2++;
1272                      eat_opt_white( &cur2 );
1273                      if (!parse_uint( &cur2, &index )) {
1274                         report_error( ctx, "Expected literal integer" );
1275                         return FALSE;
1276                      }
1277                      eat_opt_white( &cur2 );
1278                      if (*cur2 != ']') {
1279                         report_error( ctx, "Expected `]'" );
1280                         return FALSE;
1281                      }
1282                      cur2++;
1283
1284                      decl.Semantic.Index = index;
1285
1286                      cur = cur2;
1287                   }
1288
1289                   decl.Declaration.Semantic = 1;
1290                   decl.Semantic.Name = i;
1291
1292                   ctx->cur = cur;
1293                   break;
1294                }
1295             }
1296          }
1297       }
1298    }
1299
1300    cur = ctx->cur;
1301    eat_opt_white( &cur );
1302    if (*cur == ',' && !is_vs_input) {
1303       uint i;
1304
1305       cur++;
1306       eat_opt_white( &cur );
1307       for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
1308          if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
1309             decl.Declaration.Interpolate = 1;
1310             decl.Interp.Interpolate = i;
1311
1312             ctx->cur = cur;
1313             break;
1314          }
1315       }
1316       if (i == TGSI_INTERPOLATE_COUNT) {
1317          report_error( ctx, "Expected semantic or interpolate attribute" );
1318          return FALSE;
1319       }
1320    }
1321
1322    advance = tgsi_build_full_declaration(
1323       &decl,
1324       ctx->tokens_cur,
1325       ctx->header,
1326       (uint) (ctx->tokens_end - ctx->tokens_cur) );
1327
1328    if (advance == 0)
1329       return FALSE;
1330    ctx->tokens_cur += advance;
1331
1332    return TRUE;
1333 }
1334
1335 static boolean parse_immediate( struct translate_ctx *ctx )
1336 {
1337    struct tgsi_full_immediate imm;
1338    uint advance;
1339    int type;
1340
1341    if (*ctx->cur == '[') {
1342       uint uindex;
1343
1344       ++ctx->cur;
1345
1346       eat_opt_white( &ctx->cur );
1347       if (!parse_uint( &ctx->cur, &uindex )) {
1348          report_error( ctx, "Expected literal unsigned integer" );
1349          return FALSE;
1350       }
1351
1352       if (uindex != ctx->num_immediates) {
1353          report_error( ctx, "Immediates must be sorted" );
1354          return FALSE;
1355       }
1356
1357       eat_opt_white( &ctx->cur );
1358       if (*ctx->cur != ']') {
1359          report_error( ctx, "Expected `]'" );
1360          return FALSE;
1361       }
1362
1363       ctx->cur++;
1364    }
1365
1366    if (!eat_white( &ctx->cur )) {
1367       report_error( ctx, "Syntax error" );
1368       return FALSE;
1369    }
1370    for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) {
1371       if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
1372          break;
1373    }
1374    if (type == Elements(tgsi_immediate_type_names)) {
1375       report_error( ctx, "Expected immediate type" );
1376       return FALSE;
1377    }
1378
1379    imm = tgsi_default_full_immediate();
1380    imm.Immediate.NrTokens += 4;
1381    imm.Immediate.DataType = type;
1382    parse_immediate_data(ctx, type, imm.u);
1383
1384    advance = tgsi_build_full_immediate(
1385       &imm,
1386       ctx->tokens_cur,
1387       ctx->header,
1388       (uint) (ctx->tokens_end - ctx->tokens_cur) );
1389    if (advance == 0)
1390       return FALSE;
1391    ctx->tokens_cur += advance;
1392
1393    ctx->num_immediates++;
1394
1395    return TRUE;
1396 }
1397
1398 static boolean
1399 parse_primitive( const char **pcur, uint *primitive )
1400 {
1401    uint i;
1402
1403    for (i = 0; i < PIPE_PRIM_MAX; i++) {
1404       const char *cur = *pcur;
1405
1406       if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
1407          *primitive = i;
1408          *pcur = cur;
1409          return TRUE;
1410       }
1411    }
1412    return FALSE;
1413 }
1414
1415 static boolean
1416 parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
1417 {
1418    uint i;
1419
1420    for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
1421       const char *cur = *pcur;
1422
1423       if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
1424          *fs_coord_origin = i;
1425          *pcur = cur;
1426          return TRUE;
1427       }
1428    }
1429    return FALSE;
1430 }
1431
1432 static boolean
1433 parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
1434 {
1435    uint i;
1436
1437    for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
1438       const char *cur = *pcur;
1439
1440       if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
1441          *fs_coord_pixel_center = i;
1442          *pcur = cur;
1443          return TRUE;
1444       }
1445    }
1446    return FALSE;
1447 }
1448
1449
1450 static boolean parse_property( struct translate_ctx *ctx )
1451 {
1452    struct tgsi_full_property prop;
1453    uint property_name;
1454    uint values[8];
1455    uint advance;
1456    char id[64];
1457
1458    if (!eat_white( &ctx->cur )) {
1459       report_error( ctx, "Syntax error" );
1460       return FALSE;
1461    }
1462    if (!parse_identifier( &ctx->cur, id )) {
1463       report_error( ctx, "Syntax error" );
1464       return FALSE;
1465    }
1466    for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
1467         ++property_name) {
1468       if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
1469          break;
1470       }
1471    }
1472    if (property_name >= TGSI_PROPERTY_COUNT) {
1473       debug_printf( "\nError: Unknown property : '%s'", id );
1474       return FALSE;
1475    }
1476
1477    eat_opt_white( &ctx->cur );
1478    switch(property_name) {
1479    case TGSI_PROPERTY_GS_INPUT_PRIM:
1480    case TGSI_PROPERTY_GS_OUTPUT_PRIM:
1481       if (!parse_primitive(&ctx->cur, &values[0] )) {
1482          report_error( ctx, "Unknown primitive name as property!" );
1483          return FALSE;
1484       }
1485       if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
1486           ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
1487          ctx->implied_array_size = u_vertices_per_prim(values[0]);
1488       }
1489       break;
1490    case TGSI_PROPERTY_FS_COORD_ORIGIN:
1491       if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
1492          report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
1493          return FALSE;
1494       }
1495       break;
1496    case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
1497       if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
1498          report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
1499          return FALSE;
1500       }
1501       break;
1502    case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
1503    default:
1504       if (!parse_uint(&ctx->cur, &values[0] )) {
1505          report_error( ctx, "Expected unsigned integer as property!" );
1506          return FALSE;
1507       }
1508    }
1509
1510    prop = tgsi_default_full_property();
1511    prop.Property.PropertyName = property_name;
1512    prop.Property.NrTokens += 1;
1513    prop.u[0].Data = values[0];
1514
1515    advance = tgsi_build_full_property(
1516       &prop,
1517       ctx->tokens_cur,
1518       ctx->header,
1519       (uint) (ctx->tokens_end - ctx->tokens_cur) );
1520    if (advance == 0)
1521       return FALSE;
1522    ctx->tokens_cur += advance;
1523
1524    return TRUE;
1525 }
1526
1527
1528 static boolean translate( struct translate_ctx *ctx )
1529 {
1530    eat_opt_white( &ctx->cur );
1531    if (!parse_header( ctx ))
1532       return FALSE;
1533
1534    while (*ctx->cur != '\0') {
1535       uint label_val = 0;
1536       if (!eat_white( &ctx->cur )) {
1537          report_error( ctx, "Syntax error" );
1538          return FALSE;
1539       }
1540
1541       if (*ctx->cur == '\0')
1542          break;
1543       if (parse_label( ctx, &label_val )) {
1544          if (!parse_instruction( ctx, TRUE ))
1545             return FALSE;
1546       }
1547       else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
1548          if (!parse_declaration( ctx ))
1549             return FALSE;
1550       }
1551       else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
1552          if (!parse_immediate( ctx ))
1553             return FALSE;
1554       }
1555       else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
1556          if (!parse_property( ctx ))
1557             return FALSE;
1558       }
1559       else if (!parse_instruction( ctx, FALSE )) {
1560          return FALSE;
1561       }
1562    }
1563
1564    return TRUE;
1565 }
1566
1567 boolean
1568 tgsi_text_translate(
1569    const char *text,
1570    struct tgsi_token *tokens,
1571    uint num_tokens )
1572 {
1573    struct translate_ctx ctx = {0};
1574
1575    ctx.text = text;
1576    ctx.cur = text;
1577    ctx.tokens = tokens;
1578    ctx.tokens_cur = tokens;
1579    ctx.tokens_end = tokens + num_tokens;
1580
1581    if (!translate( &ctx ))
1582       return FALSE;
1583
1584    return tgsi_sanity_check( tokens );
1585 }