int cmdline_complete(struct cmdline *cl, const char *buf, int *state, char *dst, unsigned int size) { const char *partial_tok = buf; unsigned int inst_num = 0; cmdline_parse_inst_t *inst; cmdline_parse_token_hdr_t *token_p; struct cmdline_token_hdr token_hdr; char tmpbuf[CMDLINE_BUFFER_SIZE], comp_buf[CMDLINE_BUFFER_SIZE]; unsigned int partial_tok_len; int comp_len = -1; int tmp_len = -1; int nb_token = 0; unsigned int i, n; int l; unsigned int nb_completable; unsigned int nb_non_completable; int local_state = 0; const char *help_str; cmdline_parse_ctx_t *ctx; if (!cl || !buf || !state || !dst) return -1; ctx = cl->ctx; debug_printf("%s called\n", __func__); memset(&token_hdr, 0, sizeof(token_hdr)); /* count the number of complete token to parse */ for (i=0 ; buf[i] ; i++) { if (!isblank2(buf[i]) && isblank2(buf[i+1])) nb_token++; if (isblank2(buf[i]) && !isblank2(buf[i+1])) partial_tok = buf+i+1; } partial_tok_len = strnlen(partial_tok, RDLINE_BUF_SIZE); /* first call -> do a first pass */ if (*state <= 0) { debug_printf("try complete <%s>\n", buf); debug_printf("there is %d complete tokens, <%s> is incomplete\n", nb_token, partial_tok); nb_completable = 0; nb_non_completable = 0; inst = ctx[inst_num]; while (inst) { /* parse the first tokens of the inst */ if (nb_token && match_inst(inst, buf, nb_token, NULL, 0)) goto next; debug_printf("instruction match\n"); token_p = get_token(inst, nb_token); if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); /* non completable */ if (!token_p || !token_hdr.ops->complete_get_nb || !token_hdr.ops->complete_get_elt || (n = token_hdr.ops->complete_get_nb(token_p)) == 0) { nb_non_completable++; goto next; } debug_printf("%d choices for this token\n", n); for (i=0 ; i<n ; i++) { if (token_hdr.ops->complete_get_elt(token_p, i, tmpbuf, sizeof(tmpbuf)) < 0) continue; /* we have at least room for one char */ tmp_len = strnlen(tmpbuf, sizeof(tmpbuf)); if (tmp_len < CMDLINE_BUFFER_SIZE - 1) { tmpbuf[tmp_len] = ' '; tmpbuf[tmp_len+1] = 0; } debug_printf(" choice <%s>\n", tmpbuf); /* does the completion match the * beginning of the word ? */ if (!strncmp(partial_tok, tmpbuf, partial_tok_len)) { if (comp_len == -1) { snprintf(comp_buf, sizeof(comp_buf), "%s", tmpbuf + partial_tok_len); comp_len = strnlen(tmpbuf + partial_tok_len, sizeof(tmpbuf) - partial_tok_len); } else { comp_len = nb_common_chars(comp_buf, tmpbuf+partial_tok_len); comp_buf[comp_len] = 0; } nb_completable++; } } next: debug_printf("next\n"); inst_num ++; inst = ctx[inst_num]; } debug_printf("total choices %d for this completion\n", nb_completable); /* no possible completion */ if (nb_completable == 0 && nb_non_completable == 0) return 0; /* if multichoice is not required */ if (*state == 0 && partial_tok_len > 0) { /* one or several choices starting with the same chars */ if (comp_len > 0) { if ((unsigned)(comp_len + 1) > size) return 0; snprintf(dst, size, "%s", comp_buf); dst[comp_len] = 0; return 2; } } } /* init state correctly */ if (*state == -1) *state = 0; debug_printf("Multiple choice STATE=%d\n", *state); inst_num = 0; inst = ctx[inst_num]; while (inst) { /* we need to redo it */ inst = ctx[inst_num]; if (nb_token && match_inst(inst, buf, nb_token, NULL, 0)) goto next2; token_p = get_token(inst, nb_token); if (token_p) memcpy(&token_hdr, token_p, sizeof(token_hdr)); /* one choice for this token */ if (!token_p || !token_hdr.ops->complete_get_nb || !token_hdr.ops->complete_get_elt || (n = token_hdr.ops->complete_get_nb(token_p)) == 0) { if (local_state < *state) { local_state++; goto next2; } (*state)++; if (token_p && token_hdr.ops->get_help) { token_hdr.ops->get_help(token_p, tmpbuf, sizeof(tmpbuf)); help_str = inst->help_str; if (help_str) snprintf(dst, size, "[%s]: %s", tmpbuf, help_str); else snprintf(dst, size, "[%s]: No help", tmpbuf); } else { snprintf(dst, size, "[RETURN]"); } return 1; } /* several choices */ for (i=0 ; i<n ; i++) { if (token_hdr.ops->complete_get_elt(token_p, i, tmpbuf, sizeof(tmpbuf)) < 0) continue; /* we have at least room for one char */ tmp_len = strnlen(tmpbuf, sizeof(tmpbuf)); if (tmp_len < CMDLINE_BUFFER_SIZE - 1) { tmpbuf[tmp_len] = ' '; tmpbuf[tmp_len + 1] = 0; } debug_printf(" choice <%s>\n", tmpbuf); /* does the completion match the beginning of * the word ? */ if (!strncmp(partial_tok, tmpbuf, partial_tok_len)) { if (local_state < *state) { local_state++; continue; } (*state)++; l=snprintf(dst, size, "%s", tmpbuf); if (l>=0 && token_hdr.ops->get_help) { token_hdr.ops->get_help(token_p, tmpbuf, sizeof(tmpbuf)); help_str = inst->help_str; if (help_str) snprintf(dst+l, size-l, "[%s]: %s", tmpbuf, help_str); else snprintf(dst+l, size-l, "[%s]: No help", tmpbuf); } return 1; } } next2: inst_num ++; inst = ctx[inst_num]; } return 0; }
int cmdline_parse(struct cmdline *cl, const char * buf) { unsigned int inst_num=0; cmdline_parse_inst_t *inst; const char *curbuf; union { char buf[CMDLINE_PARSE_RESULT_BUFSIZE]; long double align; /* strong alignment constraint for buf */ } result, tmp_result; void (*f)(void *, struct cmdline *, void *) = NULL; void *data = NULL; int comment = 0; int linelen = 0; int parse_it = 0; int err = CMDLINE_PARSE_NOMATCH; int tok; cmdline_parse_ctx_t *ctx; #ifdef RTE_LIBRTE_CMDLINE_DEBUG char debug_buf[BUFSIZ]; #endif if (!cl || !buf) return CMDLINE_PARSE_BAD_ARGS; ctx = cl->ctx; /* * - look if the buffer contains at least one line * - look if line contains only spaces or comments * - count line length */ curbuf = buf; while (! isendofline(*curbuf)) { if ( *curbuf == '\0' ) { debug_printf("Incomplete buf (len=%d)\n", linelen); return 0; } if ( iscomment(*curbuf) ) { comment = 1; } if ( ! isblank2(*curbuf) && ! comment) { parse_it = 1; } curbuf++; linelen++; } /* skip all endofline chars */ while (isendofline(buf[linelen])) { linelen++; } /* empty line */ if ( parse_it == 0 ) { debug_printf("Empty line (len=%d)\n", linelen); return linelen; } #ifdef RTE_LIBRTE_CMDLINE_DEBUG snprintf(debug_buf, (linelen>64 ? 64 : linelen), "%s", buf); debug_printf("Parse line : len=%d, <%s>\n", linelen, debug_buf); #endif /* parse it !! */ inst = ctx[inst_num]; while (inst) { debug_printf("INST %d\n", inst_num); /* fully parsed */ tok = match_inst(inst, buf, 0, tmp_result.buf, sizeof(tmp_result.buf)); if (tok > 0) /* we matched at least one token */ err = CMDLINE_PARSE_BAD_ARGS; else if (!tok) { debug_printf("INST fully parsed\n"); memcpy(&result, &tmp_result, sizeof(result)); /* skip spaces */ while (isblank2(*curbuf)) { curbuf++; } /* if end of buf -> there is no garbage after inst */ if (isendofline(*curbuf) || iscomment(*curbuf)) { if (!f) { memcpy(&f, &inst->f, sizeof(f)); memcpy(&data, &inst->data, sizeof(data)); } else { /* more than 1 inst matches */ err = CMDLINE_PARSE_AMBIGUOUS; f=NULL; debug_printf("Ambiguous cmd\n"); break; } } } inst_num ++; inst = ctx[inst_num]; } /* call func */ if (f) { f(result.buf, cl, data); } /* no match */ else { debug_printf("No match err=%d\n", err); return err; } return linelen; }
static boolean parse_instruction( struct translate_ctx *ctx, boolean has_label ) { uint i; uint saturate = 0; const struct tgsi_opcode_info *info; struct tgsi_full_instruction inst; const char *cur; uint advance; inst = tgsi_default_full_instruction(); /* Parse predicate. */ eat_opt_white( &ctx->cur ); if (*ctx->cur == '(') { uint file; int index; uint swizzle[4]; boolean parsed_swizzle; inst.Instruction.Predicate = 1; ctx->cur++; if (*ctx->cur == '!') { ctx->cur++; inst.Predicate.Negate = 1; } if (!parse_register_1d( ctx, &file, &index )) return FALSE; if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle, 4 )) { if (parsed_swizzle) { inst.Predicate.SwizzleX = swizzle[0]; inst.Predicate.SwizzleY = swizzle[1]; inst.Predicate.SwizzleZ = swizzle[2]; inst.Predicate.SwizzleW = swizzle[3]; } } if (*ctx->cur != ')') { report_error( ctx, "Expected `)'" ); return FALSE; } ctx->cur++; } /* Parse instruction name. */ eat_opt_white( &ctx->cur ); for (i = 0; i < TGSI_OPCODE_LAST; i++) { cur = ctx->cur; info = tgsi_get_opcode_info( i ); if (match_inst(&cur, &saturate, info)) { if (info->num_dst + info->num_src + info->is_tex == 0) { ctx->cur = cur; break; } else if (*cur == '\0' || eat_white( &cur )) { ctx->cur = cur; break; } } } if (i == TGSI_OPCODE_LAST) { if (has_label) report_error( ctx, "Unknown opcode" ); else report_error( ctx, "Expected `DCL', `IMM' or a label" ); return FALSE; } inst.Instruction.Opcode = i; inst.Instruction.Saturate = saturate; inst.Instruction.NumDstRegs = info->num_dst; inst.Instruction.NumSrcRegs = info->num_src; if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { /* * These are not considered tex opcodes here (no additional * target argument) however we're required to set the Texture * bit so we can set the number of tex offsets. */ inst.Instruction.Texture = 1; inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; } if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || i == TGSI_OPCODE_RESQ) { inst.Instruction.Memory = 1; inst.Memory.Qualifier = 0; } /* Parse instruction operands. */ for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { if (i > 0) { eat_opt_white( &ctx->cur ); if (*ctx->cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ctx->cur++; eat_opt_white( &ctx->cur ); } if (i < info->num_dst) { if (!parse_dst_operand( ctx, &inst.Dst[i] )) return FALSE; } else if (i < info->num_dst + info->num_src) { if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) return FALSE; } else { uint j; for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { inst.Instruction.Texture = 1; inst.Texture.Texture = j; break; } } if (j == TGSI_TEXTURE_COUNT) { report_error( ctx, "Expected texture target" ); return FALSE; } } } cur = ctx->cur; eat_opt_white( &cur ); for (i = 0; inst.Instruction.Texture && *cur == ','; i++) { cur++; eat_opt_white( &cur ); ctx->cur = cur; if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) return FALSE; cur = ctx->cur; eat_opt_white( &cur ); } inst.Texture.NumOffsets = i; cur = ctx->cur; eat_opt_white(&cur); for (i = 0; inst.Instruction.Memory && *cur == ','; i++) { uint j; cur++; eat_opt_white(&cur); ctx->cur = cur; for (j = 0; j < 3; j++) { if (str_match_nocase_whole(&ctx->cur, tgsi_memory_names[j])) { inst.Memory.Qualifier |= 1U << j; break; } } if (j == 3) { report_error(ctx, "Expected memory qualifier"); return FALSE; } cur = ctx->cur; eat_opt_white(&cur); } cur = ctx->cur; eat_opt_white( &cur ); if (info->is_branch && *cur == ':') { uint target; cur++; eat_opt_white( &cur ); if (!parse_uint( &cur, &target )) { report_error( ctx, "Expected a label" ); return FALSE; } inst.Instruction.Label = 1; inst.Label.Label = target; ctx->cur = cur; } advance = tgsi_build_full_instruction( &inst, ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); if (advance == 0) return FALSE; ctx->tokens_cur += advance; return TRUE; }
int8_t complete(parse_pgm_ctx_t ctx[], const char *buf, int16_t *state, char *dst, uint8_t size) { const char * incomplete_token = buf; uint8_t inst_num = 0; parse_pgm_inst_t *inst; parse_pgm_token_hdr_t *token_p; struct token_hdr token_hdr; char tmpbuf[64], completion_buf[64]; uint8_t incomplete_token_len; int8_t completion_len = -1; int8_t nb_token = 0; uint8_t i, n; int8_t l; uint8_t nb_completable; uint8_t nb_non_completable; uint16_t local_state=0; prog_char *help_str; debug_printf("%s called\n", __FUNCTION__); /* count the number of complete token to parse */ for (i=0 ; buf[i] ; i++) { if (!isblank(buf[i]) && isblank(buf[i+1])) nb_token++; if (isblank(buf[i]) && !isblank(buf[i+1])) incomplete_token = buf+i+1; } incomplete_token_len = strlen(incomplete_token); /* first call -> do a first pass */ if (*state <= 0) { debug_printf("try complete <%s>\n", buf); debug_printf("there is %d complete tokens, <%s> is incomplete\n", nb_token, incomplete_token); nb_completable = 0; nb_non_completable = 0; inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); while (inst) { /* parse the first tokens of the inst */ if (nb_token && match_inst(inst, buf, nb_token, NULL)) goto next; debug_printf("instruction match \n"); token_p = (parse_pgm_token_hdr_t *) pgm_read_word(&inst->tokens[nb_token]); if (token_p) memcpy_P(&token_hdr, token_p, sizeof(token_hdr)); /* non completable */ if (!token_p || !token_hdr.ops->complete_get_nb || !token_hdr.ops->complete_get_elt || (n = token_hdr.ops->complete_get_nb(token_p)) == 0) { nb_non_completable++; goto next; } debug_printf("%d choices for this token\n", n); for (i=0 ; i<n ; i++) { if (token_hdr.ops->complete_get_elt(token_p, i, tmpbuf, sizeof(tmpbuf)) < 0) continue; strcat_P(tmpbuf, PSTR(" ")); /* we have at least room for one char */ debug_printf(" choice <%s>\n", tmpbuf); /* does the completion match the beginning of the word ? */ if (!strncmp(incomplete_token, tmpbuf, incomplete_token_len)) { if (completion_len == -1) { strcpy(completion_buf, tmpbuf+incomplete_token_len); completion_len = strlen(tmpbuf+incomplete_token_len); } else { completion_len = nb_common_chars(completion_buf, tmpbuf+incomplete_token_len); completion_buf[completion_len] = 0; } nb_completable++; } } next: inst_num ++; inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); } debug_printf("total choices %d for this completion\n", nb_completable); /* no possible completion */ if (nb_completable == 0 && nb_non_completable == 0) return 0; /* if multichoice is not required */ if (*state == 0 && incomplete_token_len > 0) { /* one or several choices starting with the same chars */ if (completion_len > 0) { if (completion_len + 1 > size) return 0; strcpy(dst, completion_buf); return 2; } } } /* init state correctly */ if (*state == -1) *state = 0; debug_printf("Multiple choice STATE=%d\n", *state); inst_num = 0; inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); while (inst) { /* we need to redo it */ inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); if (nb_token && match_inst(inst, buf, nb_token, NULL)) goto next2; token_p = (parse_pgm_token_hdr_t *)pgm_read_word(&inst->tokens[nb_token]); if (token_p) memcpy_P(&token_hdr, token_p, sizeof(token_hdr)); /* one choice for this token */ if (!token_p || !token_hdr.ops->complete_get_nb || !token_hdr.ops->complete_get_elt || (n = token_hdr.ops->complete_get_nb(token_p)) == 0) { if (local_state < *state) { local_state++; goto next2; } (*state)++; if (token_p && token_hdr.ops->get_help) { token_hdr.ops->get_help(token_p, tmpbuf, sizeof(tmpbuf)); help_str = (prog_char *) pgm_read_word(&inst->help_str); if (help_str) snprintf_P(dst, size, PSTR("[%s]: %S"), tmpbuf, help_str); else snprintf_P(dst, size, PSTR("[%s]: No help"), tmpbuf); } else { snprintf_P(dst, size, PSTR("[RETURN]")); } return 1; } /* several choices */ for (i=0 ; i<n ; i++) { if (token_hdr.ops->complete_get_elt(token_p, i, tmpbuf, sizeof(tmpbuf)) < 0) continue; strcat_P(tmpbuf, PSTR(" ")); /* we have at least room for one char */ debug_printf(" choice <%s>\n", tmpbuf); /* does the completion match the beginning of the word ? */ if (!strncmp(incomplete_token, tmpbuf, incomplete_token_len)) { if (local_state < *state) { local_state++; continue; } (*state)++; l=snprintf(dst, size, "%s", tmpbuf); if (l>=0 && token_hdr.ops->get_help) { token_hdr.ops->get_help(token_p, tmpbuf, sizeof(tmpbuf)); help_str = (prog_char *) pgm_read_word(&inst->help_str); if (help_str) snprintf_P(dst+l, size-l, PSTR("[%s]: %S"), tmpbuf, help_str); else snprintf_P(dst+l, size-l, PSTR("[%s]: No help"), tmpbuf); } return 1; } } next2: inst_num ++; inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); } return 0; }
int8_t parse(parse_pgm_ctx_t ctx[], const char * buf) { uint8_t inst_num=0; parse_pgm_inst_t * inst; const char * curbuf; char result_buf[256]; /* XXX align, size zé in broblém */ void (*f)(void *, void *) = NULL; void * data = NULL; int comment = 0; int linelen = 0; int parse_it = 0; int8_t err = PARSE_NOMATCH; int8_t tok; #ifdef CMDLINE_DEBUG char debug_buf[64]; #endif /* * - look if the buffer contains at least one line * - look if line contains only spaces or comments * - count line length */ curbuf = buf; while (! isendofline(*curbuf)) { if ( *curbuf == '\0' ) { debug_printf("Incomplete buf (len=%d)\n", linelen); return 0; } if ( iscomment(*curbuf) ) { comment = 1; } if ( ! isblank(*curbuf) && ! comment) { parse_it = 1; } curbuf++; linelen++; } /* skip all endofline chars */ while (isendofline(buf[linelen])) { linelen++; } /* empty line */ if ( parse_it == 0 ) { debug_printf("Empty line (len=%d)\n", linelen); return linelen; } #ifdef CMDLINE_DEBUG snprintf(debug_buf, (linelen>64 ? 64 : linelen), "%s", buf); debug_printf("Parse line : len=%d, <%s>\n", linelen, debug_buf); #endif /* parse it !! */ inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); while (inst) { debug_printf("INST\n"); /* fully parsed */ tok = match_inst(inst, buf, 0, result_buf); if (tok > 0) /* we matched at least one token */ err = PARSE_BAD_ARGS; else if (!tok) { debug_printf("INST fully parsed\n"); /* skip spaces */ while (isblank(*curbuf)) { curbuf++; } /* if end of buf -> there is no garbage after inst */ if (isendofline(*curbuf) || iscomment(*curbuf)) { if (!f) { memcpy_P(&f, &inst->f, sizeof(f)); memcpy_P(&data, &inst->data, sizeof(data)); } else { /* more than 1 inst matches */ err = PARSE_AMBIGUOUS; f=NULL; debug_printf("Ambiguous cmd\n"); break; } } } inst_num ++; inst = (parse_pgm_inst_t *)pgm_read_word(ctx+inst_num); } /* call func */ if (f) { f(result_buf, data); } /* no match */ else { debug_printf("No match err=%d\n", err); return err; } return linelen; }
static boolean parse_instruction( struct translate_ctx *ctx, boolean has_label ) { uint i; uint saturate = 0; uint precise = 0; const struct tgsi_opcode_info *info; struct tgsi_full_instruction inst; const char *cur; uint advance; inst = tgsi_default_full_instruction(); /* Parse instruction name. */ eat_opt_white( &ctx->cur ); for (i = 0; i < TGSI_OPCODE_LAST; i++) { cur = ctx->cur; info = tgsi_get_opcode_info( i ); if (match_inst(&cur, &saturate, &precise, info)) { if (info->num_dst + info->num_src + info->is_tex == 0) { ctx->cur = cur; break; } else if (*cur == '\0' || eat_white( &cur )) { ctx->cur = cur; break; } } } if (i == TGSI_OPCODE_LAST) { if (has_label) report_error( ctx, "Unknown opcode" ); else report_error( ctx, "Expected `DCL', `IMM' or a label" ); return FALSE; } inst.Instruction.Opcode = i; inst.Instruction.Saturate = saturate; inst.Instruction.Precise = precise; inst.Instruction.NumDstRegs = info->num_dst; inst.Instruction.NumSrcRegs = info->num_src; if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) { /* * These are not considered tex opcodes here (no additional * target argument) however we're required to set the Texture * bit so we can set the number of tex offsets. */ inst.Instruction.Texture = 1; inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN; } if ((i >= TGSI_OPCODE_LOAD && i <= TGSI_OPCODE_ATOMIMAX) || i == TGSI_OPCODE_RESQ) { inst.Instruction.Memory = 1; inst.Memory.Qualifier = 0; } assume(info->num_dst <= TGSI_FULL_MAX_DST_REGISTERS); assume(info->num_src <= TGSI_FULL_MAX_SRC_REGISTERS); /* Parse instruction operands. */ for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) { if (i > 0) { eat_opt_white( &ctx->cur ); if (*ctx->cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ctx->cur++; eat_opt_white( &ctx->cur ); } if (i < info->num_dst) { if (!parse_dst_operand( ctx, &inst.Dst[i] )) return FALSE; } else if (i < info->num_dst + info->num_src) { if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] )) return FALSE; } else { uint j; for (j = 0; j < TGSI_TEXTURE_COUNT; j++) { if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) { inst.Instruction.Texture = 1; inst.Texture.Texture = j; break; } } if (j == TGSI_TEXTURE_COUNT) { report_error( ctx, "Expected texture target" ); return FALSE; } } } cur = ctx->cur; eat_opt_white( &cur ); for (i = 0; inst.Instruction.Texture && *cur == ',' && i < TGSI_FULL_MAX_TEX_OFFSETS; i++) { cur++; eat_opt_white( &cur ); ctx->cur = cur; if (!parse_texoffset_operand( ctx, &inst.TexOffsets[i] )) return FALSE; cur = ctx->cur; eat_opt_white( &cur ); } inst.Texture.NumOffsets = i; cur = ctx->cur; eat_opt_white(&cur); for (; inst.Instruction.Memory && *cur == ','; ctx->cur = cur, eat_opt_white(&cur)) { int j; cur++; eat_opt_white(&cur); j = str_match_name_from_array(&cur, tgsi_memory_names, ARRAY_SIZE(tgsi_memory_names)); if (j >= 0) { inst.Memory.Qualifier |= 1U << j; continue; } j = str_match_name_from_array(&cur, tgsi_texture_names, ARRAY_SIZE(tgsi_texture_names)); if (j >= 0) { inst.Memory.Texture = j; continue; } j = str_match_format(&cur); if (j >= 0) { inst.Memory.Format = j; continue; } ctx->cur = cur; report_error(ctx, "Expected memory qualifier, texture target, or format\n"); return FALSE; } cur = ctx->cur; eat_opt_white( &cur ); if (info->is_branch && *cur == ':') { uint target; cur++; eat_opt_white( &cur ); if (!parse_uint( &cur, &target )) { report_error( ctx, "Expected a label" ); return FALSE; } inst.Instruction.Label = 1; inst.Label.Label = target; ctx->cur = cur; } advance = tgsi_build_full_instruction( &inst, ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); if (advance == 0) return FALSE; ctx->tokens_cur += advance; return TRUE; }