X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Ftypes%2Fnumber.c;h=840eb036ba29de8a89a9cb967f9da72ab502a028;hp=5e62c62535e8297baaf33c9e2df3e76a2aa658fd;hb=a7ac1c0a3c855321f21682c127a4b707de33a303;hpb=ef40ce43c98a00823e06c14f5cf7a8241f637ab1 diff --git a/src/types/number.c b/src/types/number.c index 5e62c62..840eb03 100644 --- a/src/types/number.c +++ b/src/types/number.c @@ -26,21 +26,27 @@ #include "php_psi_stdinc.h" #include +#include #include "data.h" #include "calc.h" #include "call.h" #include "parser.h" +#include "Zend/zend_constants.h" +#include "Zend/zend_operators.h" + + struct psi_number *psi_number_init(token_t t, void *num, unsigned flags) { - struct psi_number *exp = calloc(1, sizeof(*exp)); + struct psi_number *exp = pecalloc(1, sizeof(*exp), 1); exp->flags = flags; switch (exp->type = t) { case PSI_T_INT8: exp->data.ival.i8 = *(int8_t *) num; break; + case PSI_T_DEFINED: case PSI_T_UINT8: exp->data.ival.u8 = *(uint8_t *) num; break; @@ -63,8 +69,7 @@ struct psi_number *psi_number_init(token_t t, void *num, unsigned flags) exp->data.ival.u64 = *(uint64_t *) num; break; case PSI_T_FLOAT: - exp->data.ival.dval = *(float *) num; - exp->type = PSI_T_DOUBLE; + exp->data.ival.fval = *(float *) num; break; case PSI_T_DOUBLE: exp->data.ival.dval = *(double *) num; @@ -80,7 +85,8 @@ struct psi_number *psi_number_init(token_t t, void *num, unsigned flags) case PSI_T_NUMBER: case PSI_T_NSNAME: case PSI_T_DEFINE: - exp->data.numb = strdup(num); + case PSI_T_CPP_HEADER: + exp->data.numb = zend_string_copy(num); break; case PSI_T_NAME: exp->data.dvar = num; @@ -100,7 +106,7 @@ struct psi_number *psi_number_init(token_t t, void *num, unsigned flags) struct psi_number *psi_number_copy(struct psi_number *exp) { - struct psi_number *num = calloc(1, sizeof(*num)); + struct psi_number *num = pecalloc(1, sizeof(*num), 1); *num = *exp; @@ -109,6 +115,7 @@ struct psi_number *psi_number_copy(struct psi_number *exp) } switch (num->type) { case PSI_T_INT8: + case PSI_T_DEFINED: case PSI_T_UINT8: case PSI_T_INT16: case PSI_T_UINT16: @@ -116,6 +123,7 @@ struct psi_number *psi_number_copy(struct psi_number *exp) case PSI_T_UINT32: case PSI_T_INT64: case PSI_T_UINT64: + case PSI_T_FLOAT: case PSI_T_DOUBLE: #if HAVE_LONG_DOUBLE case PSI_T_LONG_DOUBLE: @@ -128,7 +136,8 @@ struct psi_number *psi_number_copy(struct psi_number *exp) case PSI_T_NSNAME: case PSI_T_DEFINE: case PSI_T_QUOTED_CHAR: - num->data.numb = strdup(num->data.numb); + case PSI_T_CPP_HEADER: + num->data.numb = zend_string_copy(num->data.numb); break; case PSI_T_NAME: num->data.dvar = psi_decl_var_copy(num->data.dvar); @@ -151,11 +160,10 @@ void psi_number_free(struct psi_number **exp_ptr) struct psi_number *exp = *exp_ptr; *exp_ptr = NULL; - if (exp->token) { - free(exp->token); - } + psi_token_free(&exp->token); switch (exp->type) { case PSI_T_INT8: + case PSI_T_DEFINED: case PSI_T_UINT8: case PSI_T_INT16: case PSI_T_UINT16: @@ -163,6 +171,7 @@ void psi_number_free(struct psi_number **exp_ptr) case PSI_T_UINT32: case PSI_T_INT64: case PSI_T_UINT64: + case PSI_T_FLOAT: case PSI_T_DOUBLE: #if HAVE_LONG_DOUBLE case PSI_T_LONG_DOUBLE: @@ -178,7 +187,8 @@ void psi_number_free(struct psi_number **exp_ptr) case PSI_T_NUMBER: case PSI_T_DEFINE: case PSI_T_QUOTED_CHAR: - free(exp->data.numb); + case PSI_T_CPP_HEADER: + zend_string_release(exp->data.numb); break; case PSI_T_NAME: psi_decl_var_free(&exp->data.dvar); @@ -193,44 +203,100 @@ void psi_number_free(struct psi_number **exp_ptr) } } -void psi_number_dump(int fd, struct psi_number *exp) +struct psi_plist *psi_number_tokens(struct psi_number *exp, + struct psi_plist *list) { + struct psi_token *ntoken; + size_t i; + + if (!list) { + list = psi_plist_init((psi_plist_dtor) psi_token_free); + } + switch (exp->type) { - case PSI_T_INT8: - dprintf(fd, "%" PRId8, exp->data.ival.i8); - break; - case PSI_T_UINT8: - dprintf(fd, "%" PRIu8, exp->data.ival.u8); - break; - case PSI_T_INT16: - dprintf(fd, "%" PRId16, exp->data.ival.i16); - break; - case PSI_T_UINT16: - dprintf(fd, "%" PRIu16, exp->data.ival.u16); - break; - case PSI_T_INT32: - dprintf(fd, "%" PRId32, exp->data.ival.i32); - break; - case PSI_T_UINT32: - dprintf(fd, "%" PRIu32, exp->data.ival.u32); - break; - case PSI_T_INT64: - dprintf(fd, "%" PRId64, exp->data.ival.i64); - break; - case PSI_T_UINT64: - dprintf(fd, "%" PRIu64, exp->data.ival.u64); + case PSI_T_NAME: + /* decl_var */ + ntoken = psi_token_copy(exp->data.dvar->token); + + if (exp->data.dvar->pointer_level > 1 || !exp->data.dvar->array_size) { + struct psi_token *temp = ntoken; + unsigned pl = exp->data.dvar->pointer_level - !!exp->data.dvar->array_size; + + while (pl--) { + ntoken = psi_token_init(PSI_T_POINTER, "*", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + } + ntoken = temp; + } + + list = psi_plist_add(list, &ntoken); + + if (exp->data.dvar->array_size) { + char buf[0x20], *ptr; + + ntoken = psi_token_init(PSI_T_LBRACKET, "[", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + ptr = zend_print_ulong_to_buf(&buf[sizeof(buf) - 1], exp->data.dvar->array_size); + + ntoken = psi_token_init(PSI_T_NUMBER, ptr, strlen(ptr), ntoken->col+ntoken->text->len, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + } break; - case PSI_T_FLOAT: - dprintf(fd, "%" PRIfval, exp->data.ival.dval); + + case PSI_T_SIZEOF: + /* decl_type */ + ntoken = psi_token_copy(exp->token); + list = psi_plist_add(list, &ntoken); + ntoken = psi_token_init(PSI_T_LPAREN, "(", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + ntoken = psi_token_copy(exp->data.dtyp->token); + list = psi_plist_add(list, &ntoken); + ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); break; - case PSI_T_DOUBLE: - dprintf(fd, "%" PRIdval, exp->data.ival.dval); + + case PSI_T_FUNCTION: + ntoken = psi_token_copy(exp->token); + list = psi_plist_add(list, &ntoken); + ntoken = psi_token_init(PSI_T_LPAREN, "(", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + for (i = 0; i < psi_plist_count(exp->data.call->args); ++i) { + struct psi_num_exp *tmp_exp; + + if (i) { + ntoken = psi_token_init(PSI_T_COMMA, ",", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); + } + if (psi_plist_get(exp->data.call->args, i, &tmp_exp)) { + struct psi_plist *tmp = psi_num_exp_tokens(tmp_exp, NULL); + list = psi_plist_add_r(list, psi_plist_count(tmp), psi_plist_eles(tmp)); + psi_plist_top(list, &ntoken); + free(tmp); + } + } + ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file); + list = psi_plist_add(list, &ntoken); break; -#if HAVE_LONG_DOUBLE - case PSI_T_LONG_DOUBLE: - dprintf(fd, "%" PRIldval, exp->data.ival.ldval); + + case PSI_T_DEFINED: + ntoken = psi_token_init(PSI_T_DEFINED, "defined", sizeof("defined")-1, exp->token->col, exp->token->line, exp->token->file); + list = psi_plist_add(list, &ntoken); + /* no break */ + default: + assert(exp->token); + ntoken = psi_token_copy(exp->token); + list = psi_plist_add(list, &ntoken); break; -#endif + } + + return list; +} + +void psi_number_dump(int fd, struct psi_number *exp) +{ + switch (exp->type) { + case PSI_T_DEFINED: + CASE_IMPLVAL_NUM_PRINTF(dprintf, fd, exp->data.ival) case PSI_T_NULL: dprintf(fd, "NULL"); break; @@ -238,43 +304,68 @@ void psi_number_dump(int fd, struct psi_number *exp) case PSI_T_NSNAME: case PSI_T_DEFINE: case PSI_T_QUOTED_CHAR: - dprintf(fd, "%s", exp->data.numb); + case PSI_T_CPP_HEADER: + dprintf(fd, "%s", exp->data.numb->val); break; case PSI_T_FUNCTION: psi_cpp_macro_call_dump(fd, exp->data.call); break; case PSI_T_CONST: - dprintf(fd, "%s", exp->data.cnst->name); + dprintf(fd, "%s", exp->data.cnst->name->val); break; case PSI_T_ENUM: - dprintf(fd, "%s", exp->data.enm->name); + dprintf(fd, "%s", exp->data.enm->name->val); break; case PSI_T_NAME: psi_decl_var_dump(fd, exp->data.dvar); break; case PSI_T_SIZEOF: + dprintf(fd, "sizeof("); psi_decl_type_dump(fd, exp->data.dtyp, 0); + dprintf(fd, ")"); break; default: assert(0); } } -static inline bool psi_number_validate_enum(struct psi_data *data, struct psi_number *exp, - struct psi_decl_enum *enm) +static inline bool psi_number_validate_enum(struct psi_data *data, + struct psi_number *exp, struct psi_validate_scope *scope) { - size_t i = 0; - struct psi_decl_enum_item *itm; + if (scope && scope->current_enum) { + size_t i = 0; + struct psi_decl_enum_item *itm; + struct psi_decl_enum *enm; - while (psi_plist_get(enm->items, i++, &itm)) { - if (!strcmp(itm->name, exp->data.dvar->name)) { - psi_decl_var_free(&exp->data.dvar); - exp->type = PSI_T_ENUM; - exp->data.enm = itm; - return psi_number_validate(data, exp, NULL, NULL, NULL, NULL, enm); + enm = scope->current_enum; + + switch (exp->type) { + case PSI_T_NAME: + while (psi_plist_get(enm->items, i++, &itm)) { + if (zend_string_equals(itm->name, exp->data.dvar->name)) { + psi_decl_var_free(&exp->data.dvar); + exp->type = PSI_T_ENUM; + exp->data.enm = itm; + return psi_number_validate(data, exp, scope); + } + } + break; + + case PSI_T_DEFINE: + while (psi_plist_get(enm->items, i++, &itm)) { + if (zend_string_equals(itm->name, exp->data.numb)) { + zend_string_release(exp->data.numb); + exp->type = PSI_T_ENUM; + exp->data.enm = itm; + return psi_number_validate(data, exp, scope); + } + } + break; + + default: + assert(0); } } - return false; } @@ -350,13 +441,13 @@ static inline bool psi_number_validate_char(struct psi_data *data, struct psi_nu { impl_val val = {0}; unsigned lvl = 1; - token_t typ = validate_char(exp->data.numb, &val, &lvl); + token_t typ = validate_char(exp->data.numb->val, &val, &lvl); if (!typ) { return false; } - free(exp->data.numb); + zend_string_release(exp->data.numb); exp->type = typ; exp->data.ival = val; return true; @@ -372,27 +463,27 @@ static inline bool psi_number_validate_number(struct psi_data *data, struct psi_ switch (exp->flags & 0x0f00) { case PSI_NUMBER_L: default: - tmp.i64 = strtol(exp->data.numb, NULL, 0); - free(exp->data.numb); + tmp.i64 = strtol(exp->data.numb->val, NULL, 0); + zend_string_release(exp->data.numb); exp->type = PSI_T_INT64; exp->data.ival.i64 = tmp.i64; break; case PSI_NUMBER_LL: - tmp.i64 = strtoll(exp->data.numb, NULL, 0); - free(exp->data.numb); + tmp.i64 = strtoll(exp->data.numb->val, NULL, 0); + zend_string_release(exp->data.numb); exp->type = PSI_T_INT64; exp->data.ival.i64 = tmp.i64; break; case PSI_NUMBER_U: case PSI_NUMBER_UL: - tmp.u64 = strtoul(exp->data.numb, NULL, 0); - free(exp->data.numb); + tmp.u64 = strtoul(exp->data.numb->val, NULL, 0); + zend_string_release(exp->data.numb); exp->type = PSI_T_UINT64; exp->data.ival.u64 = tmp.u64; break; case PSI_NUMBER_ULL: - tmp.u64 = strtoull(exp->data.numb, NULL, 0); - free(exp->data.numb); + tmp.u64 = strtoull(exp->data.numb->val, NULL, 0); + zend_string_release(exp->data.numb); exp->type = PSI_T_UINT64; exp->data.ival.u64 = tmp.u64; break; @@ -403,24 +494,24 @@ static inline bool psi_number_validate_number(struct psi_data *data, struct psi_ switch (exp->flags & 0x0ff00) { case PSI_NUMBER_F: case PSI_NUMBER_DF: - tmp.fval = strtof(exp->data.numb, NULL); - free(exp->data.numb); + tmp.fval = strtof(exp->data.numb->val, NULL); + zend_string_release(exp->data.numb); exp->type = PSI_T_FLOAT; exp->data.ival.fval = tmp.fval; break; case PSI_NUMBER_L: case PSI_NUMBER_DL: #if HAVE_LONG_DOUBLE - tmp.ldval = strtold(exp->data.numb, NULL); - free(exp->data.numb); + tmp.ldval = strtold(exp->data.numb->val, NULL); + zend_string_release(exp->data.numb); exp->type = PSI_T_LONG_DOUBLE; exp->data.ival.ldval = tmp.ldval; break; #endif case PSI_NUMBER_DD: default: - tmp.dval = strtod(exp->data.numb, NULL); - free(exp->data.numb); + tmp.dval = strtod(exp->data.numb->val, NULL); + zend_string_release(exp->data.numb); exp->type = PSI_T_DOUBLE; exp->data.ival.dval = tmp.dval; break; @@ -431,18 +522,64 @@ static inline bool psi_number_validate_number(struct psi_data *data, struct psi_ break; } } else { - switch (is_numeric_string(exp->data.numb, strlen(exp->data.numb), (zend_long *) &tmp, (double *) &tmp, 1)) { + int type = is_numeric_string(exp->data.numb->val, exp->data.numb->len, (zend_long *) &tmp, (double *)&tmp, 0); + char *stop = NULL; + long lval; + unsigned long ulval; + + switch (type) { case IS_LONG: - free(exp->data.numb); + zend_string_release(exp->data.numb); exp->type = PSI_T_INT64; exp->data.ival.i64 = tmp.zend.lval; return true; case IS_DOUBLE: - free(exp->data.numb); + zend_string_release(exp->data.numb); exp->type = PSI_T_DOUBLE; exp->data.ival.dval = tmp.dval; return true; + + default: + + errno = 0; + + stop = exp->data.numb->val + exp->data.numb->len; + lval = strtol(exp->data.numb->val, &stop, 0); + switch (lval) { + case 0: + assert(stop == exp->data.numb->val + exp->data.numb->len); + /* no break */ + case LONG_MIN: + assert(!errno); + /* no break */ + case LONG_MAX: + if (errno == ERANGE) { + errno = 0; + + stop = exp->data.numb->val + exp->data.numb->len; + ulval = strtoul(exp->data.numb->val, &stop, 0); + switch (ulval) { + case 0: + assert(stop == exp->data.numb->val + exp->data.numb->len); + case ULONG_MAX: + assert(!errno); + default: + zend_string_release(exp->data.numb); + exp->type = PSI_T_UINT64; + exp->data.ival.u64 = ulval; + return true; + } + } + break; + default: + zend_string_release(exp->data.numb); + exp->type = PSI_T_INT64; + exp->data.ival.i64 = lval; + return true; + } + + data->error(data, exp->token, PSI_WARNING, "Not a numeric string: '%s'", exp->data.numb->val); } } data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)"); @@ -450,8 +587,7 @@ static inline bool psi_number_validate_number(struct psi_data *data, struct psi_ } bool psi_number_validate(struct psi_data *data, struct psi_number *exp, - struct psi_impl *impl, struct psi_decl *cb_decl, struct psi_let_exp *current_let, - struct psi_set_exp *current_set, struct psi_decl_enum *current_enum) + struct psi_validate_scope *scope) { size_t i = 0; struct psi_const *cnst; @@ -470,42 +606,83 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, case PSI_T_UINT32: case PSI_T_INT64: case PSI_T_UINT64: + case PSI_T_FLOAT: case PSI_T_DOUBLE: #if HAVE_LONG_DOUBLE case PSI_T_LONG_DOUBLE: #endif case PSI_T_ENUM: - case PSI_T_DEFINE: - case PSI_T_FUNCTION: + case PSI_T_DEFINED: return true; case PSI_T_NAME: - if (current_enum && psi_number_validate_enum(data, exp, current_enum)) { + if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.dvar->name)) { + exp->type = PSI_T_DEFINE; + goto define; + } + if (scope && scope->current_enum && psi_number_validate_enum(data, exp, scope)) { return true; } while (psi_plist_get(data->enums, i++, &enm)) { - if (psi_number_validate_enum(data, exp, enm)) { + struct psi_validate_scope enum_scope = *scope; + enum_scope.current_enum = enm; + if (psi_number_validate_enum(data, exp, &enum_scope)) { return true; } } if (exp->data.dvar->arg) { return true; } - if (psi_decl_var_validate(data, exp->data.dvar, impl, - impl ? impl->decl : NULL, current_let, current_set)) { - return true; - } - if (cb_decl && psi_decl_var_validate(data, exp->data.dvar, - NULL, cb_decl, NULL, NULL)) { + if (psi_decl_var_validate(data, exp->data.dvar, scope)) { return true; } data->error(data, exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression", - exp->data.dvar->name); + exp->data.dvar->name->val); + return false; + + case PSI_T_FUNCTION: + if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.call->name)) { + size_t i, argc; + struct psi_cpp_macro_call *call = exp->data.call; + + for (i = 0, argc = psi_plist_count(call->args); i < argc; ++i) { + struct psi_num_exp *arg; + + if (!psi_plist_get(call->args, i, &arg)) { + return false; + } + if (!psi_num_exp_validate(data, arg, scope)) { + return false; + } + } + return true; + } + if (psi_builtin_exists(exp->data.call->name)) { + exp->data.call->builtin = psi_builtin_get(exp->data.call->name); + return true; + } + return false; + + case PSI_T_DEFINE: + if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.numb)) { + define: ; + if (!scope->macro || !zend_string_equals(scope->macro->token->text, exp->data.numb)) { + return true; + } + /* #define foo foo */ + } + while (psi_plist_get(data->enums, i++, &enm)) { + struct psi_validate_scope enum_scope = *scope; + enum_scope.current_enum = enm; + if (psi_number_validate_enum(data, exp, &enum_scope)) { + return true; + } + } return false; case PSI_T_SIZEOF: - if (psi_decl_type_validate(data, exp->data.dtyp, 0, NULL)) { + if (psi_decl_type_validate(data, exp->data.dtyp, NULL, scope)) { struct psi_decl_type *dtyp = exp->data.dtyp; exp->type = PSI_T_UINT64; @@ -513,16 +690,49 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, psi_decl_type_free(&dtyp); return true; } else { + struct psi_decl_type *dtyp = exp->data.dtyp; + data->error(data, exp->token, PSI_WARNING, - "Cannot compute sizeof(%s) (%u)", - exp->data.dtyp->name, exp->data.dtyp->type); + "Cannot compute sizeof(%s) (%u)", dtyp->name->val, dtyp->type); + + exp->type = PSI_T_UINT8; + exp->data.ival.u8 = 0; + psi_decl_type_free(&dtyp); } break; case PSI_T_NSNAME: + { + zval *zc; + + if (exp->data.numb->val[0] == '\\') { + zc = zend_get_constant_str(&exp->data.numb->val[1], exp->data.numb->len - 1); + } else { + zc = zend_get_constant(exp->data.numb); + } + + if (zc) { + switch (Z_TYPE_P(zc)) { + case IS_LONG: + zend_string_release(exp->data.numb); + exp->type = PSI_T_INT64; + exp->data.ival.i64 = Z_LVAL_P(zc); + return true; + + case IS_DOUBLE: + zend_string_release(exp->data.numb); + exp->type = PSI_T_DOUBLE; + exp->data.ival.dval = Z_DVAL_P(zc); + return true; + + default: + assert(0); + } + } + } while (psi_plist_get(data->consts, i++, &cnst)) { - if (!strcmp(cnst->name, exp->data.numb)) { - free(exp->data.numb); + if (zend_string_equals(cnst->name, exp->data.numb)) { + zend_string_release(exp->data.numb); exp->type = PSI_T_CONST; exp->data.cnst = cnst; return true; @@ -530,7 +740,7 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, } data->error(data, exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression", - exp->data.numb); + exp->data.numb->val); return false; case PSI_T_NUMBER: @@ -539,6 +749,9 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, case PSI_T_QUOTED_CHAR: return psi_number_validate_char(data, exp); + case PSI_T_CPP_HEADER: + return true; + default: assert(0); } @@ -546,20 +759,18 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp, return false; } -#include "Zend/zend_constants.h" - static inline token_t psi_number_eval_constant(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame) { - switch (exp->data.cnst->type->type) { + token_t typ = exp->data.cnst->type ? exp->data.cnst->type->type : PSI_T_MIXED; + + switch (typ) { case PSI_T_INT: - res->i64 = zend_get_constant_str(exp->data.cnst->name, - strlen(exp->data.cnst->name))->value.lval; + res->i64 = zend_get_constant(exp->data.cnst->name)->value.lval; if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64); return PSI_T_INT64; case PSI_T_FLOAT: - res->dval = zend_get_constant_str(exp->data.cnst->name, - strlen(exp->data.cnst->name))->value.dval; + res->dval = zend_get_constant(exp->data.cnst->name)->value.dval; if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval); return PSI_T_DOUBLE; default: @@ -600,23 +811,40 @@ static inline token_t psi_number_eval_decl_var(struct psi_number *exp, } static inline token_t psi_number_eval_define(struct psi_number *exp, - impl_val *res, HashTable *defs) + impl_val *res, struct psi_cpp *cpp, struct psi_num_exp *rec_guard) { - struct psi_cpp_macro_decl *macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb)); + if (cpp) { + struct psi_cpp_macro_decl *macro; + + macro = zend_hash_find_ptr(&cpp->defs, exp->data.numb); + if (macro && macro->exp && macro->exp != rec_guard) { + return psi_num_exp_exec(macro->exp, res, NULL, cpp); + } + } - assert(!macro); + res->u8 = 0; + return PSI_T_UINT8; +} +static inline token_t psi_number_eval_function(struct psi_number *exp, + impl_val *res, struct psi_cpp *cpp, struct psi_num_exp *rec_guard) +{ + if (cpp) { + PSI_DEBUG_PRINT(cpp->parser, "psi_number_eval(PSI_T_FUNCTION): %s\n", exp->token->text->val); + } res->u8 = 0; return PSI_T_UINT8; } -token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame, HashTable *defs) +token_t psi_number_eval(struct psi_number *exp, impl_val *res, + struct psi_call_frame *frame, struct psi_cpp *cpp, struct psi_num_exp *rec_guard) { switch (exp->type) { case PSI_T_INT8: *res = exp->data.ival; if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8); return PSI_T_INT8; + case PSI_T_DEFINED: case PSI_T_UINT8: *res = exp->data.ival; if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8); @@ -646,6 +874,11 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_f if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64); return PSI_T_UINT64; + case PSI_T_FLOAT: + *res = exp->data.ival; + if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval); + return exp->type; + case PSI_T_DOUBLE: *res = exp->data.ival; if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval); @@ -664,7 +897,7 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_f return PSI_T_INT64; case PSI_T_NUMBER: - res->i64 = atol(exp->data.numb); + res->i64 = atol(exp->data.numb->val); return PSI_T_INT64; case PSI_T_CONST: @@ -674,9 +907,12 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_f return psi_number_eval_decl_var(exp, res, frame); case PSI_T_DEFINE: - return psi_number_eval_define(exp, res, defs); + return psi_number_eval_define(exp, res, cpp, rec_guard); case PSI_T_FUNCTION: + return psi_number_eval_function(exp, res, cpp, rec_guard); + + case PSI_T_CPP_HEADER: res->u8 = 0; return PSI_T_UINT8;