radeon/r200/r300: cleanup some of the renderbuffer code
[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 "pipe/p_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> `]' |
362 * <register_file_bracket> <register_dst> `+' <uint> `]' |
363 * <register_file_bracket> <register_dst> `-' <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 {
373 const char *cur;
374 uint uindex;
375
376 if (!parse_register_file_bracket( ctx, file ))
377 return FALSE;
378 eat_opt_white( &ctx->cur );
379 cur = ctx->cur;
380 if (parse_file( &cur, ind_file )) {
381 if (!parse_register_dst( ctx, ind_file, ind_index ))
382 return FALSE;
383 eat_opt_white( &ctx->cur );
384 if (*ctx->cur == '+' || *ctx->cur == '-') {
385 boolean negate;
386
387 negate = *ctx->cur == '-';
388 ctx->cur++;
389 eat_opt_white( &ctx->cur );
390 if (!parse_uint( &ctx->cur, &uindex )) {
391 report_error( ctx, "Expected literal unsigned integer" );
392 return FALSE;
393 }
394 if (negate)
395 *index = -(int) uindex;
396 else
397 *index = (int) uindex;
398 }
399 else {
400 *index = 0;
401 }
402 }
403 else {
404 if (!parse_uint( &ctx->cur, &uindex )) {
405 report_error( ctx, "Expected literal unsigned integer" );
406 return FALSE;
407 }
408 *index = (int) uindex;
409 *ind_file = TGSI_FILE_NULL;
410 *ind_index = 0;
411 }
412 eat_opt_white( &ctx->cur );
413 if (*ctx->cur != ']') {
414 report_error( ctx, "Expected `]'" );
415 return FALSE;
416 }
417 ctx->cur++;
418 return TRUE;
419 }
420
421 /* Parse register declaration.
422 * <register_dcl> ::= <register_file_bracket_index> `]' |
423 * <register_file_bracket_index> `..' <index> `]'
424 */
425 static boolean
426 parse_register_dcl(
427 struct translate_ctx *ctx,
428 uint *file,
429 int *first,
430 int *last )
431 {
432 if (!parse_register_file_bracket_index( ctx, file, first ))
433 return FALSE;
434 eat_opt_white( &ctx->cur );
435 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
436 uint uindex;
437
438 ctx->cur += 2;
439 eat_opt_white( &ctx->cur );
440 if (!parse_uint( &ctx->cur, &uindex )) {
441 report_error( ctx, "Expected literal integer" );
442 return FALSE;
443 }
444 *last = (int) uindex;
445 eat_opt_white( &ctx->cur );
446 }
447 else {
448 *last = *first;
449 }
450 if (*ctx->cur != ']') {
451 report_error( ctx, "Expected `]' or `..'" );
452 return FALSE;
453 }
454 ctx->cur++;
455 return TRUE;
456 }
457
458 static const char *modulate_names[TGSI_MODULATE_COUNT] =
459 {
460 "_1X",
461 "_2X",
462 "_4X",
463 "_8X",
464 "_D2",
465 "_D4",
466 "_D8"
467 };
468
469 static boolean
470 parse_dst_operand(
471 struct translate_ctx *ctx,
472 struct tgsi_full_dst_register *dst )
473 {
474 uint file;
475 int index;
476 uint writemask;
477 const char *cur;
478
479 if (!parse_register_dst( ctx, &file, &index ))
480 return FALSE;
481
482 cur = ctx->cur;
483 eat_opt_white( &cur );
484 if (*cur == '_') {
485 uint i;
486
487 for (i = 0; i < TGSI_MODULATE_COUNT; i++) {
488 if (str_match_no_case( &cur, modulate_names[i] )) {
489 if (!is_digit_alpha_underscore( cur )) {
490 dst->DstRegisterExtModulate.Modulate = i;
491 ctx->cur = cur;
492 break;
493 }
494 }
495 }
496 }
497
498 if (!parse_opt_writemask( ctx, &writemask ))
499 return FALSE;
500
501 dst->DstRegister.File = file;
502 dst->DstRegister.Index = index;
503 dst->DstRegister.WriteMask = writemask;
504 return TRUE;
505 }
506
507 static boolean
508 parse_optional_swizzle(
509 struct translate_ctx *ctx,
510 uint swizzle[4],
511 boolean *parsed_swizzle,
512 boolean *parsed_extswizzle )
513 {
514 const char *cur = ctx->cur;
515
516 *parsed_swizzle = FALSE;
517 *parsed_extswizzle = FALSE;
518
519 eat_opt_white( &cur );
520 if (*cur == '.') {
521 uint i;
522
523 cur++;
524 eat_opt_white( &cur );
525 for (i = 0; i < 4; i++) {
526 if (uprcase( *cur ) == 'X')
527 swizzle[i] = TGSI_SWIZZLE_X;
528 else if (uprcase( *cur ) == 'Y')
529 swizzle[i] = TGSI_SWIZZLE_Y;
530 else if (uprcase( *cur ) == 'Z')
531 swizzle[i] = TGSI_SWIZZLE_Z;
532 else if (uprcase( *cur ) == 'W')
533 swizzle[i] = TGSI_SWIZZLE_W;
534 else {
535 if (*cur == '0')
536 swizzle[i] = TGSI_EXTSWIZZLE_ZERO;
537 else if (*cur == '1')
538 swizzle[i] = TGSI_EXTSWIZZLE_ONE;
539 else {
540 report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
541 return FALSE;
542 }
543 *parsed_extswizzle = TRUE;
544 }
545 cur++;
546 }
547 *parsed_swizzle = TRUE;
548 ctx->cur = cur;
549 }
550 return TRUE;
551 }
552
553 static boolean
554 parse_src_operand(
555 struct translate_ctx *ctx,
556 struct tgsi_full_src_register *src )
557 {
558 const char *cur;
559 float value;
560 uint file;
561 int index;
562 uint ind_file;
563 int ind_index;
564 uint swizzle[4];
565 boolean parsed_swizzle;
566 boolean parsed_extswizzle;
567
568 if (*ctx->cur == '-') {
569 cur = ctx->cur;
570 cur++;
571 eat_opt_white( &cur );
572 if (*cur == '(') {
573 cur++;
574 src->SrcRegisterExtMod.Negate = 1;
575 eat_opt_white( &cur );
576 ctx->cur = cur;
577 }
578 }
579
580 if (*ctx->cur == '|') {
581 ctx->cur++;
582 eat_opt_white( &ctx->cur );
583 src->SrcRegisterExtMod.Absolute = 1;
584 }
585
586 if (*ctx->cur == '-') {
587 ctx->cur++;
588 eat_opt_white( &ctx->cur );
589 src->SrcRegister.Negate = 1;
590 }
591
592 cur = ctx->cur;
593 if (parse_float( &cur, &value )) {
594 if (value == 2.0f) {
595 eat_opt_white( &cur );
596 if (*cur != '*') {
597 report_error( ctx, "Expected `*'" );
598 return FALSE;
599 }
600 cur++;
601 if (*cur != '(') {
602 report_error( ctx, "Expected `('" );
603 return FALSE;
604 }
605 cur++;
606 src->SrcRegisterExtMod.Scale2X = 1;
607 eat_opt_white( &cur );
608 ctx->cur = cur;
609 }
610 }
611
612 if (*ctx->cur == '(') {
613 ctx->cur++;
614 eat_opt_white( &ctx->cur );
615 src->SrcRegisterExtMod.Bias = 1;
616 }
617
618 cur = ctx->cur;
619 if (parse_float( &cur, &value )) {
620 if (value == 1.0f) {
621 eat_opt_white( &cur );
622 if (*cur != '-') {
623 report_error( ctx, "Expected `-'" );
624 return FALSE;
625 }
626 cur++;
627 if (*cur != '(') {
628 report_error( ctx, "Expected `('" );
629 return FALSE;
630 }
631 cur++;
632 src->SrcRegisterExtMod.Complement = 1;
633 eat_opt_white( &cur );
634 ctx->cur = cur;
635 }
636 }
637
638 if (!parse_register_src( ctx, &file, &index, &ind_file, &ind_index ))
639 return FALSE;
640 src->SrcRegister.File = file;
641 src->SrcRegister.Index = index;
642 if (ind_file != TGSI_FILE_NULL) {
643 src->SrcRegister.Indirect = 1;
644 src->SrcRegisterInd.File = ind_file;
645 src->SrcRegisterInd.Index = ind_index;
646 }
647
648 /* Parse optional swizzle.
649 */
650 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, &parsed_extswizzle )) {
651 if (parsed_extswizzle) {
652 assert( parsed_swizzle );
653
654 src->SrcRegisterExtSwz.ExtSwizzleX = swizzle[0];
655 src->SrcRegisterExtSwz.ExtSwizzleY = swizzle[1];
656 src->SrcRegisterExtSwz.ExtSwizzleZ = swizzle[2];
657 src->SrcRegisterExtSwz.ExtSwizzleW = swizzle[3];
658 }
659 else if (parsed_swizzle) {
660 src->SrcRegister.SwizzleX = swizzle[0];
661 src->SrcRegister.SwizzleY = swizzle[1];
662 src->SrcRegister.SwizzleZ = swizzle[2];
663 src->SrcRegister.SwizzleW = swizzle[3];
664 }
665 }
666
667 if (src->SrcRegisterExtMod.Complement) {
668 eat_opt_white( &ctx->cur );
669 if (*ctx->cur != ')') {
670 report_error( ctx, "Expected `)'" );
671 return FALSE;
672 }
673 ctx->cur++;
674 }
675
676 if (src->SrcRegisterExtMod.Bias) {
677 eat_opt_white( &ctx->cur );
678 if (*ctx->cur != ')') {
679 report_error( ctx, "Expected `)'" );
680 return FALSE;
681 }
682 ctx->cur++;
683 eat_opt_white( &ctx->cur );
684 if (*ctx->cur != '-') {
685 report_error( ctx, "Expected `-'" );
686 return FALSE;
687 }
688 ctx->cur++;
689 eat_opt_white( &ctx->cur );
690 if (!parse_float( &ctx->cur, &value )) {
691 report_error( ctx, "Expected literal floating point" );
692 return FALSE;
693 }
694 if (value != 0.5f) {
695 report_error( ctx, "Expected 0.5" );
696 return FALSE;
697 }
698 }
699
700 if (src->SrcRegisterExtMod.Scale2X) {
701 eat_opt_white( &ctx->cur );
702 if (*ctx->cur != ')') {
703 report_error( ctx, "Expected `)'" );
704 return FALSE;
705 }
706 ctx->cur++;
707 }
708
709 if (src->SrcRegisterExtMod.Absolute) {
710 eat_opt_white( &ctx->cur );
711 if (*ctx->cur != '|') {
712 report_error( ctx, "Expected `|'" );
713 return FALSE;
714 }
715 ctx->cur++;
716 }
717
718 if (src->SrcRegisterExtMod.Negate) {
719 eat_opt_white( &ctx->cur );
720 if (*ctx->cur != ')') {
721 report_error( ctx, "Expected `)'" );
722 return FALSE;
723 }
724 ctx->cur++;
725 }
726
727 return TRUE;
728 }
729
730 static const char *texture_names[TGSI_TEXTURE_COUNT] =
731 {
732 "UNKNOWN",
733 "1D",
734 "2D",
735 "3D",
736 "CUBE",
737 "RECT",
738 "SHADOW1D",
739 "SHADOW2D",
740 "SHADOWRECT"
741 };
742
743 static boolean
744 parse_instruction(
745 struct translate_ctx *ctx,
746 boolean has_label )
747 {
748 uint i;
749 uint saturate = TGSI_SAT_NONE;
750 const struct tgsi_opcode_info *info;
751 struct tgsi_full_instruction inst;
752 uint advance;
753
754 /* Parse instruction name.
755 */
756 eat_opt_white( &ctx->cur );
757 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
758 const char *cur = ctx->cur;
759
760 info = tgsi_get_opcode_info( i );
761 if (str_match_no_case( &cur, info->mnemonic )) {
762 if (str_match_no_case( &cur, "_SATNV" ))
763 saturate = TGSI_SAT_MINUS_PLUS_ONE;
764 else if (str_match_no_case( &cur, "_SAT" ))
765 saturate = TGSI_SAT_ZERO_ONE;
766
767 if (info->num_dst + info->num_src + info->is_tex == 0) {
768 if (!is_digit_alpha_underscore( cur )) {
769 ctx->cur = cur;
770 break;
771 }
772 }
773 else if (*cur == '\0' || eat_white( &cur )) {
774 ctx->cur = cur;
775 break;
776 }
777 }
778 }
779 if (i == TGSI_OPCODE_LAST) {
780 if (has_label)
781 report_error( ctx, "Unknown opcode" );
782 else
783 report_error( ctx, "Expected `DCL', `IMM' or a label" );
784 return FALSE;
785 }
786
787 inst = tgsi_default_full_instruction();
788 inst.Instruction.Opcode = i;
789 inst.Instruction.Saturate = saturate;
790 inst.Instruction.NumDstRegs = info->num_dst;
791 inst.Instruction.NumSrcRegs = info->num_src;
792
793 /* Parse instruction operands.
794 */
795 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
796 if (i > 0) {
797 eat_opt_white( &ctx->cur );
798 if (*ctx->cur != ',') {
799 report_error( ctx, "Expected `,'" );
800 return FALSE;
801 }
802 ctx->cur++;
803 eat_opt_white( &ctx->cur );
804 }
805
806 if (i < info->num_dst) {
807 if (!parse_dst_operand( ctx, &inst.FullDstRegisters[i] ))
808 return FALSE;
809 }
810 else if (i < info->num_dst + info->num_src) {
811 if (!parse_src_operand( ctx, &inst.FullSrcRegisters[i - info->num_dst] ))
812 return FALSE;
813 }
814 else {
815 uint j;
816
817 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
818 if (str_match_no_case( &ctx->cur, texture_names[j] )) {
819 if (!is_digit_alpha_underscore( ctx->cur )) {
820 inst.InstructionExtTexture.Texture = j;
821 break;
822 }
823 }
824 }
825 if (j == TGSI_TEXTURE_COUNT) {
826 report_error( ctx, "Expected texture target" );
827 return FALSE;
828 }
829 }
830 }
831
832 if (info->is_branch) {
833 uint target;
834
835 eat_opt_white( &ctx->cur );
836 if (*ctx->cur != ':') {
837 report_error( ctx, "Expected `:'" );
838 return FALSE;
839 }
840 ctx->cur++;
841 eat_opt_white( &ctx->cur );
842 if (!parse_uint( &ctx->cur, &target )) {
843 report_error( ctx, "Expected a label" );
844 return FALSE;
845 }
846 inst.InstructionExtLabel.Label = target;
847 }
848
849 advance = tgsi_build_full_instruction(
850 &inst,
851 ctx->tokens_cur,
852 ctx->header,
853 (uint) (ctx->tokens_end - ctx->tokens_cur) );
854 if (advance == 0)
855 return FALSE;
856 ctx->tokens_cur += advance;
857
858 return TRUE;
859 }
860
861 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
862 {
863 "POSITION",
864 "COLOR",
865 "BCOLOR",
866 "FOG",
867 "PSIZE",
868 "GENERIC",
869 "NORMAL"
870 };
871
872 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
873 {
874 "CONSTANT",
875 "LINEAR",
876 "PERSPECTIVE"
877 };
878
879 static boolean parse_declaration( struct translate_ctx *ctx )
880 {
881 struct tgsi_full_declaration decl;
882 uint file;
883 int first;
884 int last;
885 uint writemask;
886 const char *cur;
887 uint advance;
888
889 if (!eat_white( &ctx->cur )) {
890 report_error( ctx, "Syntax error" );
891 return FALSE;
892 }
893 if (!parse_register_dcl( ctx, &file, &first, &last ))
894 return FALSE;
895 if (!parse_opt_writemask( ctx, &writemask ))
896 return FALSE;
897
898 decl = tgsi_default_full_declaration();
899 decl.Declaration.File = file;
900 decl.Declaration.UsageMask = writemask;
901 decl.DeclarationRange.First = first;
902 decl.DeclarationRange.Last = last;
903
904 cur = ctx->cur;
905 eat_opt_white( &cur );
906 if (*cur == ',') {
907 uint i;
908
909 cur++;
910 eat_opt_white( &cur );
911 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
912 if (str_match_no_case( &cur, semantic_names[i] )) {
913 const char *cur2 = cur;
914 uint index;
915
916 if (is_digit_alpha_underscore( cur ))
917 continue;
918 eat_opt_white( &cur2 );
919 if (*cur2 == '[') {
920 cur2++;
921 eat_opt_white( &cur2 );
922 if (!parse_uint( &cur2, &index )) {
923 report_error( ctx, "Expected literal integer" );
924 return FALSE;
925 }
926 eat_opt_white( &cur2 );
927 if (*cur2 != ']') {
928 report_error( ctx, "Expected `]'" );
929 return FALSE;
930 }
931 cur2++;
932
933 decl.Semantic.SemanticIndex = index;
934
935 cur = cur2;
936 }
937
938 decl.Declaration.Semantic = 1;
939 decl.Semantic.SemanticName = i;
940
941 ctx->cur = cur;
942 break;
943 }
944 }
945 }
946
947 cur = ctx->cur;
948 eat_opt_white( &cur );
949 if (*cur == ',') {
950 uint i;
951
952 cur++;
953 eat_opt_white( &cur );
954 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
955 if (str_match_no_case( &cur, interpolate_names[i] )) {
956 if (is_digit_alpha_underscore( cur ))
957 continue;
958 decl.Declaration.Interpolate = i;
959
960 ctx->cur = cur;
961 break;
962 }
963 }
964 if (i == TGSI_INTERPOLATE_COUNT) {
965 report_error( ctx, "Expected semantic or interpolate attribute" );
966 return FALSE;
967 }
968 }
969
970 advance = tgsi_build_full_declaration(
971 &decl,
972 ctx->tokens_cur,
973 ctx->header,
974 (uint) (ctx->tokens_end - ctx->tokens_cur) );
975 if (advance == 0)
976 return FALSE;
977 ctx->tokens_cur += advance;
978
979 return TRUE;
980 }
981
982 static boolean parse_immediate( struct translate_ctx *ctx )
983 {
984 struct tgsi_full_immediate imm;
985 uint i;
986 float values[4];
987 uint advance;
988
989 if (!eat_white( &ctx->cur )) {
990 report_error( ctx, "Syntax error" );
991 return FALSE;
992 }
993 if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) {
994 report_error( ctx, "Expected `FLT32'" );
995 return FALSE;
996 }
997 eat_opt_white( &ctx->cur );
998 if (*ctx->cur != '{') {
999 report_error( ctx, "Expected `{'" );
1000 return FALSE;
1001 }
1002 ctx->cur++;
1003 for (i = 0; i < 4; i++) {
1004 eat_opt_white( &ctx->cur );
1005 if (i > 0) {
1006 if (*ctx->cur != ',') {
1007 report_error( ctx, "Expected `,'" );
1008 return FALSE;
1009 }
1010 ctx->cur++;
1011 eat_opt_white( &ctx->cur );
1012 }
1013 if (!parse_float( &ctx->cur, &values[i] )) {
1014 report_error( ctx, "Expected literal floating point" );
1015 return FALSE;
1016 }
1017 }
1018 eat_opt_white( &ctx->cur );
1019 if (*ctx->cur != '}') {
1020 report_error( ctx, "Expected `}'" );
1021 return FALSE;
1022 }
1023 ctx->cur++;
1024
1025 imm = tgsi_default_full_immediate();
1026 imm.Immediate.NrTokens += 4;
1027 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
1028 imm.u.Pointer = values;
1029
1030 advance = tgsi_build_full_immediate(
1031 &imm,
1032 ctx->tokens_cur,
1033 ctx->header,
1034 (uint) (ctx->tokens_end - ctx->tokens_cur) );
1035 if (advance == 0)
1036 return FALSE;
1037 ctx->tokens_cur += advance;
1038
1039 return TRUE;
1040 }
1041
1042 static boolean translate( struct translate_ctx *ctx )
1043 {
1044 eat_opt_white( &ctx->cur );
1045 if (!parse_header( ctx ))
1046 return FALSE;
1047
1048 while (*ctx->cur != '\0') {
1049 uint label_val = 0;
1050
1051 if (!eat_white( &ctx->cur )) {
1052 report_error( ctx, "Syntax error" );
1053 return FALSE;
1054 }
1055
1056 if (*ctx->cur == '\0')
1057 break;
1058
1059 if (parse_label( ctx, &label_val )) {
1060 if (!parse_instruction( ctx, TRUE ))
1061 return FALSE;
1062 }
1063 else if (str_match_no_case( &ctx->cur, "DCL" )) {
1064 if (!parse_declaration( ctx ))
1065 return FALSE;
1066 }
1067 else if (str_match_no_case( &ctx->cur, "IMM" )) {
1068 if (!parse_immediate( ctx ))
1069 return FALSE;
1070 }
1071 else if (!parse_instruction( ctx, FALSE )) {
1072 return FALSE;
1073 }
1074 }
1075
1076 return TRUE;
1077 }
1078
1079 boolean
1080 tgsi_text_translate(
1081 const char *text,
1082 struct tgsi_token *tokens,
1083 uint num_tokens )
1084 {
1085 struct translate_ctx ctx;
1086
1087 ctx.text = text;
1088 ctx.cur = text;
1089 ctx.tokens = tokens;
1090 ctx.tokens_cur = tokens;
1091 ctx.tokens_end = tokens + num_tokens;
1092
1093 if (!translate( &ctx ))
1094 return FALSE;
1095
1096 return tgsi_sanity_check( tokens );
1097 }