static bool cf_lexer_is_include(struct cf_lexer *lex) { bool found_include_import = false; bool found_preprocessor = false; size_t i; for (i = lex->tokens.num; i > 0; i--) { struct cf_token *token = lex->tokens.array+(i-1); if (is_space_or_tab(*token->str.array)) continue; if (!found_include_import) { if (strref_cmp(&token->str, "include") != 0 && strref_cmp(&token->str, "import") != 0) break; found_include_import = true; } else if (!found_preprocessor) { if (*token->str.array != '#') break; found_preprocessor = true; } else { return is_newline(*token->str.array); } } /* if starting line */ return found_preprocessor && found_include_import; }
static bool gl_write_intrinsic(struct gl_shader_parser *glsp, struct cf_token **p_token) { struct cf_token *token = *p_token; bool written = true; if (strref_cmp(&token->str, "atan2") == 0) { dstr_cat(&glsp->gl_string, "atan2"); } else if (strref_cmp(&token->str, "ddx") == 0) { dstr_cat(&glsp->gl_string, "dFdx"); } else if (strref_cmp(&token->str, "ddy") == 0) { dstr_cat(&glsp->gl_string, "dFdy"); } else if (strref_cmp(&token->str, "frac") == 0) { dstr_cat(&glsp->gl_string, "fract"); } else if (strref_cmp(&token->str, "lerp") == 0) { dstr_cat(&glsp->gl_string, "mix"); } else if (strref_cmp(&token->str, "rsqrt") == 0) { dstr_cat(&glsp->gl_string, "inversesqrt"); } else if (strref_cmp(&token->str, "saturate") == 0) { written = gl_write_saturate(glsp, &token); } else if (strref_cmp(&token->str, "mul") == 0) { written = gl_write_mul(glsp, &token); } else { struct shader_var *var = sp_getparam(glsp, token); if (var && astrcmp_n(var->type, "texture", 7) == 0) written = gl_write_texture_code(glsp, &token, var); else written = false; } if (written) *p_token = token; return written; }
static void ep_parse_sampler_state(struct effect_parser *ep) { struct ep_sampler eps; struct cf_token peek; ep_sampler_init(&eps); if (cf_next_name(&ep->cfp, &eps.name, "name", ";") != PARSE_SUCCESS) goto error; if (cf_next_token_should_be(&ep->cfp, "{", ";", NULL) != PARSE_SUCCESS) goto error; if (!cf_peek_valid_token(&ep->cfp, &peek)) goto error; while (strref_cmp(&peek.str, "}") != 0) { int ret = ep_parse_sampler_state_item(ep, &eps); if (ret == PARSE_EOF) goto error; if (!cf_peek_valid_token(&ep->cfp, &peek)) goto error; } if (cf_next_token_should_be(&ep->cfp, "}", ";", NULL) != PARSE_SUCCESS) goto error; if (cf_next_token_should_be(&ep->cfp, ";", NULL, NULL) != PARSE_SUCCESS) goto error; da_push_back(ep->samplers, &eps); return; error: ep_sampler_free(&eps); }
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 void cf_preprocess_ifdef(struct cf_preprocessor *pp, bool ifnot, struct cf_token **p_cur_token) { struct cf_token *cur_token = *p_cur_token; struct cf_def *def; bool is_true; next_token(&cur_token, true); if (cur_token->type != CFTOKEN_NAME) { cf_adderror_expecting(pp, cur_token, "identifier"); go_to_newline(&cur_token); goto exit; } def = cf_preprocess_get_def(pp, &cur_token->str); is_true = (def == NULL) == ifnot; if (!cf_preprocess_subblock(pp, !is_true, &cur_token)) goto exit; if (strref_cmp(&cur_token->str, "else") == 0) { if (!cf_preprocess_subblock(pp, is_true, &cur_token)) goto exit; /*} else if (strref_cmp(&cur_token->str, "elif") == 0) {*/ } cur_token++; exit: *p_cur_token = cur_token; }
static void sp_parse_sampler_state(struct shader_parser *sp) { struct shader_sampler ss; struct cf_token peek; shader_sampler_init(&ss); if (cf_next_name(&sp->cfp, &ss.name, "name", ";") != PARSE_SUCCESS) goto error; if (cf_next_token_should_be(&sp->cfp, "{", ";", NULL) != PARSE_SUCCESS) goto error; if (!cf_peek_valid_token(&sp->cfp, &peek)) goto error; while (strref_cmp(&peek.str, "}") != 0) { int ret = sp_parse_sampler_state_item(sp, &ss); if (ret == PARSE_EOF) goto error; if (!cf_peek_valid_token(&sp->cfp, &peek)) goto error; } if (cf_next_token_should_be(&sp->cfp, "}", ";", NULL) != PARSE_SUCCESS) goto error; if (cf_next_token_should_be(&sp->cfp, ";", NULL, NULL) != PARSE_SUCCESS) goto error; da_push_back(sp->samplers, &ss); return; error: shader_sampler_free(&ss); }
static inline struct ep_param *ep_getparam_strref(struct effect_parser *ep, const struct strref *ref) { size_t i; for (i = 0; i < ep->params.num; i++) { if (strref_cmp(ref, ep->params.array[i].name) == 0) return ep->params.array+i; } return NULL; }
static inline size_t sp_getsampler(struct gl_shader_parser *glsp, struct cf_token *token) { size_t i; for (i = 0; i < glsp->parser.samplers.num; i++) { struct shader_sampler *sampler = glsp->parser.samplers.array+i; if (strref_cmp(&token->str, sampler->name) == 0) return i; } return -1; }
static inline struct shader_var *sp_getparam(struct gl_shader_parser *glsp, struct cf_token *token) { size_t i; for (i = 0; i < glsp->parser.params.num; i++) { struct shader_var *param = glsp->parser.params.array+i; if (strref_cmp(&token->str, param->name) == 0) return param; } return NULL; }
static bool cf_preprocessor(struct cf_preprocessor *pp, bool if_block, struct cf_token **p_cur_token) { struct cf_token *cur_token = *p_cur_token; if (strref_cmp(&cur_token->str, "include") == 0) { cf_preprocess_include(pp, p_cur_token); } else if (strref_cmp(&cur_token->str, "define") == 0) { cf_preprocess_define(pp, p_cur_token); } else if (strref_cmp(&cur_token->str, "undef") == 0) { cf_preprocess_undef(pp, p_cur_token); } else if (strref_cmp(&cur_token->str, "ifdef") == 0) { cf_preprocess_ifdef(pp, false, p_cur_token); } else if (strref_cmp(&cur_token->str, "ifndef") == 0) { cf_preprocess_ifdef(pp, true, p_cur_token); /*} else if (strref_cmp(&cur_token->str, "if") == 0) { TODO;*/ } else if (strref_cmp(&cur_token->str, "else") == 0 || /*strref_cmp(&cur_token->str, "elif") == 0 ||*/ strref_cmp(&cur_token->str, "endif") == 0) { if (!if_block) { struct dstr name; dstr_init_strref(&name, &cur_token->str); cf_adderror(pp, cur_token,"#$1 outside of " "#if/#ifdef/#ifndef block", name.array, NULL, NULL); dstr_free(&name); (*p_cur_token)++; return true; } return false; } else if (cur_token->type != CFTOKEN_NEWLINE && cur_token->type != CFTOKEN_NONE) { /* * TODO: language-specific preprocessor stuff should be sent to * handler of some sort */ (*p_cur_token)++; } return true; }
static void ep_makeshaderstring(struct effect_parser *ep, struct dstr *shader, struct darray *shader_call, struct darray *used_params) { struct cf_token *token = shader_call->array; struct cf_token *func_name; struct ep_func *func; struct dstr call_str; dstr_init(&call_str); if (!token) return; while (token->type != CFTOKEN_NONE && is_whitespace(*token->str.array)) token++; if (token->type == CFTOKEN_NONE || strref_cmp(&token->str, "NULL") == 0) return; func_name = token; while (token->type != CFTOKEN_NONE) { struct ep_param *param = ep_getparam_strref(ep, &token->str); if (param) ep_write_param(shader, param, used_params); dstr_cat_strref(&call_str, &token->str); token++; } func = ep_getfunc_strref(ep, &func_name->str); if (!func) return; ep_write_func(ep, shader, func, used_params); ep_write_main(ep, shader, func, &call_str); dstr_free(&call_str); ep_reset_written(ep); }
static void gl_write_function_contents(struct gl_shader_parser *glsp, struct cf_token **p_token, const char *end) { struct cf_token *token = *p_token; if (token->type != CFTOKEN_NAME || ( !gl_write_type_token(glsp, token) && !gl_write_intrinsic(glsp, &token))) dstr_cat_strref(&glsp->gl_string, &token->str); while (token->type != CFTOKEN_NONE) { token++; if (end && strref_cmp(&token->str, end) == 0) break; if (token->type == CFTOKEN_NAME) { if (!gl_write_type_token(glsp, token) && !gl_write_intrinsic(glsp, &token)) dstr_cat_strref(&glsp->gl_string, &token->str); } else if (token->type == CFTOKEN_OTHER) { if (*token->str.array == '{') gl_write_function_contents(glsp, &token, "}"); else if (*token->str.array == '(') gl_write_function_contents(glsp, &token, ")"); dstr_cat_strref(&glsp->gl_string, &token->str); } else { dstr_cat_strref(&glsp->gl_string, &token->str); } } *p_token = token; }