static void ep_parse_technique(struct effect_parser *ep) { struct ep_technique ept; ep_technique_init(&ept); if (cf_next_name(&ep->cfp, &ept.name, "name", ";") != PARSE_SUCCESS) goto error; if (!cf_next_valid_token(&ep->cfp)) return; if (!cf_token_is(&ep->cfp, "{")) { if (!cf_go_to_token(&ep->cfp, ";", NULL)) { cf_adderror_expecting(&ep->cfp, ";"); return; } cf_adderror_expecting(&ep->cfp, "{"); goto error; } if (!cf_next_valid_token(&ep->cfp)) goto error; while (!cf_token_is(&ep->cfp, "}")) { struct ep_pass pass; ep_pass_init(&pass); switch (ep_parse_pass(ep, &pass)) { case PARSE_UNEXPECTED_CONTINUE: ep_pass_free(&pass); if (!cf_go_to_token(&ep->cfp, "}", NULL)) goto error; continue; case PARSE_EOF: ep_pass_free(&pass); goto error; } da_push_back(ept.passes, &pass); if (!cf_next_valid_token(&ep->cfp)) goto error; } /* pass the current token (which is '}') if we reached here */ cf_next_token(&ep->cfp); da_push_back(ep->techniques, &ept); return; error: cf_next_token(&ep->cfp); ep_technique_free(&ept); }
static inline int ep_parse_param_assign_intfloat(struct effect_parser *ep, struct ep_param *param, bool is_float) { int code; bool is_negative = false; if (!cf_next_valid_token(&ep->cfp)) return PARSE_EOF; if (cf_token_is(&ep->cfp, "-")) { is_negative = true; if (!cf_next_token(&ep->cfp)) return PARSE_EOF; } code = cf_token_is_type(&ep->cfp, CFTOKEN_NUM, "numeric value", ";"); if (code != PARSE_SUCCESS) return code; if (is_float) { float f = (float)os_strtod(ep->cfp.cur_token->str.array); if (is_negative) f = -f; da_push_back_array(param->default_val, &f, sizeof(float)); } else { long l = strtol(ep->cfp.cur_token->str.array, NULL, 10); if (is_negative) l = -l; da_push_back_array(param->default_val, &l, sizeof(long)); } return PARSE_SUCCESS; }
static int ep_parse_pass(struct effect_parser *ep, struct ep_pass *pass) { struct cf_token peek; if (!cf_token_is(&ep->cfp, "pass")) return PARSE_UNEXPECTED_CONTINUE; if (!cf_next_valid_token(&ep->cfp)) return PARSE_EOF; if (!cf_token_is(&ep->cfp, "{")) { pass->name = bstrdup_n(ep->cfp.cur_token->str.array, ep->cfp.cur_token->str.len); if (!cf_next_valid_token(&ep->cfp)) return PARSE_EOF; } if (!cf_peek_valid_token(&ep->cfp, &peek)) return PARSE_EOF; while (strref_cmp(&peek.str, "}") != 0) { int ret = ep_parse_pass_command(ep, pass); if (ret < 0 && ret != PARSE_CONTINUE) return ret; if (!cf_peek_valid_token(&ep->cfp, &peek)) return PARSE_EOF; } /* token is '}' */ cf_next_token(&ep->cfp); return PARSE_SUCCESS; }
static bool gl_write_mul(struct gl_shader_parser *glsp, struct cf_token **p_token) { struct cf_parser *cfp = &glsp->parser.cfp; cfp->cur_token = *p_token; if (!cf_next_token(cfp)) return false; if (!cf_token_is(cfp, "(")) return false; dstr_cat(&glsp->gl_string, "("); gl_write_function_contents(glsp, &cfp->cur_token, ","); dstr_cat(&glsp->gl_string, ") * ("); cf_next_token(cfp); gl_write_function_contents(glsp, &cfp->cur_token, ")"); dstr_cat(&glsp->gl_string, "))"); *p_token = cfp->cur_token; return true; }
/* processes texture.Sample(sampler, texcoord) */ static bool gl_write_texture_code(struct gl_shader_parser *glsp, struct cf_token **p_token, struct shader_var *var) { struct cf_parser *cfp = &glsp->parser.cfp; bool written = false; cfp->cur_token = *p_token; if (!cf_next_token(cfp)) return false; if (!cf_token_is(cfp, ".")) return false; if (!cf_next_token(cfp)) return false; const char *function_end = ")"; if (cf_token_is(cfp, "Sample")) written = gl_write_texture_call(glsp, var, "texture", true); else if (cf_token_is(cfp, "SampleBias")) written = gl_write_texture_call(glsp, var, "texture", true); else if (cf_token_is(cfp, "SampleGrad")) written = gl_write_texture_call(glsp, var, "textureGrad", true); else if (cf_token_is(cfp, "SampleLevel")) written = gl_write_texture_call(glsp, var, "textureLod", true); else if (cf_token_is(cfp, "Load")) { written = gl_write_texture_call(glsp, var, "texelFetch", false); dstr_cat(&glsp->gl_string, "("); function_end = ").xy, 0)"; } if (!written) return false; if (!cf_next_token(cfp)) return false; gl_write_function_contents(glsp, &cfp->cur_token, ")"); dstr_cat(&glsp->gl_string, function_end); *p_token = cfp->cur_token; return true; }
static inline bool gl_write_texture_call(struct gl_shader_parser *glsp, struct shader_var *var, const char *call, bool sampler) { struct cf_parser *cfp = &glsp->parser.cfp; size_t sampler_id = (size_t)-1; if (!cf_next_token(cfp)) return false; if (!cf_token_is(cfp, "(")) return false; if (sampler) { if (!cf_next_token(cfp)) return false; sampler_id = sp_getsampler(glsp, cfp->cur_token); if (sampler_id == (size_t) -1) return false; var->gl_sampler_id = sampler_id; if (!cf_next_token(cfp)) return false; if (!cf_token_is(cfp, ",")) return false; } dstr_cat(&glsp->gl_string, call); dstr_cat(&glsp->gl_string, "("); dstr_cat(&glsp->gl_string, var->name); dstr_cat(&glsp->gl_string, ", "); return true; }
static void ep_parse_function(struct effect_parser *ep, char *type, char *name) { struct ep_func func; int code; ep_func_init(&func, type, name); if (ep_getstruct(ep, type)) da_push_back(func.struct_deps, &func.ret_type); if (!ep_parse_func_params(ep, &func)) goto error; if (!cf_next_valid_token(&ep->cfp)) goto error; /* if function is mapped to something, for example COLOR */ if (cf_token_is(&ep->cfp, ":")) { code = cf_next_name(&ep->cfp, &func.mapping, "mapping specifier", "{"); if (code == PARSE_EOF) goto error; else if (code != PARSE_CONTINUE) { if (!cf_next_valid_token(&ep->cfp)) goto error; } } if (!cf_token_is(&ep->cfp, "{")) { cf_adderror_expecting(&ep->cfp, "{"); goto error; } if (!ep_parse_func_contents(ep, &func)) goto error; /* it is established that the current token is '}' if we reach this */ cf_next_token(&ep->cfp); da_push_back(ep->funcs, &func); return; error: ep_func_free(&func); }
static void sp_parse_function(struct shader_parser *sp, char *type, char *name) { struct shader_func func; shader_func_init(&func, type, name); if (!sp_parse_func_params(sp, &func)) goto error; if (!cf_next_valid_token(&sp->cfp)) goto error; /* if function is mapped to something, for example COLOR */ if (cf_token_is(&sp->cfp, ":")) { char *mapping = NULL; int errorcode = cf_next_name(&sp->cfp, &mapping, "mapping", "{"); if (errorcode != PARSE_SUCCESS) goto error; func.mapping = mapping; if (!cf_next_valid_token(&sp->cfp)) goto error; } if (!cf_token_is(&sp->cfp, "{")) { cf_adderror_expecting(&sp->cfp, "{"); goto error; } func.start = sp->cfp.cur_token; if (!cf_pass_pair(&sp->cfp, '{', '}')) goto error; /* it is established that the current token is '}' if we reach this */ cf_next_token(&sp->cfp); func.end = sp->cfp.cur_token; da_push_back(sp->funcs, &func); return; error: shader_func_free(&func); }
static bool sp_parse_func_params(struct shader_parser *sp, struct shader_func *func) { struct cf_token peek; int code; cf_token_clear(&peek); if (!cf_peek_valid_token(&sp->cfp, &peek)) return false; if (*peek.str.array == ')') { cf_next_token(&sp->cfp); goto exit; } do { struct shader_var var; shader_var_init(&var); if (!cf_token_is(&sp->cfp, "(") && !cf_token_is(&sp->cfp, ",")) cf_adderror_syntax_error(&sp->cfp); code = sp_parse_func_param(sp, &var); if (code != PARSE_SUCCESS) { shader_var_free(&var); if (code == PARSE_CONTINUE) goto exit; else if (code == PARSE_EOF) return false; } da_push_back(func->params, &var); } while (!cf_token_is(&sp->cfp, ")")); exit: return true; }