diff --git a/lib/master.pike.in b/lib/master.pike.in index c80370510d16938f152440a4fd1ebfa6c279babb..4ee05dafd8676ae1813bb8defe7789e572a33774 100644 --- a/lib/master.pike.in +++ b/lib/master.pike.in @@ -1169,16 +1169,19 @@ program compile_string(string source, void|string filename, werror ("%*s>>> compile_string %O\n", GET_MSG_DEPTH, "", filename); INC_MSG_DEPTH(); #endif - program ret = compile(cpp(source, filename||"-", 1, handler, - compat_major, compat_minor, - (zero_type(_show_if_constant_errors)? - show_if_constant_errors: - _show_if_constant_errors)), - handler, - compat_major, - compat_minor, - p, - o); + string code = cpp(source, filename||"-", 1, handler, + compat_major, compat_minor, + (zero_type(_show_if_constant_errors)? + show_if_constant_errors: + _show_if_constant_errors)); + program ret; + if(code) + ret = compile(code, + handler, + compat_major, + compat_minor, + p, + o); if (source_cache) source_cache[ret] = source; #ifdef RECUR_COMPILE_DEBUG @@ -1970,7 +1973,10 @@ protected program low_findprog(string pname, return programs[fname] = 0; } else { - resolv_debug("low_findprog %s: returning %O\n", fname, ret); + if(!ret) + resolv_debug("low_findprog %s: dependencies failed.\n"); + else + resolv_debug("low_findprog %s: returning %O\n", fname, ret); return programs[fname]=ret; } } diff --git a/src/cpp.c b/src/cpp.c index b91ec48391f009cac1eded409ad7dc5b609e3c24..0b2f32c910ea6d8a96ccb724115ba00b9216fddc 100644 --- a/src/cpp.c +++ b/src/cpp.c @@ -131,7 +131,7 @@ struct cpp INT_TYPE compat_minor; struct pike_string *data; struct pike_string *prefix; - INT_TYPE picky_cpp, keep_comments; + INT_TYPE picky_cpp, keep_comments, dependencies_fail; }; struct define *defined_macro =0; @@ -588,6 +588,17 @@ void cpp_change_compat(struct cpp *this, int major, int minor) *! @[#if], @[#ifdef], @[defined] */ +/*! @directive #require + *! + *! If the directive evaluates to false, the source file will be + *! considered to have failed dependencies, and will not be found by + *! the resolver. In practical terms the @[cpp()] call will return + *! zero. + *! + *! @seealso + *! @[#if] + */ + /*! @directive #endif *! *! End a block opened with @[#if], @[#ifdef], @[#ifndef], @@ -2471,6 +2482,7 @@ void f_cpp(INT32 args) this.compile_errors=0; this.defines=0; this.keep_comments = 0; + this.dependencies_fail = 0; #define TTS(type) (((type) == PIKE_T_STRING && "string") \ || ((type) == PIKE_T_MAPPING && "mapping")\ @@ -2752,7 +2764,14 @@ void f_cpp(INT32 args) free_string_builder(&this.buf); throw_error_object(fast_clone_object(cpp_error_program), 0, 0, 0, "Cpp() failed\n"); - }else{ + } + else if(this.dependencies_fail) + { + free_string_builder(&this.buf); + push_int(0); + } + else + { pop_n_elems(sp - save_sp); push_string(finish_string_builder(&this.buf)); } diff --git a/src/preprocessor.h b/src/preprocessor.h index 4219e33d406f30535a46cc119bdfc26a5c62d6ed..666358fd7dd1dbea34c78c79d6700f98504b67da 100644 --- a/src/preprocessor.h +++ b/src/preprocessor.h @@ -1074,7 +1074,7 @@ static ptrdiff_t lower_cpp(struct cpp *this, int include_mode; INT_TYPE first_line = this->current_line; /* FIXME: What about this->current_file? */ - + for(pos=0; pos<len;) { ptrdiff_t old_pos = pos; @@ -2531,6 +2531,46 @@ concat_identifier: break; } } + case 'r': /* require */ + { + static const WCHAR require_[] = { 'r', 'e', 'q', 'u', 'i', 'r', 'e' }; + if(WGOBBLE2(require_)) + { + struct string_builder save, tmp; + save = this->buf; + init_string_builder(&this->buf, SHIFT); + pos += lower_cpp(this, data+pos, len-pos, + CPP_END_AT_NEWLINE | CPP_DO_IF, + auto_convert, charset); + tmp = this->buf; + this->buf = save; + string_builder_putchar(&tmp, 0); + tmp.s->len--; + + switch(tmp.s->size_shift) { + case 0: + calc_0(this, (p_wchar0 *)tmp.s->str, tmp.s->len, 0, 0); + break; + case 1: + calc_1(this, (p_wchar1 *)tmp.s->str, tmp.s->len, 0, 0); + break; + case 2: + calc_2(this, (p_wchar2 *)tmp.s->str, tmp.s->len, 0, 0); + break; +#ifdef PIKE_DEBUG + default: + Pike_fatal("cpp(): Bad shift: %d\n", tmp.s->size_shift); + break; +#endif + } + if(SAFE_IS_ZERO(Pike_sp-1)) this->dependencies_fail=1; + pop_stack(); + free_string_builder(&tmp); + if(this->dependencies_fail) return pos; + break; + } + goto unknown_preprocessor_directive; + } case 'w': /* warning */ { static const WCHAR warning_[] = { 'w', 'a', 'r', 'n', 'i', 'n', 'g' };