00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "pipe/p_debug.h"
00029 #include "tgsi_text.h"
00030 #include "tgsi_build.h"
00031 #include "tgsi_info.h"
00032 #include "tgsi_parse.h"
00033 #include "tgsi_sanity.h"
00034 #include "tgsi_util.h"
00035
00036 static boolean is_alpha_underscore( const char *cur )
00037 {
00038 return
00039 (*cur >= 'a' && *cur <= 'z') ||
00040 (*cur >= 'A' && *cur <= 'Z') ||
00041 *cur == '_';
00042 }
00043
00044 static boolean is_digit( const char *cur )
00045 {
00046 return *cur >= '0' && *cur <= '9';
00047 }
00048
00049 static boolean is_digit_alpha_underscore( const char *cur )
00050 {
00051 return is_digit( cur ) || is_alpha_underscore( cur );
00052 }
00053
00054 static boolean uprcase( char c )
00055 {
00056 if (c >= 'a' && c <= 'z')
00057 return c += 'A' - 'a';
00058 return c;
00059 }
00060
00061 static boolean str_match_no_case( const char **pcur, const char *str )
00062 {
00063 const char *cur = *pcur;
00064
00065 while (*str != '\0' && *str == uprcase( *cur )) {
00066 str++;
00067 cur++;
00068 }
00069 if (*str == '\0') {
00070 *pcur = cur;
00071 return TRUE;
00072 }
00073 return FALSE;
00074 }
00075
00076
00077
00078 static void eat_opt_white( const char **pcur )
00079 {
00080 while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
00081 (*pcur)++;
00082 }
00083
00084
00085
00086
00087 static boolean eat_white( const char **pcur )
00088 {
00089 const char *cur = *pcur;
00090
00091 eat_opt_white( pcur );
00092 return *pcur > cur;
00093 }
00094
00095
00096
00097
00098 static boolean parse_uint( const char **pcur, uint *val )
00099 {
00100 const char *cur = *pcur;
00101
00102 if (is_digit( cur )) {
00103 *val = *cur++ - '0';
00104 while (is_digit( cur ))
00105 *val = *val * 10 + *cur++ - '0';
00106 *pcur = cur;
00107 return TRUE;
00108 }
00109 return FALSE;
00110 }
00111
00112
00113
00114 static boolean parse_float( const char **pcur, float *val )
00115 {
00116 const char *cur = *pcur;
00117 boolean integral_part = FALSE;
00118 boolean fractional_part = FALSE;
00119
00120 *val = (float) atof( cur );
00121
00122 if (*cur == '-' || *cur == '+')
00123 cur++;
00124 if (is_digit( cur )) {
00125 cur++;
00126 integral_part = TRUE;
00127 while (is_digit( cur ))
00128 cur++;
00129 }
00130 if (*cur == '.') {
00131 cur++;
00132 if (is_digit( cur )) {
00133 cur++;
00134 fractional_part = TRUE;
00135 while (is_digit( cur ))
00136 cur++;
00137 }
00138 }
00139 if (!integral_part && !fractional_part)
00140 return FALSE;
00141 if (uprcase( *cur ) == 'E') {
00142 cur++;
00143 if (*cur == '-' || *cur == '+')
00144 cur++;
00145 if (is_digit( cur )) {
00146 cur++;
00147 while (is_digit( cur ))
00148 cur++;
00149 }
00150 else
00151 return FALSE;
00152 }
00153 *pcur = cur;
00154 return TRUE;
00155 }
00156
00157 struct translate_ctx
00158 {
00159 const char *text;
00160 const char *cur;
00161 struct tgsi_token *tokens;
00162 struct tgsi_token *tokens_cur;
00163 struct tgsi_token *tokens_end;
00164 struct tgsi_header *header;
00165 };
00166
00167 static void report_error( struct translate_ctx *ctx, const char *msg )
00168 {
00169 debug_printf( "\nError: %s", msg );
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 static boolean parse_header( struct translate_ctx *ctx )
00179 {
00180 uint processor;
00181
00182 if (str_match_no_case( &ctx->cur, "FRAG1.1" ))
00183 processor = TGSI_PROCESSOR_FRAGMENT;
00184 else if (str_match_no_case( &ctx->cur, "VERT1.1" ))
00185 processor = TGSI_PROCESSOR_VERTEX;
00186 else if (str_match_no_case( &ctx->cur, "GEOM1.1" ))
00187 processor = TGSI_PROCESSOR_GEOMETRY;
00188 else {
00189 report_error( ctx, "Unknown header" );
00190 return FALSE;
00191 }
00192
00193 if (ctx->tokens_cur >= ctx->tokens_end)
00194 return FALSE;
00195 *(struct tgsi_version *) ctx->tokens_cur++ = tgsi_build_version();
00196
00197 if (ctx->tokens_cur >= ctx->tokens_end)
00198 return FALSE;
00199 ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
00200 *ctx->header = tgsi_build_header();
00201
00202 if (ctx->tokens_cur >= ctx->tokens_end)
00203 return FALSE;
00204 *(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
00205
00206 return TRUE;
00207 }
00208
00209 static boolean parse_label( struct translate_ctx *ctx, uint *val )
00210 {
00211 const char *cur = ctx->cur;
00212
00213 if (parse_uint( &cur, val )) {
00214 eat_opt_white( &cur );
00215 if (*cur == ':') {
00216 cur++;
00217 ctx->cur = cur;
00218 return TRUE;
00219 }
00220 }
00221 return FALSE;
00222 }
00223
00224 static const char *file_names[TGSI_FILE_COUNT] =
00225 {
00226 "NULL",
00227 "CONST",
00228 "IN",
00229 "OUT",
00230 "TEMP",
00231 "SAMP",
00232 "ADDR",
00233 "IMM",
00234 "LOOP"
00235 };
00236
00237 static boolean
00238 parse_file( const char **pcur, uint *file )
00239 {
00240 uint i;
00241
00242 for (i = 0; i < TGSI_FILE_COUNT; i++) {
00243 const char *cur = *pcur;
00244
00245 if (str_match_no_case( &cur, file_names[i] )) {
00246 if (!is_digit_alpha_underscore( cur )) {
00247 *pcur = cur;
00248 *file = i;
00249 return TRUE;
00250 }
00251 }
00252 }
00253 return FALSE;
00254 }
00255
00256 static boolean
00257 parse_opt_writemask(
00258 struct translate_ctx *ctx,
00259 uint *writemask )
00260 {
00261 const char *cur;
00262
00263 cur = ctx->cur;
00264 eat_opt_white( &cur );
00265 if (*cur == '.') {
00266 cur++;
00267 *writemask = TGSI_WRITEMASK_NONE;
00268 eat_opt_white( &cur );
00269 if (uprcase( *cur ) == 'X') {
00270 cur++;
00271 *writemask |= TGSI_WRITEMASK_X;
00272 }
00273 if (uprcase( *cur ) == 'Y') {
00274 cur++;
00275 *writemask |= TGSI_WRITEMASK_Y;
00276 }
00277 if (uprcase( *cur ) == 'Z') {
00278 cur++;
00279 *writemask |= TGSI_WRITEMASK_Z;
00280 }
00281 if (uprcase( *cur ) == 'W') {
00282 cur++;
00283 *writemask |= TGSI_WRITEMASK_W;
00284 }
00285
00286 if (*writemask == TGSI_WRITEMASK_NONE) {
00287 report_error( ctx, "Writemask expected" );
00288 return FALSE;
00289 }
00290
00291 ctx->cur = cur;
00292 }
00293 else {
00294 *writemask = TGSI_WRITEMASK_XYZW;
00295 }
00296 return TRUE;
00297 }
00298
00299
00300
00301 static boolean
00302 parse_register_file_bracket(
00303 struct translate_ctx *ctx,
00304 uint *file )
00305 {
00306 if (!parse_file( &ctx->cur, file )) {
00307 report_error( ctx, "Unknown register file" );
00308 return FALSE;
00309 }
00310 eat_opt_white( &ctx->cur );
00311 if (*ctx->cur != '[') {
00312 report_error( ctx, "Expected `['" );
00313 return FALSE;
00314 }
00315 ctx->cur++;
00316 return TRUE;
00317 }
00318
00319
00320
00321 static boolean
00322 parse_register_file_bracket_index(
00323 struct translate_ctx *ctx,
00324 uint *file,
00325 int *index )
00326 {
00327 uint uindex;
00328
00329 if (!parse_register_file_bracket( ctx, file ))
00330 return FALSE;
00331 eat_opt_white( &ctx->cur );
00332 if (!parse_uint( &ctx->cur, &uindex )) {
00333 report_error( ctx, "Expected literal unsigned integer" );
00334 return FALSE;
00335 }
00336 *index = (int) uindex;
00337 return TRUE;
00338 }
00339
00340
00341
00342
00343 static boolean
00344 parse_register_dst(
00345 struct translate_ctx *ctx,
00346 uint *file,
00347 int *index )
00348 {
00349 if (!parse_register_file_bracket_index( ctx, file, index ))
00350 return FALSE;
00351 eat_opt_white( &ctx->cur );
00352 if (*ctx->cur != ']') {
00353 report_error( ctx, "Expected `]'" );
00354 return FALSE;
00355 }
00356 ctx->cur++;
00357 return TRUE;
00358 }
00359
00360
00361
00362
00363
00364
00365
00366 static boolean
00367 parse_register_src(
00368 struct translate_ctx *ctx,
00369 uint *file,
00370 int *index,
00371 uint *ind_file,
00372 int *ind_index )
00373 {
00374 const char *cur;
00375 uint uindex;
00376
00377 if (!parse_register_file_bracket( ctx, file ))
00378 return FALSE;
00379 eat_opt_white( &ctx->cur );
00380 cur = ctx->cur;
00381 if (parse_file( &cur, ind_file )) {
00382 if (!parse_register_dst( ctx, ind_file, ind_index ))
00383 return FALSE;
00384 eat_opt_white( &ctx->cur );
00385 if (*ctx->cur == '+' || *ctx->cur == '-') {
00386 boolean negate;
00387
00388 negate = *ctx->cur == '-';
00389 ctx->cur++;
00390 eat_opt_white( &ctx->cur );
00391 if (!parse_uint( &ctx->cur, &uindex )) {
00392 report_error( ctx, "Expected literal unsigned integer" );
00393 return FALSE;
00394 }
00395 if (negate)
00396 *index = -(int) uindex;
00397 else
00398 *index = (int) uindex;
00399 }
00400 else {
00401 *index = 0;
00402 }
00403 }
00404 else {
00405 if (!parse_uint( &ctx->cur, &uindex )) {
00406 report_error( ctx, "Expected literal unsigned integer" );
00407 return FALSE;
00408 }
00409 *index = (int) uindex;
00410 *ind_file = TGSI_FILE_NULL;
00411 *ind_index = 0;
00412 }
00413 eat_opt_white( &ctx->cur );
00414 if (*ctx->cur != ']') {
00415 report_error( ctx, "Expected `]'" );
00416 return FALSE;
00417 }
00418 ctx->cur++;
00419 return TRUE;
00420 }
00421
00422
00423
00424
00425
00426 static boolean
00427 parse_register_dcl(
00428 struct translate_ctx *ctx,
00429 uint *file,
00430 int *first,
00431 int *last )
00432 {
00433 if (!parse_register_file_bracket_index( ctx, file, first ))
00434 return FALSE;
00435 eat_opt_white( &ctx->cur );
00436 if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
00437 uint uindex;
00438
00439 ctx->cur += 2;
00440 eat_opt_white( &ctx->cur );
00441 if (!parse_uint( &ctx->cur, &uindex )) {
00442 report_error( ctx, "Expected literal integer" );
00443 return FALSE;
00444 }
00445 *last = (int) uindex;
00446 eat_opt_white( &ctx->cur );
00447 }
00448 else {
00449 *last = *first;
00450 }
00451 if (*ctx->cur != ']') {
00452 report_error( ctx, "Expected `]' or `..'" );
00453 return FALSE;
00454 }
00455 ctx->cur++;
00456 return TRUE;
00457 }
00458
00459 static const char *modulate_names[TGSI_MODULATE_COUNT] =
00460 {
00461 "_1X",
00462 "_2X",
00463 "_4X",
00464 "_8X",
00465 "_D2",
00466 "_D4",
00467 "_D8"
00468 };
00469
00470 static boolean
00471 parse_dst_operand(
00472 struct translate_ctx *ctx,
00473 struct tgsi_full_dst_register *dst )
00474 {
00475 uint file;
00476 int index;
00477 uint writemask;
00478 const char *cur;
00479
00480 if (!parse_register_dst( ctx, &file, &index ))
00481 return FALSE;
00482
00483 cur = ctx->cur;
00484 eat_opt_white( &cur );
00485 if (*cur == '_') {
00486 uint i;
00487
00488 for (i = 0; i < TGSI_MODULATE_COUNT; i++) {
00489 if (str_match_no_case( &cur, modulate_names[i] )) {
00490 if (!is_digit_alpha_underscore( cur )) {
00491 dst->DstRegisterExtModulate.Modulate = i;
00492 ctx->cur = cur;
00493 break;
00494 }
00495 }
00496 }
00497 }
00498
00499 if (!parse_opt_writemask( ctx, &writemask ))
00500 return FALSE;
00501
00502 dst->DstRegister.File = file;
00503 dst->DstRegister.Index = index;
00504 dst->DstRegister.WriteMask = writemask;
00505 return TRUE;
00506 }
00507
00508 static boolean
00509 parse_optional_swizzle(
00510 struct translate_ctx *ctx,
00511 uint swizzle[4],
00512 boolean *parsed_swizzle,
00513 boolean *parsed_extswizzle )
00514 {
00515 const char *cur = ctx->cur;
00516
00517 *parsed_swizzle = FALSE;
00518 *parsed_extswizzle = FALSE;
00519
00520 eat_opt_white( &cur );
00521 if (*cur == '.') {
00522 uint i;
00523
00524 cur++;
00525 eat_opt_white( &cur );
00526 for (i = 0; i < 4; i++) {
00527 if (uprcase( *cur ) == 'X')
00528 swizzle[i] = TGSI_SWIZZLE_X;
00529 else if (uprcase( *cur ) == 'Y')
00530 swizzle[i] = TGSI_SWIZZLE_Y;
00531 else if (uprcase( *cur ) == 'Z')
00532 swizzle[i] = TGSI_SWIZZLE_Z;
00533 else if (uprcase( *cur ) == 'W')
00534 swizzle[i] = TGSI_SWIZZLE_W;
00535 else {
00536 if (*cur == '0')
00537 swizzle[i] = TGSI_EXTSWIZZLE_ZERO;
00538 else if (*cur == '1')
00539 swizzle[i] = TGSI_EXTSWIZZLE_ONE;
00540 else {
00541 report_error( ctx, "Expected register swizzle component `x', `y', `z', `w', `0' or `1'" );
00542 return FALSE;
00543 }
00544 *parsed_extswizzle = TRUE;
00545 }
00546 cur++;
00547 }
00548 *parsed_swizzle = TRUE;
00549 ctx->cur = cur;
00550 }
00551 return TRUE;
00552 }
00553
00554 static boolean
00555 parse_src_operand(
00556 struct translate_ctx *ctx,
00557 struct tgsi_full_src_register *src )
00558 {
00559 const char *cur;
00560 float value;
00561 uint file;
00562 int index;
00563 uint ind_file;
00564 int ind_index;
00565 uint swizzle[4];
00566 boolean parsed_swizzle;
00567 boolean parsed_extswizzle;
00568
00569 if (*ctx->cur == '-') {
00570 cur = ctx->cur;
00571 cur++;
00572 eat_opt_white( &cur );
00573 if (*cur == '(') {
00574 cur++;
00575 src->SrcRegisterExtMod.Negate = 1;
00576 eat_opt_white( &cur );
00577 ctx->cur = cur;
00578 }
00579 }
00580
00581 if (*ctx->cur == '|') {
00582 ctx->cur++;
00583 eat_opt_white( &ctx->cur );
00584 src->SrcRegisterExtMod.Absolute = 1;
00585 }
00586
00587 if (*ctx->cur == '-') {
00588 ctx->cur++;
00589 eat_opt_white( &ctx->cur );
00590 src->SrcRegister.Negate = 1;
00591 }
00592
00593 cur = ctx->cur;
00594 if (parse_float( &cur, &value )) {
00595 if (value == 2.0f) {
00596 eat_opt_white( &cur );
00597 if (*cur != '*') {
00598 report_error( ctx, "Expected `*'" );
00599 return FALSE;
00600 }
00601 cur++;
00602 if (*cur != '(') {
00603 report_error( ctx, "Expected `('" );
00604 return FALSE;
00605 }
00606 cur++;
00607 src->SrcRegisterExtMod.Scale2X = 1;
00608 eat_opt_white( &cur );
00609 ctx->cur = cur;
00610 }
00611 }
00612
00613 if (*ctx->cur == '(') {
00614 ctx->cur++;
00615 eat_opt_white( &ctx->cur );
00616 src->SrcRegisterExtMod.Bias = 1;
00617 }
00618
00619 cur = ctx->cur;
00620 if (parse_float( &cur, &value )) {
00621 if (value == 1.0f) {
00622 eat_opt_white( &cur );
00623 if (*cur != '-') {
00624 report_error( ctx, "Expected `-'" );
00625 return FALSE;
00626 }
00627 cur++;
00628 if (*cur != '(') {
00629 report_error( ctx, "Expected `('" );
00630 return FALSE;
00631 }
00632 cur++;
00633 src->SrcRegisterExtMod.Complement = 1;
00634 eat_opt_white( &cur );
00635 ctx->cur = cur;
00636 }
00637 }
00638
00639 if (!parse_register_src( ctx, &file, &index, &ind_file, &ind_index ))
00640 return FALSE;
00641 src->SrcRegister.File = file;
00642 src->SrcRegister.Index = index;
00643 if (ind_file != TGSI_FILE_NULL) {
00644 src->SrcRegister.Indirect = 1;
00645 src->SrcRegisterInd.File = ind_file;
00646 src->SrcRegisterInd.Index = ind_index;
00647 }
00648
00649
00650
00651 if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, &parsed_extswizzle )) {
00652 if (parsed_extswizzle) {
00653 assert( parsed_swizzle );
00654
00655 src->SrcRegisterExtSwz.ExtSwizzleX = swizzle[0];
00656 src->SrcRegisterExtSwz.ExtSwizzleY = swizzle[1];
00657 src->SrcRegisterExtSwz.ExtSwizzleZ = swizzle[2];
00658 src->SrcRegisterExtSwz.ExtSwizzleW = swizzle[3];
00659 }
00660 else if (parsed_swizzle) {
00661 src->SrcRegister.SwizzleX = swizzle[0];
00662 src->SrcRegister.SwizzleY = swizzle[1];
00663 src->SrcRegister.SwizzleZ = swizzle[2];
00664 src->SrcRegister.SwizzleW = swizzle[3];
00665 }
00666 }
00667
00668 if (src->SrcRegisterExtMod.Complement) {
00669 eat_opt_white( &ctx->cur );
00670 if (*ctx->cur != ')') {
00671 report_error( ctx, "Expected `)'" );
00672 return FALSE;
00673 }
00674 ctx->cur++;
00675 }
00676
00677 if (src->SrcRegisterExtMod.Bias) {
00678 eat_opt_white( &ctx->cur );
00679 if (*ctx->cur != ')') {
00680 report_error( ctx, "Expected `)'" );
00681 return FALSE;
00682 }
00683 ctx->cur++;
00684 eat_opt_white( &ctx->cur );
00685 if (*ctx->cur != '-') {
00686 report_error( ctx, "Expected `-'" );
00687 return FALSE;
00688 }
00689 ctx->cur++;
00690 eat_opt_white( &ctx->cur );
00691 if (!parse_float( &ctx->cur, &value )) {
00692 report_error( ctx, "Expected literal floating point" );
00693 return FALSE;
00694 }
00695 if (value != 0.5f) {
00696 report_error( ctx, "Expected 0.5" );
00697 return FALSE;
00698 }
00699 }
00700
00701 if (src->SrcRegisterExtMod.Scale2X) {
00702 eat_opt_white( &ctx->cur );
00703 if (*ctx->cur != ')') {
00704 report_error( ctx, "Expected `)'" );
00705 return FALSE;
00706 }
00707 ctx->cur++;
00708 }
00709
00710 if (src->SrcRegisterExtMod.Absolute) {
00711 eat_opt_white( &ctx->cur );
00712 if (*ctx->cur != '|') {
00713 report_error( ctx, "Expected `|'" );
00714 return FALSE;
00715 }
00716 ctx->cur++;
00717 }
00718
00719 if (src->SrcRegisterExtMod.Negate) {
00720 eat_opt_white( &ctx->cur );
00721 if (*ctx->cur != ')') {
00722 report_error( ctx, "Expected `)'" );
00723 return FALSE;
00724 }
00725 ctx->cur++;
00726 }
00727
00728 return TRUE;
00729 }
00730
00731 static const char *texture_names[TGSI_TEXTURE_COUNT] =
00732 {
00733 "UNKNOWN",
00734 "1D",
00735 "2D",
00736 "3D",
00737 "CUBE",
00738 "RECT",
00739 "SHADOW1D",
00740 "SHADOW2D",
00741 "SHADOWRECT"
00742 };
00743
00744 static boolean
00745 parse_instruction(
00746 struct translate_ctx *ctx,
00747 boolean has_label )
00748 {
00749 uint i;
00750 uint saturate = TGSI_SAT_NONE;
00751 const struct tgsi_opcode_info *info;
00752 struct tgsi_full_instruction inst;
00753 uint advance;
00754
00755
00756
00757 eat_opt_white( &ctx->cur );
00758 for (i = 0; i < TGSI_OPCODE_LAST; i++) {
00759 const char *cur = ctx->cur;
00760
00761 info = tgsi_get_opcode_info( i );
00762 if (str_match_no_case( &cur, info->mnemonic )) {
00763 if (str_match_no_case( &cur, "_SATNV" ))
00764 saturate = TGSI_SAT_MINUS_PLUS_ONE;
00765 else if (str_match_no_case( &cur, "_SAT" ))
00766 saturate = TGSI_SAT_ZERO_ONE;
00767
00768 if (info->num_dst + info->num_src + info->is_tex == 0) {
00769 if (!is_digit_alpha_underscore( cur )) {
00770 ctx->cur = cur;
00771 break;
00772 }
00773 }
00774 else if (*cur == '\0' || eat_white( &cur )) {
00775 ctx->cur = cur;
00776 break;
00777 }
00778 }
00779 }
00780 if (i == TGSI_OPCODE_LAST) {
00781 if (has_label)
00782 report_error( ctx, "Unknown opcode" );
00783 else
00784 report_error( ctx, "Expected `DCL', `IMM' or a label" );
00785 return FALSE;
00786 }
00787
00788 inst = tgsi_default_full_instruction();
00789 inst.Instruction.Opcode = i;
00790 inst.Instruction.Saturate = saturate;
00791 inst.Instruction.NumDstRegs = info->num_dst;
00792 inst.Instruction.NumSrcRegs = info->num_src;
00793
00794
00795
00796 for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
00797 if (i > 0) {
00798 eat_opt_white( &ctx->cur );
00799 if (*ctx->cur != ',') {
00800 report_error( ctx, "Expected `,'" );
00801 return FALSE;
00802 }
00803 ctx->cur++;
00804 eat_opt_white( &ctx->cur );
00805 }
00806
00807 if (i < info->num_dst) {
00808 if (!parse_dst_operand( ctx, &inst.FullDstRegisters[i] ))
00809 return FALSE;
00810 }
00811 else if (i < info->num_dst + info->num_src) {
00812 if (!parse_src_operand( ctx, &inst.FullSrcRegisters[i - info->num_dst] ))
00813 return FALSE;
00814 }
00815 else {
00816 uint j;
00817
00818 for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
00819 if (str_match_no_case( &ctx->cur, texture_names[j] )) {
00820 if (!is_digit_alpha_underscore( ctx->cur )) {
00821 inst.InstructionExtTexture.Texture = j;
00822 break;
00823 }
00824 }
00825 }
00826 if (j == TGSI_TEXTURE_COUNT) {
00827 report_error( ctx, "Expected texture target" );
00828 return FALSE;
00829 }
00830 }
00831 }
00832
00833 if (info->is_branch) {
00834 uint target;
00835
00836 eat_opt_white( &ctx->cur );
00837 if (*ctx->cur != ':') {
00838 report_error( ctx, "Expected `:'" );
00839 return FALSE;
00840 }
00841 ctx->cur++;
00842 eat_opt_white( &ctx->cur );
00843 if (!parse_uint( &ctx->cur, &target )) {
00844 report_error( ctx, "Expected a label" );
00845 return FALSE;
00846 }
00847 inst.InstructionExtLabel.Label = target;
00848 }
00849
00850 advance = tgsi_build_full_instruction(
00851 &inst,
00852 ctx->tokens_cur,
00853 ctx->header,
00854 (uint) (ctx->tokens_end - ctx->tokens_cur) );
00855 if (advance == 0)
00856 return FALSE;
00857 ctx->tokens_cur += advance;
00858
00859 return TRUE;
00860 }
00861
00862 static const char *semantic_names[TGSI_SEMANTIC_COUNT] =
00863 {
00864 "POSITION",
00865 "COLOR",
00866 "BCOLOR",
00867 "FOG",
00868 "PSIZE",
00869 "GENERIC",
00870 "NORMAL"
00871 };
00872
00873 static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] =
00874 {
00875 "CONSTANT",
00876 "LINEAR",
00877 "PERSPECTIVE"
00878 };
00879
00880 static boolean parse_declaration( struct translate_ctx *ctx )
00881 {
00882 struct tgsi_full_declaration decl;
00883 uint file;
00884 int first;
00885 int last;
00886 uint writemask;
00887 const char *cur;
00888 uint advance;
00889
00890 if (!eat_white( &ctx->cur )) {
00891 report_error( ctx, "Syntax error" );
00892 return FALSE;
00893 }
00894 if (!parse_register_dcl( ctx, &file, &first, &last ))
00895 return FALSE;
00896 if (!parse_opt_writemask( ctx, &writemask ))
00897 return FALSE;
00898
00899 decl = tgsi_default_full_declaration();
00900 decl.Declaration.File = file;
00901 decl.Declaration.UsageMask = writemask;
00902 decl.DeclarationRange.First = first;
00903 decl.DeclarationRange.Last = last;
00904
00905 cur = ctx->cur;
00906 eat_opt_white( &cur );
00907 if (*cur == ',') {
00908 uint i;
00909
00910 cur++;
00911 eat_opt_white( &cur );
00912 for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
00913 if (str_match_no_case( &cur, semantic_names[i] )) {
00914 const char *cur2 = cur;
00915 uint index;
00916
00917 if (is_digit_alpha_underscore( cur ))
00918 continue;
00919 eat_opt_white( &cur2 );
00920 if (*cur2 == '[') {
00921 cur2++;
00922 eat_opt_white( &cur2 );
00923 if (!parse_uint( &cur2, &index )) {
00924 report_error( ctx, "Expected literal integer" );
00925 return FALSE;
00926 }
00927 eat_opt_white( &cur2 );
00928 if (*cur2 != ']') {
00929 report_error( ctx, "Expected `]'" );
00930 return FALSE;
00931 }
00932 cur2++;
00933
00934 decl.Semantic.SemanticIndex = index;
00935
00936 cur = cur2;
00937 }
00938
00939 decl.Declaration.Semantic = 1;
00940 decl.Semantic.SemanticName = i;
00941
00942 ctx->cur = cur;
00943 break;
00944 }
00945 }
00946 }
00947
00948 cur = ctx->cur;
00949 eat_opt_white( &cur );
00950 if (*cur == ',') {
00951 uint i;
00952
00953 cur++;
00954 eat_opt_white( &cur );
00955 for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
00956 if (str_match_no_case( &cur, interpolate_names[i] )) {
00957 if (is_digit_alpha_underscore( cur ))
00958 continue;
00959 decl.Declaration.Interpolate = i;
00960
00961 ctx->cur = cur;
00962 break;
00963 }
00964 }
00965 if (i == TGSI_INTERPOLATE_COUNT) {
00966 report_error( ctx, "Expected semantic or interpolate attribute" );
00967 return FALSE;
00968 }
00969 }
00970
00971 advance = tgsi_build_full_declaration(
00972 &decl,
00973 ctx->tokens_cur,
00974 ctx->header,
00975 (uint) (ctx->tokens_end - ctx->tokens_cur) );
00976 if (advance == 0)
00977 return FALSE;
00978 ctx->tokens_cur += advance;
00979
00980 return TRUE;
00981 }
00982
00983 static boolean parse_immediate( struct translate_ctx *ctx )
00984 {
00985 struct tgsi_full_immediate imm;
00986 uint i;
00987 float values[4];
00988 uint advance;
00989
00990 if (!eat_white( &ctx->cur )) {
00991 report_error( ctx, "Syntax error" );
00992 return FALSE;
00993 }
00994 if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) {
00995 report_error( ctx, "Expected `FLT32'" );
00996 return FALSE;
00997 }
00998 eat_opt_white( &ctx->cur );
00999 if (*ctx->cur != '{') {
01000 report_error( ctx, "Expected `{'" );
01001 return FALSE;
01002 }
01003 ctx->cur++;
01004 for (i = 0; i < 4; i++) {
01005 eat_opt_white( &ctx->cur );
01006 if (i > 0) {
01007 if (*ctx->cur != ',') {
01008 report_error( ctx, "Expected `,'" );
01009 return FALSE;
01010 }
01011 ctx->cur++;
01012 eat_opt_white( &ctx->cur );
01013 }
01014 if (!parse_float( &ctx->cur, &values[i] )) {
01015 report_error( ctx, "Expected literal floating point" );
01016 return FALSE;
01017 }
01018 }
01019 eat_opt_white( &ctx->cur );
01020 if (*ctx->cur != '}') {
01021 report_error( ctx, "Expected `}'" );
01022 return FALSE;
01023 }
01024 ctx->cur++;
01025
01026 imm = tgsi_default_full_immediate();
01027 imm.Immediate.Size += 4;
01028 imm.Immediate.DataType = TGSI_IMM_FLOAT32;
01029 imm.u.Pointer = values;
01030
01031 advance = tgsi_build_full_immediate(
01032 &imm,
01033 ctx->tokens_cur,
01034 ctx->header,
01035 (uint) (ctx->tokens_end - ctx->tokens_cur) );
01036 if (advance == 0)
01037 return FALSE;
01038 ctx->tokens_cur += advance;
01039
01040 return TRUE;
01041 }
01042
01043 static boolean translate( struct translate_ctx *ctx )
01044 {
01045 eat_opt_white( &ctx->cur );
01046 if (!parse_header( ctx ))
01047 return FALSE;
01048
01049 while (*ctx->cur != '\0') {
01050 uint label_val = 0;
01051
01052 if (!eat_white( &ctx->cur )) {
01053 report_error( ctx, "Syntax error" );
01054 return FALSE;
01055 }
01056
01057 if (*ctx->cur == '\0')
01058 break;
01059
01060 if (parse_label( ctx, &label_val )) {
01061 if (!parse_instruction( ctx, TRUE ))
01062 return FALSE;
01063 }
01064 else if (str_match_no_case( &ctx->cur, "DCL" )) {
01065 if (!parse_declaration( ctx ))
01066 return FALSE;
01067 }
01068 else if (str_match_no_case( &ctx->cur, "IMM" )) {
01069 if (!parse_immediate( ctx ))
01070 return FALSE;
01071 }
01072 else if (!parse_instruction( ctx, FALSE )) {
01073 return FALSE;
01074 }
01075 }
01076
01077 return TRUE;
01078 }
01079
01080 boolean
01081 tgsi_text_translate(
01082 const char *text,
01083 struct tgsi_token *tokens,
01084 uint num_tokens )
01085 {
01086 struct translate_ctx ctx;
01087
01088 ctx.text = text;
01089 ctx.cur = text;
01090 ctx.tokens = tokens;
01091 ctx.tokens_cur = tokens;
01092 ctx.tokens_end = tokens + num_tokens;
01093
01094 if (!translate( &ctx ))
01095 return FALSE;
01096
01097 return tgsi_sanity_check( tokens );
01098 }