+ comment: ;
+ P->tok = P->cur;
+ /*!re2c
+ "\n" { NEWLINE(comment); }
+ "*" "/" { continue; }
+ [^] { goto comment; }
+ */
+
+#define PSI_DEBUG_CPP(P, msg, ...) do { \
+ if (PSI_DATA(P)->flags & PSI_DEBUG) { \
+ fprintf(stderr, "PSI> CPP %.*s line=%u level=%u skip=%u ", \
+ (int) strcspn(P->tok, "\r\n"), P->tok, \
+ P->line, P->cpp.level, P->cpp.skip); \
+ fprintf(stderr, msg, __VA_ARGS__); \
+ } \
+} while(0)
+
+ cpp: ;
+ P->tok = P->cur;
+ /*!re2c
+ [\t ] {goto cpp;}
+ "#" [\t ]* "if" { goto cpp_if; }
+ "#" [\t ]* "ifdef" { goto cpp_ifdef; }
+ "#" [\t ]* "ifndef" { goto cpp_ifndef; }
+ "#" [\t ]* "else" { goto cpp_else; }
+ "#" [\t ]* "endif" { goto cpp_endif; }
+ "#" [\t ]* "define" { goto cpp_define; }
+ "#" [\t ]* "undef" { goto cpp_undef; }
+ "#" [\t ]* "error" { goto cpp_error; }
+ [^] { goto cpp_default; }
+ */
+
+ cpp_default: ;
+ if (P->cpp.skip) {
+ goto cpp_skip;
+ } else {
+ assert(0);
+ break;
+ }
+
+ cpp_skip: ;
+ P->tok = P->cur;
+ /*!re2c
+ [\r\n] { goto cpp_skip_eol; }
+ [^] { goto cpp_skip; }
+ */
+
+ cpp_skip_eol:
+ PSI_DEBUG_PRINT(P, "PSI> CPP skip line %u\n", P->line);
+ NEWLINE(cpp);
+
+ cpp_if: ;
+ PSI_DEBUG_CPP(P, "%s\n", "");
+
+ ++P->cpp.level;
+
+ cpp_if_cont: ;
+ if (P->cpp.skip) {
+ goto cpp_skip;
+ }
+
+ P->tok = P->cur;
+
+ /*!re2c
+ [\t ]+ { goto cpp_if_cont; }
+ "!" [\t ]* "defined" [\t ]* "("? { goto cpp_ifndef_cont; }
+ "defined" [ \t]* "("? { goto cpp_ifdef_cont; }
+ NAME [\t ]* [\r\n] { goto cpp_if_name_eol; }
+ [^] { goto cpp_if_default; }
+ */
+
+ cpp_if_default: ;
+ cpp_error(P, "PSI syntax error: invalid #if");
+ continue;
+
+ cpp_if_name_eol: ;
+ if (cpp_truth(P)) {
+ NEWLINE(nextline);
+ } else {
+ P->cpp.skip = P->cpp.level;
+ NEWLINE(cpp);
+ }
+
+ cpp_ifdef: ;
+ PSI_DEBUG_CPP(P, "%s\n", "");
+
+ ++P->cpp.level;
+
+ cpp_ifdef_cont: ;
+ if (P->cpp.skip) {
+ goto cpp_skip;
+ }
+
+ P->tok = P->cur;
+
+ /*!re2c
+ [\t ]+ { goto cpp_ifdef_cont; }
+ NAME [\t ]* ")"? [\t ]* [\r\n] { goto cpp_ifdef_name_eol; }
+ [^] { goto cpp_ifdef_default; }
+ */
+
+ cpp_ifdef_default: ;
+ cpp_error(P, "PSI syntax error: invalid #ifdef");
+ continue;
+
+ cpp_ifdef_name_eol: ;
+ if (cpp_defined(P)) {
+ NEWLINE(nextline);
+ } else {
+ P->cpp.skip = P->cpp.level;
+ NEWLINE(cpp);
+ }
+
+ cpp_ifndef: ;
+ PSI_DEBUG_CPP(P, "%s\n", "");
+
+ ++P->cpp.level;
+
+ cpp_ifndef_cont:
+ if (P->cpp.skip) {
+ goto cpp_skip;
+ }
+
+ P->tok = P->cur;
+
+ /*!re2c
+ [\t ]+ { goto cpp_ifndef_cont; }
+ NAME [\t ]* ")"? [\t ]* [\r\n] { goto cpp_ifndef_name_eol; }
+ [^] { goto cpp_ifndef_default; }
+ */
+
+ cpp_ifndef_default: ;
+ cpp_error(P, "PSI syntax error: invalid #ifndef");
+ continue;
+
+ cpp_ifndef_name_eol: ;
+ if (!cpp_defined(P)) {
+ NEWLINE(nextline);
+ } else {
+ P->cpp.skip = P->cpp.level;
+ NEWLINE(cpp_skip);
+ }
+
+ cpp_else: ;
+ PSI_DEBUG_CPP(P, "%s\n", "");
+
+ P->tok = P->cur;
+
+ if (!P->cpp.level) {
+ cpp_error(P, "PSI syntax error: ignoring lone #else");
+ continue;
+ }
+ if (!P->cpp.skip) {
+ P->cpp.skip = P->cpp.level;
+ goto cpp_skip;
+ } else if (P->cpp.skip == P->cpp.level) {
+ P->cpp.skip = 0;
+ }
+ continue;
+
+ cpp_endif: ;
+ PSI_DEBUG_CPP(P, "%s\n", "");
+
+ P->tok = P->cur;
+ if (!P->cpp.level) {
+ cpp_error(P, "PSI syntax_error: ignoring lone #endif");
+ continue;
+ } else if (P->cpp.skip == P->cpp.level) {
+ P->cpp.skip = 0;
+ }
+ --P->cpp.level;
+ continue;
+
+ cpp_define: ;
+ PSI_DEBUG_CPP(P, "%s\n", "");
+
+ zval *val = NULL;
+
+ if (P->cpp.skip) {
+ goto cpp_skip;
+ }
+
+ cpp_define_cont: ;
+ P->tok = P->cur;
+
+ /*!re2c
+ [\t ]+ { goto cpp_define_cont; }
+ [\r\n] { goto cpp_define_eol; }
+ NAME { goto cpp_define_name; }
+ QUOTED_STRING { goto cpp_define_quoted_string; }
+ NUMBER { goto cpp_define_number; }
+ [^] { goto cpp_define_default; }
+ */
+
+ cpp_define_default: ;
+ cpp_error(P, "PSI syntax error: invalid #ifndef");
+ continue;
+
+ cpp_define_eol: ;
+ if (!val) {
+ cpp_error(P, "PSI syntax error: ignoring lone #define");
+ continue;
+ }
+ NEWLINE(nextline);
+
+ cpp_define_name: ;
+ if (val) {
+ if (Z_TYPE_P(val) != IS_TRUE) {
+ cpp_error(P, "PSI syntax error: invalid #define");
+ continue;
+ }
+ cpp_define_val(P, PSI_T_NAME, val);
+ } else {
+ val = cpp_define_var(P);
+ }
+ goto cpp_define_cont;
+
+ cpp_define_quoted_string: ;
+ if (!val) {
+ cpp_error(P, "PSI syntax error: invalid quoted string in #define");
+ continue;
+ } else {
+ cpp_define_val(P, PSI_T_QUOTED_STRING, val);
+ }
+ goto cpp_define_cont;
+
+ cpp_define_number: ;
+ if (!val) {
+ cpp_error(P, "PSI syntax error: invalid quoted string in #define");
+ continue;
+ } else {
+ cpp_define_val(P, PSI_T_NUMBER, val);
+ }
+ goto cpp_define_cont;
+
+ cpp_undef: ;
+ PSI_DEBUG_CPP(P, "%s\n", "");
+
+ if (P->cpp.skip) {
+ goto cpp_skip;
+ }
+
+ cpp_undef_cont: ;