#include "php_psi_stdinc.h"
+#include <libgen.h>
+
#include "cpp.h"
#include "parser.h"
return false;
}
+#if PSI_CPP_DEBUG
static int dump_def(zval *p)
{
struct psi_cpp_macro_decl *decl = Z_PTR_P(p);
}
return ZEND_HASH_APPLY_KEEP;
}
+#endif
void psi_cpp_free(struct psi_cpp **cpp_ptr)
{
if (*cpp_ptr) {
struct psi_cpp *cpp = *cpp_ptr;
+#if PSI_CPP_DEBUG
+ fprintf(stderr, "PSI: CPP decls:\n");
+ zend_hash_apply(&cpp->defs, dump_def);
+#endif
*cpp_ptr = NULL;
- if (cpp->parser->flags & PSI_DEBUG) {
- fprintf(stderr, "PSI: CPP decls:\n");
- zend_hash_apply(&cpp->defs, dump_def);
- }
zend_hash_destroy(&cpp->defs);
zend_hash_destroy(&cpp->once);
free(cpp);
cpp->parser->error(PSI_DATA(cpp->parser), old->token, PSI_WARNING,
"'%s' previously defined", old->token->text);
}
+#if PSI_CPP_DEBUG
+ if (decl->exp) {
+ fprintf(stderr, "MACRO: num_exp: ", decl->token->text);
+ } else if (decl->tokens) {
+ fprintf(stderr, "MACRO: decl : ", decl->token->text);
+ }
+ psi_cpp_macro_decl_dump(2, decl);
+ fprintf(stderr, "\n");
+#endif
zend_hash_str_update_ptr(&cpp->defs, decl->token->text, decl->token->size, decl);
}
bool psi_cpp_if(struct psi_cpp *cpp, struct psi_cpp_exp *exp)
{
- if (!psi_num_exp_validate(PSI_DATA(cpp->parser), exp->data.num, NULL, NULL, NULL, NULL, NULL)) {
+ struct psi_validate_scope scope = {0};
+
+ scope.defs = &cpp->defs;
+ if (!psi_num_exp_validate(PSI_DATA(cpp->parser), exp->data.num, &scope)) {
return false;
}
- if (!psi_long_num_exp(exp->data.num, NULL, &cpp->defs)) {
+ if (!psi_num_exp_get_long(exp->data.num, NULL, &cpp->defs)) {
return false;
}
return true;
return false;
}
-bool psi_cpp_include(struct psi_cpp *cpp, const char *file, unsigned flags)
+static inline void include_path(const struct psi_token *file, char **path)
+{
+ if (*file->text == '/') {
+ *path = file->text;
+ } else {
+ char *dir;
+ size_t len;
+
+ strncpy(*path, file->file, PATH_MAX);
+
+ dir = dirname(*path);
+ len = strlen(dir);
+
+ assert(len + file->size + 1 < PATH_MAX);
+
+ memmove(*path, dir, len);
+ (*path)[len] = '/';
+ memcpy(&(*path)[len + 1], file->text, file->size + 1);
+ }
+}
+
+bool psi_cpp_include(struct psi_cpp *cpp, const struct psi_token *file, unsigned flags)
{
bool parsed = false;
- int f_len = strlen(file);
+ int f_len = strlen(file->text);
- if (!(flags & PSI_CPP_INCLUDE_NEXT) || *file == '/') {
+ if (!(flags & PSI_CPP_INCLUDE_NEXT) || *file->text == '/') {
/* first try as is, full or relative path */
- if ((flags & PSI_CPP_INCLUDE_ONCE) && zend_hash_str_exists(&cpp->once, file, f_len)) {
+ char temp[PATH_MAX], *path = temp;
+
+ include_path(file, &path);
+
+ if ((flags & PSI_CPP_INCLUDE_ONCE) && zend_hash_str_exists(&cpp->once, path, f_len)) {
return true;
}
- if (try_include(cpp, file, &parsed)) {
+ if (try_include(cpp, path, &parsed)) {
/* found */
return parsed;
}
}
/* look through search paths */
- if (*file != '/') {
+ if (*file->text != '/') {
char path[PATH_MAX];
const char *sep;
int p_len;
sep = strchr(cpp->search, ':');
d_len = sep ? sep - cpp->search : strlen(cpp->search);
- if (PATH_MAX > (p_len = snprintf(path, PATH_MAX, "%.*s/%.*s", d_len, cpp->search, f_len, file))) {
+ if (PATH_MAX > (p_len = snprintf(path, PATH_MAX, "%.*s/%.*s", d_len, cpp->search, f_len, file->text))) {
if ((flags & PSI_CPP_INCLUDE_ONCE) && zend_hash_str_exists(&cpp->once, path, p_len)) {
return true;
}