+ if (conditional->in_else) {
+ errorf(&pp_token.base.source_position,
+ "#else after #else (condition started %P)",
+ conditional->source_position);
+ skip_mode = true;
+ return;
+ }
+
+ conditional->in_else = true;
+ if (!conditional->skip) {
+ skip_mode = conditional->condition;
+ }
+ conditional->source_position = pp_token.base.source_position;
+}
+
+static void parse_endif_directive(void)
+{
+ eat_pp(TP_endif);
+
+ if (!info.at_line_begin) {
+ if (!skip_mode) {
+ warningf(WARN_OTHER, &pp_token.base.source_position, "extra tokens at end of #endif");
+ }
+ eat_pp_directive();
+ }
+
+ pp_conditional_t *conditional = conditional_stack;
+ if (conditional == NULL) {
+ errorf(&pp_token.base.source_position, "#endif without prior #if");
+ return;
+ }
+
+ if (!conditional->skip) {
+ skip_mode = false;
+ }
+ pop_conditional();
+}
+
+static void parse_preprocessing_directive(void)
+{
+ in_pp_directive = true;
+ eat_pp('#');
+
+ if (skip_mode) {
+ switch (pp_token.kind) {
+ case TP_ifdef:
+ case TP_ifndef:
+ parse_ifdef_ifndef_directive();
+ break;
+ case TP_else:
+ parse_else_directive();
+ break;
+ case TP_endif:
+ parse_endif_directive();
+ break;
+ default:
+ eat_pp_directive();
+ break;
+ }
+ } else {
+ switch (pp_token.kind) {
+ case TP_define:
+ parse_define_directive();
+ break;
+ case TP_undef:
+ parse_undef_directive();
+ break;
+ case TP_ifdef:
+ case TP_ifndef:
+ parse_ifdef_ifndef_directive();
+ break;
+ case TP_else:
+ parse_else_directive();
+ break;
+ case TP_endif:
+ parse_endif_directive();
+ break;
+ case TP_include:
+ parse_include_directive();
+ break;
+ default:
+ if (info.at_line_begin) {
+ /* the nop directive "#" */
+ break;
+ }
+ errorf(&pp_token.base.source_position,
+ "invalid preprocessing directive #%t", &pp_token);
+ eat_pp_directive();
+ break;
+ }
+ }
+
+ in_pp_directive = false;
+ assert(info.at_line_begin);
+}
+
+static void prepend_include_path(const char *path)
+{
+ searchpath_entry_t *entry = OALLOCZ(&config_obstack, searchpath_entry_t);
+ entry->path = path;
+ entry->next = searchpath;
+ searchpath = entry;
+}
+
+static void setup_include_path(void)
+{
+ /* built-in paths */
+ prepend_include_path("/usr/include");
+
+ /* parse environment variable */
+ const char *cpath = getenv("CPATH");
+ if (cpath != NULL && *cpath != '\0') {
+ const char *begin = cpath;
+ const char *c;
+ do {
+ c = begin;
+ while (*c != '\0' && *c != ':')
+ ++c;
+
+ size_t len = c-begin;
+ if (len == 0) {
+ /* for gcc compatibility (Matze: I would expect that
+ * nothing happens for an empty entry...) */
+ prepend_include_path(".");
+ } else {
+ char *string = obstack_alloc(&config_obstack, len+1);
+ memcpy(string, begin, len);
+ string[len] = '\0';
+
+ prepend_include_path(string);
+ }
+
+ begin = c+1;
+ /* skip : */
+ if (*begin == ':')
+ ++begin;
+ } while(*c != '\0');
+ }
+}
+
+int pptest_main(int argc, char **argv);