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