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