X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;ds=sidebyside;f=src%2Ftypes%2Fcpp_exp.c;fp=src%2Ftypes%2Fcpp_exp.c;h=ee7a30b255fef8bfa27cccb76e584455e778c003;hb=42f44eb5bf4ecd36e26e051fada79d861d0f92d2;hp=f2a29bcc7b9be9f3c5a19da9b03cbc0e25c876a9;hpb=1b6db76e3005344b33ab45b00e7e61386a33932a;p=m6w6%2Fext-psi diff --git a/src/types/cpp_exp.c b/src/types/cpp_exp.c index f2a29bc..ee7a30b 100644 --- a/src/types/cpp_exp.c +++ b/src/types/cpp_exp.c @@ -28,6 +28,7 @@ #include #include "data.h" +#include "cpp.h" struct psi_cpp_exp *psi_cpp_exp_init(token_t type, void *data) { @@ -36,8 +37,12 @@ struct psi_cpp_exp *psi_cpp_exp_init(token_t type, void *data) switch ((exp->type = type)) { case PSI_T_WARNING: case PSI_T_ERROR: + case PSI_T_UNDEF: case PSI_T_IFDEF: case PSI_T_IFNDEF: + case PSI_T_IMPORT: + case PSI_T_INCLUDE: + case PSI_T_INCLUDE_NEXT: exp->data.tok = data; break; case PSI_T_DEFINE: @@ -54,6 +59,7 @@ struct psi_cpp_exp *psi_cpp_exp_init(token_t type, void *data) assert(0); break; } + return exp; } @@ -66,8 +72,16 @@ void psi_cpp_exp_free(struct psi_cpp_exp **exp_ptr) switch (exp->type) { case PSI_T_WARNING: case PSI_T_ERROR: + if (!exp->data.tok) { + break; + } + /* no break */ + case PSI_T_UNDEF: case PSI_T_IFDEF: case PSI_T_IFNDEF: + case PSI_T_IMPORT: + case PSI_T_INCLUDE: + case PSI_T_INCLUDE_NEXT: free(exp->data.tok); exp->data.tok = NULL; break; @@ -98,8 +112,16 @@ void psi_cpp_exp_dump(int fd, struct psi_cpp_exp *exp) switch (exp->type) { case PSI_T_WARNING: case PSI_T_ERROR: + if (!exp->data.tok) { + break; + } + /* no break */ + case PSI_T_UNDEF: case PSI_T_IFDEF: case PSI_T_IFNDEF: + case PSI_T_IMPORT: + case PSI_T_INCLUDE: + case PSI_T_INCLUDE_NEXT: dprintf(fd, "%s", exp->data.tok->text); break; case PSI_T_DEFINE: @@ -118,3 +140,176 @@ void psi_cpp_exp_dump(int fd, struct psi_cpp_exp *exp) } dprintf(fd, "\n"); } + + +static inline bool psi_cpp_level_skipped(struct psi_cpp *cpp) +{ + return cpp->skip == cpp->level; +} + +static inline void psi_cpp_level_skip(struct psi_cpp *cpp) +{ + assert(!cpp->skip); + cpp->skip = cpp->level; +} + +static inline void psi_cpp_level_unskip(struct psi_cpp *cpp) +{ + if (psi_cpp_level_skipped(cpp)) { + cpp->skip = 0; + } +} + +static inline bool psi_cpp_level_masked(struct psi_cpp *cpp) +{ + return cpp->seen & (1 << cpp->level); +} + +static inline void psi_cpp_level_mask(struct psi_cpp *cpp) +{ + assert(!psi_cpp_level_masked(cpp)); + cpp->seen |= (1 << cpp->level); +} + +static inline void psi_cpp_level_unmask(struct psi_cpp *cpp) +{ + cpp->seen &= ~(1 << cpp->level); +} + +void psi_cpp_exp_exec(struct psi_cpp_exp *exp, struct psi_cpp *cpp, struct psi_data *D) +{ + PSI_DEBUG_PRINT(D, "PSI: CPP EVAL < %s (level=%u, skip=%u)\n", + exp->token->text, cpp->level, cpp->skip); + +#if PSI_CPP_DEBUG + psi_cpp_exp_dump(2, exp); +#endif + + switch (exp->type) { + case PSI_T_ERROR: + if (!cpp->skip) { + D->error(D, exp->token, PSI_ERROR, "%s", + exp->data.tok ? exp->data.tok->text : ""); + } + break; + case PSI_T_WARNING: + if (!cpp->skip) { + D->error(D, exp->token, PSI_WARNING, "%s", + exp->data.tok ? exp->data.tok->text : ""); + } + break; + case PSI_T_UNDEF: + if (!cpp->skip) { + psi_cpp_undef(cpp, exp->data.tok); + } + break; + case PSI_T_DEFINE: + if (!cpp->skip) { + psi_cpp_define(cpp, exp->data.decl); + /* FIXME: copy */ + exp->data.decl = NULL; + } + break; + case PSI_T_IFDEF: + ++cpp->level; + if (!cpp->skip) { + if (psi_cpp_defined(cpp, exp->data.tok)) { + psi_cpp_level_mask(cpp); + } else { + psi_cpp_level_skip(cpp); + } + } + break; + case PSI_T_IFNDEF: + ++cpp->level; + if (!cpp->skip) { + if (psi_cpp_defined(cpp, exp->data.tok)) { + psi_cpp_level_skip(cpp); + } else { + psi_cpp_level_mask(cpp); + } + } + break; + case PSI_T_IF: + ++cpp->level; + if (!cpp->skip) { + if (psi_cpp_if(cpp, exp)) { + psi_cpp_level_mask(cpp); + } else { + psi_cpp_level_skip(cpp); + } + } + break; + case PSI_T_ENDIF: + if (!cpp->level) { + D->error(D, exp->token, PSI_WARNING, "Ingoring lone #endif"); + } else { + psi_cpp_level_unskip(cpp); + psi_cpp_level_unmask(cpp); + --cpp->level; + } + break; + case PSI_T_ELSE: + /* FIXME: catch "else" after "else" */ + if (!cpp->level) { + D->error(D, exp->token, PSI_WARNING, "Ingoring lone #else"); + } else if (psi_cpp_level_skipped(cpp) && !psi_cpp_level_masked(cpp)) { + /* + * if skip is set on this level and the level has + * not been masked yet, then unskip and mask this level + */ + psi_cpp_level_unskip(cpp); + psi_cpp_level_mask(cpp); + } else if (!cpp->skip && psi_cpp_level_masked(cpp)) { + /* + * previous block masked this level + */ + psi_cpp_level_skip(cpp); + } else { + assert(cpp->skip <= cpp->level); + } + break; + case PSI_T_ELIF: + if (!cpp->level) { + D->error(D, exp->token, PSI_WARNING, "Ingoring lone #elif"); + } else if (psi_cpp_level_skipped(cpp) && !psi_cpp_level_masked(cpp)) { + /* + * if skip is set on this level and the level has + * not been masked yet, then unskip and mask this + * level, if the condition evals truthy + */ + if (psi_cpp_if(cpp, exp)) { + psi_cpp_level_unskip(cpp); + psi_cpp_level_mask(cpp); + } + } else if (!cpp->skip && psi_cpp_level_masked(cpp)) { + /* + * previous block masked this level + */ + psi_cpp_level_skip(cpp); + } else { + assert(cpp->skip <= cpp->level); + } + break; + case PSI_T_INCLUDE: + if (!cpp->skip) { + if (!psi_cpp_include(cpp, exp->data.tok->text, PSI_CPP_INCLUDE)) { + D->error(D, exp->token, PSI_WARNING, "Failed to include %s", exp->data.tok->text); + } + } + break; + case PSI_T_INCLUDE_NEXT: + if (!cpp->skip) { + if (!psi_cpp_include(cpp, exp->data.tok->text, PSI_CPP_INCLUDE_NEXT)) { + D->error(D, exp->token, PSI_WARNING, "Failed to include %s", exp->data.tok->text); + } + } + break; + default: + assert(0); + break; + } + + PSI_DEBUG_PRINT(D, "PSI: CPP EVAL > %s (level=%u, skip=%u)\n", + exp->token->text, cpp->level, cpp->skip); +}