nouveau: avoid running out of relocs
[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 "tgsi_text.h"
31 #include "tgsi_build.h"
32 #include "tgsi_info.h"
33 #include "tgsi_parse.h"
34 #include "tgsi_sanity.h"
35 #include "tgsi_util.h"
36
37 static boolean is_alpha_underscore( const char *cur )
38 {
39 return
40 (*cur >= 'a' && *cur <= 'z') ||
41 (*cur >= 'A' && *cur <= 'Z') ||
42 *cur == '_';
43 }
44
45 static boolean is_digit( const char *cur )
46 {
47 return *cur >= '0' && *cur <= '9';
48 }
49
50 static boolean is_digit_alpha_underscore( const char *cur )
51 {
52 return is_digit( cur ) || is_alpha_underscore( cur );
53 }
54
55 static boolean uprcase( char c )
56 {
57 if (c >= 'a' && c <= 'z')
58 return c += 'A' - 'a';
59 return c;
60 }
61
62 static boolean str_match_no_case( const char **pcur, const char *str )
63 {
64 const char *cur = *pcur;
65
66 while (*str != '\0' && *str == uprcase( *cur )) {
67 str++;
68 cur++;
69 }
70 if (*str == '\0') {
71 *pcur = cur;
72 return TRUE;
73 }
74 return FALSE;
75 }
76
77 /* Eat zero or more whitespaces.
78 */
79 static void eat_opt_white( const char **pcur )
80 {
81 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
82 (*pcur)++;
83 }
84
85 /* Eat one or more whitespaces.
86 * Return TRUE if at least one whitespace eaten.
87 */
88 static boolean eat_white( const char **pcur )
89 {
90 const char *cur = *pcur;
91
92 eat_opt_white( pcur );
93 return *pcur > cur;
94 }
95
96 /* Parse unsigned integer.
97 * No checks for overflow.
98 */
99 static boolean parse_uint( const char **pcur, uint *val )
100 {
101 const char *cur = *pcur;
102
103 if (is_digit( cur )) {
104 *val = *cur++ - '0';
105 while (is_digit( cur ))
106 *val = *val * 10 + *cur++ - '0';
107 *pcur = cur;
108 return TRUE;
109 }
110 return FALSE;
111 }
112
113 /* Parse floating point.
114 */
115 static boolean parse_float( const char **pcur, float *val )
116 {
117 const char *cur = *pcur;
118 boolean integral_part = FALSE;
119 boolean fractional_part = FALSE;
120
121 *val = (float) atof( cur );
122
123 if (*cur == '-' || *cur == '+')
124 cur++;
125 if (is_digit( cur )) {
126 cur++;
127 integral_part = TRUE;
128 while (is_digit( cur ))
129 cur++;
130 }
131 if (*cur == '.') {
132 cur++;
133 if (is_digit( cur )) {
134 cur++;
135 fractional_part = TRUE;
136 while (is_digit( cur ))
137 cur++;
138 }
139 }
140 if (!integral_part && !fractional_part)
141 return FALSE;
142 if (uprcase( *cur ) == 'E') {
143 cur++;
144 if (*cur == '-' || *cur == '+')
145 cur++;
146 if (is_digit( cur )) {
147 cur++;
148 while (is_digit( cur ))
149 cur++;
150 }
151 else
152 return FALSE;
153 }
154 *pcur = cur;
155 return TRUE;
156 }
157
158 struct translate_ctx
159 {
160 const char *text;
161 const char *cur;
162 struct tgsi_token *tokens;
163 struct tgsi_token *tokens_cur;
164 struct tgsi_token *tokens_end;
165 struct tgsi_header *header;
166 };
167
168 static void report_error( struct translate_ctx *ctx, const char *msg )
169 {
170 debug_printf( "\nError: %s", msg );
171 }
172
173 /* Parse shader header.
174 * Return TRUE for one of the following headers.
175 * FRAG
176 * GEOM
177 * VERT
178 */
179 static boolean parse_header( struct translate_ctx *ctx )
180 {
181 uint processor;
182
183 if (str_match_no_case( &ctx->cur, "FRAG" ))
184 processor = TGSI_PROCESSOR_FRAGMENT;
185 else if (str_match_no_case( &ctx->cur, "VERT" ))
186 processor = TGSI_PROCESSOR_VERTEX;
187 else if (str_match_no_case( &ctx->cur, "GEOM" ))
188 processor = TGSI_PROCESSOR_GEOMETRY;
189 else {
190 report_error( ctx, "Unknown header" );
191 return FALSE;
192 }
193
194 if (ctx->tokens_cur >= ctx->tokens_end)
195 return FALSE;
196 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
197 *ctx->header = tgsi_build_header();
198
199 if (ctx->tokens_cur >= ctx->tokens_end)
200 return FALSE;
201 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
202
203 return TRUE;
204 }
205
206 static boolean parse_label( struct translate_ctx *ctx, uint *val )
207 {
208 const char *cur = ctx->cur;
209
210 if (parse_uint( &cur, val )) {
211 eat_opt_white( &cur );
212 if (*cur == ':') {
213 cur++;
214 ctx->cur = cur;
215 return TRUE;
216 }
217 }
218 return FALSE;
219 }
220
221 static const char *file_names[TGSI_FILE_COUNT] =
222 {
223 "NULL",
224 "CONST",
225 "IN",
226 "OUT",
227 "TEMP",
228 "SAMP",
229 "ADDR",
230 "IMM",
231 "LOOP",
232 "PRED"
233 };
234
235 static boolean
236 parse_file( const char **pcur, uint *file )
237 {
238 uint i;
239
240 for (i = 0; i < TGSI_FILE_COUNT; i++) {
241 const char *cur = *pcur;
242
243 if (str_match_no_case( &cur, file_names[i] )) {
244 if (!is_digit_alpha_underscore( cur )) {
245 *pcur = cur;
246 *file = i;
247 return TRUE;
248 }
249 }
250 }
251 return FALSE;
252 }
253
254 static boolean
255 parse_opt_writemask(
256 struct translate_ctx *ctx,
257 uint *writemask )
258 {
259 const char *cur;
260
261 cur = ctx->cur;
262 eat_opt_white( &cur );
263 if (*cur == '.') {
264 cur++;
265 *writemask = TGSI_WRITEMASK_NONE;
266 eat_opt_white( &cur );
267 if (uprcase( *cur ) == 'X') {
268 cur++;
269 *writemask |= TGSI_WRITEMASK_X;
270 }
271 if (uprcase( *cur ) == 'Y') {
272 cur++;
273 *writemask |= TGSI_WRITEMASK_Y;
274 }
275 if (uprcase( *cur ) == 'Z') {
276 cur++;
277 *writemask |= TGSI_WRITEMASK_Z;
278 }
279 if (uprcase( *cur ) == 'W') {
280 cur++;
281 *writemask |= TGSI_WRITEMASK_W;
282 }
283
284 if (*writemask == TGSI_WRITEMASK_NONE) {
285 report_error( ctx, "Writemask expected" );
286 return FALSE;
287 }
288
289 ctx->cur = cur;
290 }
291 else {
292 *writemask = TGSI_WRITEMASK_XYZW;
293 }
294 return TRUE;
295 }
296
297 /* <register_file_bracket> ::= <file> `['
298 */
299 static boolean
300 parse_register_file_bracket(
301 struct translate_ctx *ctx,
302 uint *file )
303 {
304 if (!parse_file( &ctx->cur, file )) {
305 report_error( ctx, "Unknown register file" );
306 return FALSE;
307 }
308 eat_opt_white( &ctx->cur );
309 if (*ctx->cur != '[') {
310 report_error( ctx, "Expected `['" );
311 return FALSE;
312 }
313 ctx->cur++;
314 return TRUE;
315 }
316
317 /* <register_file_bracket_index> ::= <register_file_bracket> <uint>
318 */
319 static boolean
320 parse_register_file_bracket_index(
321 struct translate_ctx *ctx,
322 uint *file,
323 int *index )
324 {
325 uint uindex;
326
327 if (!parse_register_file_bracket( ctx, file ))
328 return FALSE;
329 eat_opt_white( &ctx->cur );
330 if (!parse_uint( &ctx->cur, &uindex )) {
331 report_error( ctx, "Expected literal unsigned integer" );
332 return FALSE;
333 }
334 *index = (int) uindex;
335 return TRUE;
336 }
337
338 /* Parse destination register operand.
339 * <register_dst> ::= <register_file_bracket_index> `]'
340 */
341 static boolean
342 parse_register_dst(
343 struct translate_ctx *ctx,
344 uint *file,
345 int *index )
346 {
347 if (!parse_register_file_bracket_index( ctx, file, index ))
348 return FALSE;
349 eat_opt_white( &ctx->cur );
350 if (*ctx->cur != ']') {
351 report_error( ctx, "Expected `]'" );
352 return FALSE;
353 }
354 ctx->cur++;
355 return TRUE;
356 }
357
358 /* Parse source register operand.
359 * <register_src> ::= <register_file_bracket_index> `]' |
360 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
361 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
362 * <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
363 */
364 static boolean
365 parse_register_src(
366 struct translate_ctx *ctx,
367 uint *file,
368 int *index,
369 uint *ind_file,
370 int *ind_index,
371 uint *ind_comp)
372 {
373 const char *cur;
374 uint uindex;
375
376 *ind_comp = TGSI_SWIZZLE_X;
377 if (!parse_register_file_bracket( ctx, file ))
378 return FALSE;
379 eat_opt_white( &ctx->cur );
380 cur = ctx->cur;
381 if (parse_file( &cur, ind_file )) {
382 if (!parse_register_dst( ctx, ind_file, ind_index ))
383 return FALSE;
384 eat_opt_white( &ctx->cur );
385
386 if (*ctx->cur == '.') {
387 ctx->cur++;
388 eat_opt_white(&ctx->cur);
389
390 switch (uprcase(*ctx->cur)) {
391 case 'X':
392 *ind_comp = TGSI_SWIZZLE_X;
393 break;
394 case 'Y':
395 *ind_comp = TGSI_SWIZZLE_Y;
396 break;
397 case 'Z':
398 *ind_comp = TGSI_SWIZZLE_Z;
399 break;
400 case 'W':
401 *ind_comp = TGSI_SWIZZLE_W;
402 break;
403 default:
404 report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
405 return FALSE;
406 }
407 ctx->cur++;
408 eat_opt_white(&ctx->cur);
409 }
410
411 if (*ctx->cur == '+' || *ctx->cur == '-') {
412 boolean negate;
413
414 negate = *ctx->cur == '-';
415 ctx->cur++;
416 eat_opt_white( &ctx->cur );
417 if (!parse_uint( &ctx->cur, &uindex )) {
418 report_error( ctx, "Expected literal unsigned integer" );
419 return FALSE;
420 }
421 if (negate)
422 *index = -(int) uindex;
423 else
424 *index = (int) uindex;
425 }
426 else {
427 *index = 0;
428 }
429 }
430 else {
431 if (!parse_uint( &ctx->cur, &uindex )) {
432 report_error( ctx, "Expected literal unsigned integer" );
433 return FALSE;
434 }
435 *index = (int) uindex;
436 *ind_file = TGSI_FILE_NULL;
437 *ind_index = 0;
438 }
439 eat_opt_white( &ctx->cur );
440 if (*ctx->cur != ']') {
441 report_error( ctx, "Expected `]'" );
442 return FALSE;
443 }
444 ctx->cur++;
445 return TRUE;
446 }
447
448 /* Parse register declaration.
449 * <register_dcl> ::= <register_file_bracket_index> `]' |
450 * <register_file_bracket_index> `..' <index> `]'
451 */
452 static boolean
453 parse_register_dcl(
454 struct translate_ctx *ctx,
455 uint *file,
456 int *first,
457 int *last )
458 {
459 if (!parse_register_file_bracket_index( ctx, file, first ))
460 return FALSE;
461 eat_opt_white( &ctx->cur );
462 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
463 uint uindex;
464
465 ctx->cur += 2;
466 eat_opt_white( &ctx->cur );
467 if (!parse_uint( &ctx->cur, &uindex )) {
468 report_error( ctx, "Expected literal integer" );
469 return FALSE;
470 }
471 *last = (int) uindex;
472 eat_opt_white( &ctx->cur );
473 }
474 else {
475 *last = *first;
476 }
477 if (*ctx->cur != ']') {
478 report_error( ctx, "Expected `]' or `..'" );
479 return FALSE;
480 }
481 ctx->cur++;
482 return TRUE;
483 }
484
485
486 static boolean
487 parse_dst_operand(
488 struct translate_ctx *ctx,
489 struct tgsi_full_dst_register *dst )
490 {
491 uint file;
492 int index;
493 uint writemask;
494 const char *cur;
495
496 if (!parse_register_dst( ctx, &file, &index ))
497 return FALSE;
498
499 cur = ctx->cur;
500 eat_opt_white( &cur );
501
502 if (!parse_opt_writemask( ctx, &writemask ))
503 return FALSE;
504
505 dst->Register.File = file;
506 dst->Register.Index = index;
507 dst->Register.WriteMask = writemask;
508 return TRUE;
509 }
510
511 static boolean
512 parse_optional_swizzle(
513 struct translate_ctx *ctx,
514 uint swizzle[4],
515 boolean *parsed_swizzle )
516 {
517 const char *cur = ctx->cur;
518
519 *parsed_swizzle = FALSE;
520
521 eat_opt_white( &cur );
522 if (*cur == '.') {
523 uint i;
524
525 cur++;
526 eat_opt_white( &cur );
527 for (i = 0; i < 4; i++) {
528 if (uprcase( *cur ) == 'X')
529 swizzle[i] = TGSI_SWIZZLE_X;
530 else if (uprcase( *cur ) == 'Y')
531 swizzle[i] = TGSI_SWIZZLE_Y;
532 else if (uprcase( *cur ) == 'Z')
533 swizzle[i] = TGSI_SWIZZLE_Z;
534 else if (uprcase( *cur ) == 'W')
535 swizzle[i] = TGSI_SWIZZLE_W;
536 else {
537 report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
538 return FALSE;
539 }
540 cur++;
541 }
542 *parsed_swizzle = TRUE;
543 ctx->cur = cur;
544 }
545 return TRUE;
546 }
547
548 static boolean
549 parse_src_operand(
550 struct translate_ctx *ctx,
551 struct tgsi_full_src_register *src )
552 {
553 uint file;
554 int index;
555 uint ind_file;
556 int ind_index;
557 uint ind_comp;
558 uint swizzle[4];
559 boolean parsed_swizzle;
560
561 if (*ctx->cur == '-') {
562 ctx->cur++;
563 eat_opt_white( &ctx->cur );
564 src->Register.Negate = 1;
565 }
566
567 if (*ctx->cur == '|') {
568 ctx->cur++;
569 eat_opt_white( &ctx->cur );
570 src->Register.Absolute = 1;
571 }
572
573 if (!parse_register_src(ctx, &file, &index, &ind_file, &ind_index, &ind_comp))
574 return FALSE;
575 src->Register.File = file;
576 src->Register.Index = index;
577 if (ind_file != TGSI_FILE_NULL) {
578 src->Register.Indirect = 1;
579 src->Indirect.File = ind_file;
580 src->Indirect.Index = ind_index;
581 src->Indirect.SwizzleX = ind_comp;
582 src->Indirect.SwizzleY = ind_comp;
583 src->Indirect.SwizzleZ = ind_comp;
584 src->Indirect.SwizzleW = ind_comp;
585 }
586
587 /* Parse optional swizzle.
588 */
589 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
590 if (parsed_swizzle) {
591 src->Register.SwizzleX = swizzle[0];
592 src->Register.SwizzleY = swizzle[1];
593 src->Register.SwizzleZ = swizzle[2];
594 src->Register.SwizzleW = swizzle[3];
595 }
596 }
597
598 if (src->Register.Absolute) {
599 eat_opt_white( &ctx->cur );
600 if (*ctx->cur != '|') {
601 report_error( ctx, "Expected `|'" );
602 return FALSE;
603 }
604 ctx->cur++;
605 }
606
607
608 return TRUE;
609 }
610
611 static const char *texture_names[TGSI_TEXTURE_COUNT] =
612 {
613 "UNKNOWN",
614 "1D",
615 "2D",
616 "3D",
617 "CUBE",
618 "RECT",
619 "SHADOW1D",
620 "SHADOW2D",
621 "SHADOWRECT"
622 };
623
624 static boolean
625 match_inst_mnemonic(const char **pcur,
626 const struct tgsi_opcode_info *info)
627 {
628 if (str_match_no_case(pcur, info->mnemonic)) {
629 return TRUE;
630 }
631 return FALSE;
632 }
633
634 static boolean
635 parse_instruction(
636 struct translate_ctx *ctx,
637 boolean has_label )
638 {
639 uint i;
640 uint saturate = TGSI_SAT_NONE;
641 const struct tgsi_opcode_info *info;
642 struct tgsi_full_instruction inst;
643 uint advance;
644
645 /* Parse instruction name.
646 */
647 eat_opt_white( &ctx->cur );
648 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
649 const char *cur = ctx->cur;
650
651 info = tgsi_get_opcode_info( i );
652 if (match_inst_mnemonic(&cur, info)) {
653 if (str_match_no_case( &cur, "_SATNV" ))
654 saturate = TGSI_SAT_MINUS_PLUS_ONE;
655 else if (str_match_no_case( &cur, "_SAT" ))
656 saturate = TGSI_SAT_ZERO_ONE;
657
658 if (info->num_dst + info->num_src + info->is_tex == 0) {
659 if (!is_digit_alpha_underscore( cur )) {
660 ctx->cur = cur;
661 break;
662 }
663 }
664 else if (*cur == '\0' || eat_white( &cur )) {
665 ctx->cur = cur;
666 break;
667 }
668 }
669 }
670 if (i == TGSI_OPCODE_LAST) {
671 if (has_label)
672 report_error( ctx, "Unknown opcode" );
673 else
674 report_error( ctx, "Expected `DCL', `IMM' or a label" );
675 return FALSE;
676 }
677
678 inst = tgsi_default_full_instruction();
679 inst.Instruction.Opcode = i;
680 inst.Instruction.Saturate = saturate;
681 inst.Instruction.NumDstRegs = info->num_dst;
682 inst.Instruction.NumSrcRegs = info->num_src;
683
684 /* Parse instruction operands.
685 */
686 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
687 if (i > 0) {
688 eat_opt_white( &ctx->cur );
689 if (*ctx->cur != ',') {
690 report_error( ctx, "Expected `,'" );
691 return FALSE;
692 }
693 ctx->cur++;
694 eat_opt_white( &ctx->cur );
695 }
696
697 if (i < info->num_dst) {
698 if (!parse_dst_operand( ctx, &inst.Dst[i] ))
699 return FALSE;
700 }
701 else if (i < info->num_dst + info->num_src) {
702 if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
703 return FALSE;
704 }
705 else {
706 uint j;
707
708 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
709 if (str_match_no_case( &ctx->cur, texture_names[j] )) {
710 if (!is_digit_alpha_underscore( ctx->cur )) {
711 inst.Instruction.Texture = 1;
712 inst.Texture.Texture = j;
713 break;
714 }
715 }
716 }
717 if (j == TGSI_TEXTURE_COUNT) {
718 report_error( ctx, "Expected texture target" );
719 return FALSE;
720 }
721 }
722 }
723
724 if (info->is_branch) {
725 uint target;
726
727 eat_opt_white( &ctx->cur );
728 if (*ctx->cur != ':') {
729 report_error( ctx, "Expected `:'" );
730 return FALSE;
731 }
732 ctx->cur++;
733 eat_opt_white( &ctx->cur );
734 if (!parse_uint( &ctx->cur, &target )) {
735 report_error( ctx, "Expected a label" );
736 return FALSE;
737 }
738 inst.Instruction.Label = 1;
739 inst.Label.Label = target;
740 }
741
742 advance = tgsi_build_full_instruction(
743 &inst,
744 ctx->tokens_cur,
745 ctx->header,
746 (uint) (ctx->tokens_end - ctx->tokens_cur) );
747 if (advance == 0)
748 return FALSE;
749 ctx->tokens_cur += advance;
750
751 return TRUE;
752 }
753
754 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
755 {
756 "POSITION",
757 "COLOR",
758 "BCOLOR",
759 "FOG",
760 "PSIZE",
761 "GENERIC",
762 "NORMAL",
763 "FACE"
764 };
765
766 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
767 {
768 "CONSTANT",
769 "LINEAR",
770 "PERSPECTIVE"
771 };
772
773 static boolean parse_declaration( struct translate_ctx *ctx )
774 {
775 struct tgsi_full_declaration decl;
776 uint file;
777 int first;
778 int last;
779 uint writemask;
780 const char *cur;
781 uint advance;
782
783 assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT);
784 assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT);
785
786 if (!eat_white( &ctx->cur )) {
787 report_error( ctx, "Syntax error" );
788 return FALSE;
789 }
790 if (!parse_register_dcl( ctx, &file, &first, &last ))
791 return FALSE;
792 if (!parse_opt_writemask( ctx, &writemask ))
793 return FALSE;
794
795 decl = tgsi_default_full_declaration();
796 decl.Declaration.File = file;
797 decl.Declaration.UsageMask = writemask;
798 decl.Range.First = first;
799 decl.Range.Last = last;
800
801 cur = ctx->cur;
802 eat_opt_white( &cur );
803 if (*cur == ',') {
804 uint i;
805
806 cur++;
807 eat_opt_white( &cur );
808 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
809 if (str_match_no_case( &cur, semantic_names[i] )) {
810 const char *cur2 = cur;
811 uint index;
812
813 if (is_digit_alpha_underscore( cur ))
814 continue;
815 eat_opt_white( &cur2 );
816 if (*cur2 == '[') {
817 cur2++;
818 eat_opt_white( &cur2 );
819 if (!parse_uint( &cur2, &index )) {
820 report_error( ctx, "Expected literal integer" );
821 return FALSE;
822 }
823 eat_opt_white( &cur2 );
824 if (*cur2 != ']') {
825 report_error( ctx, "Expected `]'" );
826 return FALSE;
827 }
828 cur2++;
829
830 decl.Semantic.Index = index;
831
832 cur = cur2;
833 }
834
835 decl.Declaration.Semantic = 1;
836 decl.Semantic.Name = i;
837
838 ctx->cur = cur;
839 break;
840 }
841 }
842 }
843
844 cur = ctx->cur;
845 eat_opt_white( &cur );
846 if (*cur == ',') {
847 uint i;
848
849 cur++;
850 eat_opt_white( &cur );
851 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
852 if (str_match_no_case( &cur, interpolate_names[i] )) {
853 if (is_digit_alpha_underscore( cur ))
854 continue;
855 decl.Declaration.Interpolate = i;
856
857 ctx->cur = cur;
858 break;
859 }
860 }
861 if (i == TGSI_INTERPOLATE_COUNT) {
862 report_error( ctx, "Expected semantic or interpolate attribute" );
863 return FALSE;
864 }
865 }
866
867 advance = tgsi_build_full_declaration(
868 &decl,
869 ctx->tokens_cur,
870 ctx->header,
871 (uint) (ctx->tokens_end - ctx->tokens_cur) );
872 if (advance == 0)
873 return FALSE;
874 ctx->tokens_cur += advance;
875
876 return TRUE;
877 }
878
879 static boolean parse_immediate( struct translate_ctx *ctx )
880 {
881 struct tgsi_full_immediate imm;
882 uint i;
883 float values[4];
884 uint advance;
885
886 if (!eat_white( &ctx->cur )) {
887 report_error( ctx, "Syntax error" );
888 return FALSE;
889 }
890 if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) {
891 report_error( ctx, "Expected `FLT32'" );
892 return FALSE;
893 }
894 eat_opt_white( &ctx->cur );
895 if (*ctx->cur != '{') {
896 report_error( ctx, "Expected `{'" );
897 return FALSE;
898 }
899 ctx->cur++;
900 for (i = 0; i < 4; i++) {
901 eat_opt_white( &ctx->cur );
902 if (i > 0) {
903 if (*ctx->cur != ',') {
904 report_error( ctx, "Expected `,'" );
905 return FALSE;
906 }
907 ctx->cur++;
908 eat_opt_white( &ctx->cur );
909 }
910 if (!parse_float( &ctx->cur, &values[i] )) {
911 report_error( ctx, "Expected literal floating point" );
912 return FALSE;
913 }
914 }
915 eat_opt_white( &ctx->cur );
916 if (*ctx->cur != '}') {
917 report_error( ctx, "Expected `}'" );
918 return FALSE;
919 }
920 ctx->cur++;
921
922 imm = tgsi_default_full_immediate();
923 imm.Immediate.NrTokens += 4;
924 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
925 imm.u[0].Float = values[0];
926 imm.u[1].Float = values[1];
927 imm.u[2].Float = values[2];
928 imm.u[3].Float = values[3];
929
930 advance = tgsi_build_full_immediate(
931 &imm,
932 ctx->tokens_cur,
933 ctx->header,
934 (uint) (ctx->tokens_end - ctx->tokens_cur) );
935 if (advance == 0)
936 return FALSE;
937 ctx->tokens_cur += advance;
938
939 return TRUE;
940 }
941
942 static boolean translate( struct translate_ctx *ctx )
943 {
944 eat_opt_white( &ctx->cur );
945 if (!parse_header( ctx ))
946 return FALSE;
947
948 while (*ctx->cur != '\0') {
949 uint label_val = 0;
950
951 if (!eat_white( &ctx->cur )) {
952 report_error( ctx, "Syntax error" );
953 return FALSE;
954 }
955
956 if (*ctx->cur == '\0')
957 break;
958
959 if (parse_label( ctx, &label_val )) {
960 if (!parse_instruction( ctx, TRUE ))
961 return FALSE;
962 }
963 else if (str_match_no_case( &ctx->cur, "DCL" )) {
964 if (!parse_declaration( ctx ))
965 return FALSE;
966 }
967 else if (str_match_no_case( &ctx->cur, "IMM" )) {
968 if (!parse_immediate( ctx ))
969 return FALSE;
970 }
971 else if (!parse_instruction( ctx, FALSE )) {
972 return FALSE;
973 }
974 }
975
976 return TRUE;
977 }
978
979 boolean
980 tgsi_text_translate(
981 const char *text,
982 struct tgsi_token *tokens,
983 uint num_tokens )
984 {
985 struct translate_ctx ctx;
986
987 ctx.text = text;
988 ctx.cur = text;
989 ctx.tokens = tokens;
990 ctx.tokens_cur = tokens;
991 ctx.tokens_end = tokens + num_tokens;
992
993 if (!translate( &ctx ))
994 return FALSE;
995
996 return tgsi_sanity_check( tokens );
997 }