|
|
|
|
|
|
|
|
|
#pike __REAL_VERSION__ |
|
|
#pragma dynamic_dot |
|
|
|
|
|
|
|
|
|
|
#define PIKE_AUTORELOAD |
#define GETCWD_CACHE |
|
|
|
#undef PIKE_MODULE_RELOC |
|
#ifndef PIKE_WARNINGS |
#define PIKE_WARNINGS 1 |
#endif /* PIKE_WARNINGS */ |
|
|
|
|
|
#if !defined(BT_MAX_STRING_LEN) || (BT_MAX_STRING_LEN <= 0) |
#undef BT_MAX_STRING_LEN |
#define BT_MAX_STRING_LEN 200 |
#endif /* !defined(BT_MAX_STRING_LEN) || (BT_MAX_STRING_LEN <= 0) */ |
constant bt_max_string_len = BT_MAX_STRING_LEN; |
|
|
|
|
|
|
|
#ifndef OUT_OF_DATE_WARNING |
#define OUT_OF_DATE_WARNING 1 |
#endif /* OUT_OF_DATE_WARNING */ |
constant out_of_date_warning = OUT_OF_DATE_WARNING; |
|
|
|
|
|
#if defined(__NT__) |
#define PATH_SEPARATOR ";" |
#else |
#define PATH_SEPARATOR ":" |
#endif |
|
#define UPDIR "../" |
|
|
|
|
|
|
|
int want_warnings = PIKE_WARNINGS; |
|
|
|
|
|
|
|
int compat_major=-1; |
|
|
|
|
|
|
|
int compat_minor=-1; |
|
|
|
|
|
int show_if_constant_errors = 0; |
|
protected int _is_pike_master = 0; |
|
|
|
|
|
|
|
|
int `is_pike_master() |
{ |
return _is_pike_master; |
} |
void `is_pike_master=(int one) |
{ |
_is_pike_master = one; |
if (one) { |
add_constants(); |
} |
} |
|
|
mapping(string:object) fs_map = ([]); |
object root_fs; |
|
|
|
private object(_static_modules.Builtin) Builtin = _static_modules.Builtin(); |
private constant Files = _static_modules._Stdio; |
|
#define Stat Files.Stat |
#define capitalize(X) (upper_case((X)[..0])+(X)[1..]) |
#define trim(X) (Builtin.string_trim (X)) |
|
private function write = Files()->_stdout->write; |
private function werror = Files()->_stderr->write; |
|
|
constant pike_cycle_depth = 0; |
|
|
|
|
|
#if defined (RESOLV_DEBUG) || defined (RECUR_COMPILE_DEBUG) |
|
#if constant (thread_local) |
protected object _msg_depth = thread_local(); |
|
#define GET_MSG_DEPTH (_msg_depth && _msg_depth->get()) |
#define INC_MSG_DEPTH() (_msg_depth && _msg_depth->set (_msg_depth->get() + 1)) |
#define DEC_MSG_DEPTH() (_msg_depth && _msg_depth->set (_msg_depth->get() - 1)) |
#else |
protected int _msg_depth; |
#define GET_MSG_DEPTH _msg_depth |
#define INC_MSG_DEPTH() (++_msg_depth) |
#define DEC_MSG_DEPTH() (--_msg_depth) |
#endif |
|
#endif |
|
#ifdef RESOLV_DEBUG |
|
#define GET_RESOLV_MSG_DEPTH GET_MSG_DEPTH |
#define INC_RESOLV_MSG_DEPTH() INC_MSG_DEPTH() |
#define DEC_RESOLV_MSG_DEPTH() DEC_MSG_DEPTH() |
|
void resolv_debug (sprintf_format fmt, sprintf_args... args) |
{ |
string pad = " " * GET_RESOLV_MSG_DEPTH; |
if (sizeof (args)) fmt = sprintf (fmt, @args); |
if (fmt[-1] == '\n') |
fmt = pad + replace (fmt[..<1], "\n", "\n" + pad) + "\n"; |
else |
fmt = pad + replace (fmt, "\n", "\n" + pad); |
function _werror = werror; |
if (!_werror || (_werror == locale_werror && !locale_werror_cache)) |
_werror = Files()->_stderr->write; |
_werror (fmt); |
} |
|
#else // !RESOLV_DEBUG |
#define INC_RESOLV_MSG_DEPTH() 0 |
#define DEC_RESOLV_MSG_DEPTH() 0 |
#define resolv_debug(X...) do {} while (0) |
#endif // !RESOLV_DEBUG |
|
constant no_value = (<>); |
constant NoValue = typeof (no_value); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected class Pike_7_8_master |
{ |
extern array(string) pike_include_path; |
extern array(string) pike_module_path; |
extern array(string) pike_program_path; |
#ifdef GETCWD_CACHE |
extern string current_path; |
int cd(string s); |
string getcwd(); |
#endif |
string combine_path_with_cwd(string path); |
#ifdef FILE_STAT_CACHE |
extern int invalidate_time; |
extern mapping(string:multiset(string)) dir_cache; |
#endif |
|
string|mapping(string:string) getenv(string|void s); |
void putenv(string|void varname, string|void value); |
|
void add_include_path(string tmp); |
void remove_include_path(string tmp); |
void add_module_path(string tmp); |
void remove_module_path(string tmp); |
void add_program_path(string tmp); |
void remove_program_path(string tmp); |
mapping(string:program|NoValue) programs; |
|
extern mapping(program:object) objects; |
object cast_to_object(string oname, string current_file); |
class dirnode {}; |
extern string _master_file_name; |
void _main(array(string) orig_argv, array(string) env); |
extern mixed inhibit_compile_errors; |
void set_inhibit_compile_errors(mixed f); |
string trim_file_name(string s); |
void compile_error(string file,int line,string err); |
string handle_include(string f, string current_file, int local_include); |
|
int is_absolute_path(string p); |
array(string) explode_path(string p); |
string dirname(string x); |
string basename(string x); |
object low_cast_to_object(string oname, string current_file); |
extern int want_warnings; |
program compile_string(string data, void|string name); |
program compile_file(string file); |
|
constant master_efuns = ({}); |
class joinnode {}; |
extern mapping(string:mixed) fc; |
extern string _pike_file_name; |
void compile_warning(string file,int line,string err); |
string read_include(string f); |
|
class Codec {}; |
|
constant bt_max_string_len = 1; |
constant out_of_date_warning = 1; |
#ifdef PIKE_FAKEROOT |
extern object o; |
string fakeroot(string s); |
#endif |
#ifdef PIKE_AUTORELOAD |
extern int autoreload_on; |
extern int newest; |
extern mapping(string:int) load_time; |
#endif |
string master_read_file(); |
string normalize_path(string X); |
array(string) query_precompiled_names(string fname); |
program cast_to_program(string pname, string current_file, |
object|void handler); |
void handle_error(array(mixed)|object trace); |
program handle_inherit(string pname, string current_file, object|void handler); |
mixed handle_import(string what, string|void current_file, object|void handler); |
mixed resolv_base(string identifier, string|void current_file); |
|
mixed get_inhibit_compile_errors(); |
string decode_charset(string data, string charset); |
|
string describe_object(object o); |
string describe_backtrace(array(mixed) trace, void|int linewidth); |
string describe_error(mixed trace); |
|
|
|
#ifdef PIKE_MODULE_RELOC |
string relocate_module(string s); |
string unrelocate_module(string s); |
#endif |
extern int compat_major; |
extern int compat_minor; |
Stat master_file_stat(string x); |
object low_cast_to_object(string oname, string current_file, |
object|void current_handler); |
object findmodule(string fullname, object|void handler); |
extern multiset no_resolv; |
extern string ver; |
mapping get_default_module(); |
void runtime_warning(string where, string what, mixed ... args); |
protected int clipped; |
protected int canclip; |
protected string stupid_describe(mixed m, int maxlen); |
protected string stupid_describe_comma_list(array x, int maxlen); |
class Describer {}; |
string describe_function(function f); |
class CompatResolver {}; |
int(0..1) asyncp(); |
class Version {}; |
extern object currentversion; |
extern mapping(object:object) compat_handler_cache; |
object get_compilation_handler(int major, int minor); |
|
|
|
#ifdef RESOLV_DEBUG |
void resolv_debug (sprintf_format fmt, sprintf_args... args); |
#endif |
void error(sprintf_format f, sprintf_args ... args); |
constant no_value = (<>); |
constant NoValue = typeof (no_value); |
string programs_reverse_lookup (program prog); |
program objects_reverse_lookup (object obj); |
string fc_reverse_lookup (object obj); |
void unregister(program p); |
program low_cast_to_program(string pname, |
string current_file, |
object|void handler, |
void|int mkobj); |
extern string include_prefix; |
extern mapping(string:string) predefines; |
|
void add_predefine (string name, string value); |
void remove_predefine (string name); |
mapping get_predefines(); |
#if constant(thread_create) |
object backend_thread(); |
#endif |
function(string:string) set_trim_file_name_callback(function(string:string) s); |
int compile_exception (array|object trace); |
string program_path_to_name ( string path, |
void|string module_prefix, |
void|string module_suffix, |
void|string object_suffix ); |
string describe_module(object|program mod, array(object)|void ret_obj); |
string describe_program(program|function p); |
class Encoder {}; |
class Decoder {}; |
extern mapping(string:Codec) codecs; |
Codec get_codec(string|void fname, int|void mkobj); |
|
|
|
extern mixed encoded; |
string|array nameof (mixed what, void|array(object) module_object); |
mixed encode_object(object x); |
|
extern string fname; |
extern int mkobj; |
object __register_new_program(program p); |
object objectof (string|array what); |
function functionof (string|array what); |
program programof (string|array what); |
void decode_object(object o, mixed data); |
|
__deprecated__ string _sprintf(int t); |
|
|
|
extern int show_if_constant_errors; |
extern mapping(string:string) initial_predefines; |
extern joinnode root_module; |
extern mapping(object:joinnode) handler_root_modules; |
extern array(string) system_module_path; |
extern CompatResolver fallback_resolver; |
joinnode get_root_module(object|void current_handler); |
local protected object Pike_7_8_compat_handler; |
local mixed resolv_or_error(string identifier, string|void current_file, |
void|object current_handler) |
{ |
if (!Pike_7_8_compat_handler) { |
Pike_7_8_compat_handler = global::get_compilation_handler(7, 8); |
} |
return Pike_7_8_compat_handler->resolv_or_error(identifier, current_file, |
current_handler); |
} |
local mixed resolv(string identifier, string|void current_file) |
{ |
if (!Pike_7_8_compat_handler) { |
Pike_7_8_compat_handler = global::get_compilation_handler(7, 8); |
} |
return Pike_7_8_compat_handler->resolv(identifier, current_file); |
} |
array get_backtrace (object|array err); |
object get_compat_master(int major, int minor) |
{ |
|
if (major < 8) |
return this::this; |
return get_compat_master(major, minor); |
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
protected class Pike_8_0_master |
{ |
inherit Pike_7_8_master; |
|
local protected object Pike_8_0_compat_handler; |
local mixed resolv_or_error(string identifier, string|void current_file, |
void|object current_handler) |
{ |
if (!Pike_8_0_compat_handler) { |
Pike_8_0_compat_handler = global::get_compilation_handler(8, 0); |
} |
return Pike_8_0_compat_handler->resolv_or_error(identifier, current_file, |
current_handler); |
} |
local mixed resolv(string identifier, string|void current_file) |
{ |
if (!Pike_8_0_compat_handler) { |
Pike_8_0_compat_handler = global::get_compilation_handler(8, 0); |
} |
return Pike_8_0_compat_handler->resolv(identifier, current_file); |
} |
object get_compat_master(int major, int minor) |
{ |
if (major < 8) |
return Pike_7_8_master::get_compat_master(major, minor); |
|
if ((major == 8) && (minor < 1)) |
return this::this; |
return get_compat_master(major, minor); |
} |
} |
|
|
|
|
|
|
|
|
protected inherit Pike_8_0_master; |
|
|
|
|
|
void error(sprintf_format f, sprintf_args ... args) { |
if (sizeof(args)) f = sprintf(f, @args); |
throw( ({ f, backtrace()[..<1] }) ); |
} |
|
|
#ifdef PIKE_FAKEROOT |
object o; |
string fakeroot(string s) |
{ |
string tmp1=combine_path_with_cwd(s); |
#ifdef PIKE_FAKEROOT_OMIT |
foreach(PIKE_FAKEROOT_OMIT/PATH_SEPARATOR, string x) |
if(glob(x,tmp1)) |
return s; |
#endif |
return PIKE_FAKEROOT+tmp1; |
} |
#else |
#define fakeroot(X) X |
#endif // PIKE_FAKEROOT |
|
#ifdef PIKE_MODULE_RELOC |
string relocate_module(string s) |
{ |
if(s == "/${PIKE_MODULE_PATH}" || has_prefix (s, "/${PIKE_MODULE_PATH}/")) { |
string tmp = s[21..]; |
foreach(pike_module_path, string path) { |
string s2 = fakeroot(sizeof(tmp)? combine_path(path, tmp) : path); |
if(master_file_stat(s2)) |
return s2; |
} |
} |
return fakeroot(s); |
} |
|
string unrelocate_module(string s) |
{ |
if(s == "/${PIKE_MODULE_PATH}" || has_prefix (s, "/${PIKE_MODULE_PATH}/")) |
return s; |
|
foreach(pike_module_path, string path) |
if(s == path) |
return "/${PIKE_MODULE_PATH}"; |
else { |
path = combine_path(path, ""); |
if(has_prefix (s, path)) |
return "/${PIKE_MODULE_PATH}/"+s[sizeof(path)..]; |
} |
|
|
foreach(pike_module_path, string path) { |
path = combine_path(path, UPDIR, ""); |
if(has_prefix (s, path)) |
return "/${PIKE_MODULE_PATH}/"+UPDIR+s[sizeof(path)..]; |
} |
|
return s; |
} |
|
#ifdef fakeroot |
#undef fakeroot |
#endif |
#define fakeroot relocate_module |
#endif // PIKE_MODULE_RELOC |
|
|
|
|
|
|
int is_absolute_path(string p) |
{ |
#if defined(__NT__) |
p=replace(p,"\\","/"); |
if(sscanf(p,"%[a-zA-Z]:%*c",string s)==2 && sizeof(s)==1) |
return 1; |
#define IS_ABSOLUTE_PATH is_absolute_path |
#else |
#define IS_ABSOLUTE_PATH(X) has_prefix((X),"/") |
#endif |
return has_prefix(p,"/"); |
} |
|
#if defined(__NT__) |
#define EXPLODE_PATH(X) (replace((X),"\\","/")/"/") |
#else |
#define EXPLODE_PATH(X) ((X)/"/") |
#endif |
|
|
|
|
|
|
|
|
array(string) explode_path(string p) |
{ |
array(string) r = EXPLODE_PATH(p); |
if(r[0] == "" && sizeof(p)) |
r[0] = "/"; |
return r; |
} |
|
#if !constant(dirname) |
string dirname(string x) |
{ |
if(x=="") return ""; |
array(string) tmp = EXPLODE_PATH(x); |
if (x[0] == '/' && sizeof(tmp) < 3) return "/"; |
return tmp[..<1]*"/"; |
} |
#else /* dirname */ |
constant dirname = predef::dirname; |
#endif /* !dirname */ |
|
#if !constant(basename) |
string basename(string x) |
{ |
array(string) tmp=EXPLODE_PATH(x); |
return tmp[-1]; |
#define BASENAME(X) (EXPLODE_PATH(X)[-1]) |
} |
#else /* basename */ |
constant basename = predef::basename; |
#define BASENAME(X) basename(X) |
#endif /* !basename */ |
|
#ifdef PIKE_AUTORELOAD |
|
int autoreload_on; |
int newest; |
|
#define AUTORELOAD_BEGIN() \ |
int ___newest=newest; \ |
newest=0 |
|
#define AUTORELOAD_CHECK_FILE(X) do { \ |
if(autoreload_on) \ |
if(Stat s=master_file_stat(X)) \ |
if(s->mtime>newest) newest=[int]s->mtime; \ |
} while(0) |
|
#define AUTORELOAD_CHECK_PRECOMPILED_FILE(X) do { \ |
if(autoreload_on) { \ |
int mtime = get_precompiled_mtime (X); \ |
if (mtime >= 0 && mtime > newest) \ |
if(s->mtime>newest) newest=[int]s->mtime; \ |
} \ |
} while(0) |
|
#define AUTORELOAD_FINISH(VAR, CACHE, FILE) \ |
if(autoreload_on) { \ |
mixed val = CACHE[FILE]; \ |
if(!undefinedp (val) && val != no_value && \ |
newest <= load_time[FILE]) { \ |
VAR = val; \ |
} \ |
} \ |
load_time[FILE] = newest; \ |
if(___newest > newest) newest=___newest; |
|
|
mapping(string:int) load_time=([]); |
#else |
|
#define AUTORELOAD_CHECK_FILE(X) |
#define AUTORELOAD_BEGIN() |
#define AUTORELOAD_FINISH(VAR,CACHE,FILE) |
|
#endif // PIKE_AUTORELOAD |
|
|
protected class CompilerEnvironment |
{ |
|
inherit predef::CompilerEnvironment : OrigCompilerEnvironment; |
|
|
mixed resolv(string identifier, string filename, |
object|void handler, object|void compat_handler) |
{ |
return master()->resolv(identifier, filename, |
handler, compat_handler); |
} |
|
|
program handle_inherit(string inh, string current_file, |
object|void handler, object|void compat_handler) |
{ |
return master()->handle_inherit(inh, current_file, |
handler, compat_handler); |
} |
|
|
program handle_import(string module, string current_file, |
object|void handler, object|void compat_handler) |
{ |
return master()->handle_import(module, current_file, |
handler, compat_handler); |
} |
|
object get_compilation_handler(int major, int minor) |
{ |
return master()->get_compilation_handler(major, minor); |
} |
|
#if constant(_static_modules.Builtin.__HAVE_COMPILER_NO_HANDLERS__) |
|
class PikeCompiler |
{ |
|
inherit ::this_program; |
|
|
object handler; |
object compat_handler; |
|
|
protected mixed apply_handler(string fun, mixed ... args) |
{ |
function f; |
foreach(({ handler, compat_handler }), object o) { |
if (objectp(o) && functionp(f = predef::`->(o, fun))) { |
return f(@args); |
} |
} |
return CompilerEnvironment::`->(fun)(@args); |
} |
|
|
void report(SeverityLevel severity, string filename, int linenumber, |
string subsystem, string message, |
mixed ... extra_args) |
{ |
foreach(({ handler, compat_handler }), object o) { |
if (!objectp(o)) continue; |
if (functionp(o->report)) { |
o->report(severity, filename, linenumber, |
subsystem, message, @extra_args); |
return; |
} |
if (severity < WARNING) continue; |
if (severity >= ERROR) { |
if (functionp(o->compile_error)) { |
o->compile_error(filename, linenumber, |
sizeof(extra_args)? |
sprintf(message, @extra_args): |
message); |
return; |
} |
} else { |
if (functionp(o->compile_warning)) { |
o->compile_warning(filename, linenumber, |
sizeof(extra_args)? |
sprintf(message, @extra_args): |
message); |
return; |
} |
} |
} |
CompilerEnvironment::report(severity, filename, linenumber, |
subsystem, message, @extra_args); |
} |
|
|
mixed resolv(string identifier) |
{ |
return apply_handler(__func__, identifier, current_file, |
handler, compat_handler); |
} |
|
|
mapping(string:mixed)|object get_default_module() |
{ |
|
|
|
return apply_handler(__func__); |
} |
|
|
object get_compilation_handler(int major, int minor) |
{ |
return apply_handler(__func__, major, minor); |
} |
|
|
program handle_inherit(string inh) |
{ |
return apply_handler(__func__, inh, current_file, |
handler, compat_handler); |
} |
|
|
program handle_import(string module) |
{ |
return apply_handler(__func__, module, current_file, |
handler, compat_handler); |
} |
|
|
void change_compiler_compatibility(int major, int minor) |
{ |
if ((major == compat_major) && (minor == compat_minor)) { |
|
return; |
} |
if (((major == -1) && (minor == -1)) || |
((major == __REAL_MAJOR__) && (minor == __REAL_MINOR__))) { |
if ((compat_major == __REAL_MAJOR__) && |
(compat_minor == __REAL_MINOR__)) { |
|
return; |
} |
compat_handler = 0; |
} else { |
compat_handler = get_compilation_handler(major, minor); |
} |
|
::change_compiler_compatibility(major, minor); |
} |
|
|
protected void create(string|void source, |
object|void handler, |
int|void major, int|void minor, |
program|void target, object|void placeholder) |
{ |
this::handler = handler; |
::create(source, UNDEFINED, major, minor, target, placeholder); |
} |
} |
#endif /* _static_modules.Builtin.__HAVE_COMPILER_NO_HANDLERS__ */ |
|
|
int compile_exception(mixed err) |
{ |
function(mixed:int) fun = master()->compile_exception; |
return fun && fun(err); |
} |
|
|
string format_exception(mixed err) |
{ |
return 0; |
} |
|
|
class CPP |
{ |
|
inherit ::this_program; |
|
#if constant(_static_modules.Builtin.__HAVE_CPP_NO_HANDLERS__) |
|
object handler; |
object compat_handler; |
#endif |
|
|
protected mixed apply_handler(string fun, mixed ... args) |
{ |
function f; |
foreach(({ handler, compat_handler }), object o) { |
if (objectp(o) && functionp(f = predef::`->(o, fun))) { |
return f(@args); |
} |
} |
return CompilerEnvironment::`->(fun)(@args); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void report(SeverityLevel severity, string filename, int linenumber, |
string subsystem, |
sprintf_format message, sprintf_args ... extra_args) |
{ |
foreach(({ handler, compat_handler }), object o) { |
if (!objectp(o)) continue; |
if (functionp(o->report)) { |
o->report(severity, filename, linenumber, |
subsystem, message, @extra_args); |
return; |
} |
if (severity < WARNING) continue; |
if (severity >= ERROR) { |
if (functionp(o->compile_error)) { |
o->compile_error(filename, linenumber, |
sizeof(extra_args)? |
sprintf(message, @extra_args): |
message); |
return; |
} |
} else { |
if (functionp(o->compile_warning)) { |
o->compile_warning(filename, linenumber, |
sizeof(extra_args)? |
sprintf(message, @extra_args): |
message); |
return; |
} |
} |
} |
::report(severity, filename, linenumber, subsystem, message, @extra_args); |
} |
|
|
object get_compilation_handler(int major, int minor) |
{ |
return apply_handler(__func__, major, minor); |
} |
|
#if constant(_static_modules.Builtin.__HAVE_CPP_NO_HANDLERS__) |
|
mapping(string:string|function|object) get_predefines() |
{ |
return apply_handler(__func__); |
} |
|
|
mixed resolv(string sym) |
{ |
return apply_handler(__func__, sym, current_file, |
handler, compat_handler); |
} |
|
|
string handle_include(string header_file, string current_file, |
int(0..1) is_local_ref) |
{ |
return apply_handler(__func__, header_file, current_file, |
is_local_ref); |
} |
|
|
string read_include(string filename) |
{ |
return apply_handler(__func__, filename); |
} |
|
string decode_charset(string data, string charset) |
{ |
return apply_handler(__func__, data, charset); |
} |
#endif |
|
string evaluate_define(string def, string|void arguments) |
{ |
return apply_handler(__func__, def, arguments); |
} |
|
|
void change_cpp_compatibility(int major, int minor) |
{ |
if ((compat_major == major) && (compat_minor == minor)) { |
return; |
} |
|
if (((major == __REAL_MAJOR__) && (minor == __REAL_MINOR__)) || |
(major < 0)) { |
compat_handler = UNDEFINED; |
} else { |
compat_handler = get_compilation_handler(major, minor); |
} |
::change_cpp_compatibility(major, minor); |
} |
|
|
int compile_exception(mixed err) |
{ |
return apply_handler(__func__, err); |
} |
|
|
string format_exception(mixed err) |
{ |
string ret = apply_handler(__func__, err); |
if (ret) return ret; |
if (compile_exception(err)) { |
return ""; |
} |
return 0; |
} |
|
#if constant(_static_modules.Builtin.__HAVE_CPP_NO_HANDLERS__) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected void create(mapping(string:mixed) options) |
{ |
|
handler = options->handler; |
compat_handler = UNDEFINED; |
::create(options); |
} |
|
protected variant void create(string|void current_file, |
int|string|void charset, object|void handler, |
void|int compat_major, void|int compat_minor, |
void|int picky_cpp) |
{ |
mapping(string:mixed) options = ([]); |
#define CPP_OPT(X) do { if (X) { options->X = X; } } while(0) |
CPP_OPT(current_file); |
CPP_OPT(charset); |
CPP_OPT(handler); |
CPP_OPT(compat_major); |
CPP_OPT(compat_minor); |
CPP_OPT(picky_cpp); |
#undef CPP_OPT |
local::create(options); |
} |
#endif |
} |
|
#if constant(_static_modules.Builtin.__HAVE_COMPILER_NO_HANDLERS__) |
|
program compile(string source, object|void handler, |
int|void major, int|void minor, |
program|void target, object|void placeholder) |
{ |
return PikeCompiler(source, handler, major, minor, target, placeholder)-> |
compile(); |
} |
#endif /* _static_modules.Builtin.__HAVE_COMPILER_NO_HANDLERS__ */ |
} |
|
protected CompilerEnvironment DefaultCompilerEnvironment = |
CompilerEnvironment(); |
|
#if constant(_static_modules.Builtin.__HAVE_COMPILER_NO_HANDLERS__) |
|
protected program compile(string source, object|void handler, |
int|void major, int|void minor, |
program|void target, object|void placeholder) |
{ |
return DefaultCompilerEnvironment->compile(source, handler, |
major, minor, |
target, placeholder); |
} |
#endif /* _static_modules.Builtin.__HAVE_COMPILER_NO_HANDLERS__ */ |
|
|
|
|
|
|
|
|
|
|
|
|
protected object get_active_compilation_handler() |
{ |
CompilerEnvironment.PikeCompiler c = get_active_compiler(); |
return c && c->compat_handler; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
protected object get_active_error_handler() |
{ |
CompilerEnvironment.PikeCompiler c = get_active_compiler(); |
return c && c->handler; |
} |
|
|
protected string cpp(string data, mapping|string|void current_file, |
int|string|void charset, object|void handler, |
void|int compat_major, void|int compat_minor, |
void|int picky_cpp) |
{ |
CompilerEnvironment.CPP cpp_obj = |
DefaultCompilerEnvironment->CPP(current_file, charset, |
handler || UNDEFINED, |
compat_major, compat_minor, |
picky_cpp); |
|
cpp_obj->init_pike_cpp(); |
return cpp_obj->high_cpp(data); |
} |
|
|
|
|
|
|
|
|
|
program compile_string(string source, void|string filename, |
object|void handler, |
void|program p, |
void|object o, |
void|int _show_if_constant_errors) |
{ |
#ifdef RECUR_COMPILE_DEBUG |
werror ("%*s>>> compile_string %O\n", GET_MSG_DEPTH, "", filename); |
INC_MSG_DEPTH(); |
#endif |
string code = cpp(source, filename||"-", 1, handler, |
compat_major, compat_minor, |
(undefinedp(_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 |
DEC_MSG_DEPTH(); |
werror ("%*s<<< compile_string %O\n", GET_MSG_DEPTH, "", filename); |
#endif |
return ret; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string master_read_file(string file) |
{ |
string x = find_handler_for_path(file); |
if(x) |
{ |
object h = fs_map[x]; |
file = file[sizeof(x)+1..]; |
|
if(h = h->open(fakeroot(file),"r") ) |
{ |
string q = ([function(void : string)]h->read)(); |
return q; |
} |
|
} |
|
object o=Files()->Fd(); |
if( ([function(string, string : int)]o->open)(fakeroot(file),"r") ) |
return ([function(void : string)]o->read)(); |
return 0; |
} |
|
#ifdef GETCWD_CACHE |
protected string current_path; |
int cd(string s) |
{ |
current_path=0; |
return predef::cd(s); |
} |
|
string getcwd() |
{ |
return current_path || (current_path=predef::getcwd()); |
} |
#endif // GETCWD_CACHE |
|
constant high_master_get_dir = predef::get_dir; |
|
string combine_path_with_cwd(string ... paths) |
{ |
#ifdef PIKE_MODULE_RELOC |
|
if (has_prefix(paths[0], "/${PIKE_MODULE_PATH}/"+UPDIR)) |
return "/${PIKE_MODULE_PATH}/"+combine_path(paths[0][21..],@paths[1..]-({""})); |
#endif |
return combine_path(IS_ABSOLUTE_PATH(paths[0])?"":getcwd(),@paths-({""})); |
} |
|
#ifdef FILE_STAT_CACHE |
|
#define FILE_STAT_CACHE_TIME 20 |
|
int invalidate_time; |
mapping(string:multiset(string)) dir_cache = ([]); |
|
|
array(string) master_get_dir(string|void x) |
{ |
string y = find_handler_for_path(file); |
if(y) |
{ |
object h = fs_map[y]; |
x = x[sizeof(y)+1..]; |
return h->get_dir(x); |
} |
else return predef::get_dir(x); |
} |
|
Stat master_file_stat(string x) |
{ |
object y = find_handler_for_path(file); |
|
string dir = combine_path_with_cwd(x); |
string file = BASENAME(dir); |
dir = dirname(dir); |
|
if(time() > invalidate_time) |
{ |
dir_cache = ([]); |
invalidate_time = time()+FILE_STAT_CACHE_TIME; |
} |
|
multiset(string) d = dir_cache[dir]; |
if( undefinedp(d) ) |
{ |
array(string) tmp = master_get_dir(dir); |
if(tmp) |
{ |
#ifdef __NT__ |
tmp = map(tmp, lower_case); |
#endif |
d = dir_cache[dir] = (multiset)tmp; |
} |
else |
dir_cache[dir]=0; |
} |
|
#ifdef __NT__ |
file = lower_case(file); |
#endif |
if(d && !d[file]) return 0; |
|
|
if(y) |
{ |
object h = fs_map[y]; |
x = x[sizeof(y)+1..]; |
return h->stat(x); |
} |
else return predef::file_stat(x); |
} |
#else |
|
|
|
Stat master_file_stat(string file) |
{ |
string x = find_handler_for_path(file); |
if(x) |
{ |
object h = fs_map[x]; |
file = file[sizeof(x)+1..]; |
|
return h->stat(file); |
} |
else return predef::file_stat(file); |
} |
|
array master_get_dir(string file) |
{ |
string x = find_handler_for_path(file); |
if(x) |
{ |
object h = fs_map[x]; |
file = file[sizeof(x)+1..]; |
|
return h->get_dir(file); |
} |
else return predef::get_dir(file); |
} |
|
#endif // FILE_STAT_CACHE |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mixed add_filesystem_handler(string mountpoint, object filesystem) |
{ |
mixed rv = fs_map[mountpoint]; |
fs_map[mountpoint] = filesystem; |
return rv; |
} |
|
|
|
|
|
|
string find_handler_for_path(string file) |
{ |
|
|
foreach(reverse(sort(indices(fs_map))); int x; string path) |
{ |
string p = path; |
if(p[-1] != '/') p+="/"; |
if(file[-1] != '/') file+="/"; |
if(has_prefix(file, p)) |
return path; |
} |
|
return 0; |
} |
|
protected mapping(string:string) environment; |
|
#ifdef __NT__ |
protected void set_lc_env (mapping(string:string) env) |
{ |
environment = ([]); |
foreach (env; string var; string val) |
environment[lower_case (var)] = val; |
} |
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mapping(string:string) getenv (void|int force_update) |
{ |
mapping(string:string) res; |
|
if (force_update > 0) { |
res = Builtin._getenv(); |
#ifdef __NT__ |
set_lc_env (res); |
#else |
environment = res + ([]); |
#endif |
} |
else { |
#ifdef __NT__ |
|
|
res = Builtin._getenv(); |
if (!environment) set_lc_env (res); |
#else |
if (!environment) environment = Builtin._getenv(); |
res = environment + ([]); |
#endif |
if (force_update < 0) return environment; |
} |
|
return res; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
variant string getenv (string varname, void|int force_update) |
{ |
if (!environment || force_update) { |
#ifdef __NT__ |
set_lc_env (Builtin._getenv()); |
#else |
environment = Builtin._getenv(); |
#endif |
} |
|
#ifdef __NT__ |
varname = lower_case(varname); |
#endif |
|
return environment[varname]; |
} |
|
void putenv (string varname, void|string value) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
Builtin._putenv (varname, value); |
if (environment) { |
#ifdef __NT__ |
varname = lower_case (varname); |
#endif |
if (value) environment[varname] = value; |
else m_delete (environment, varname); |
} |
} |
|
|
|
|
|
|
|
|
|
|
|
program compile_file(string filename, |
object|void handler, |
void|program p, |
void|object o) |
{ |
AUTORELOAD_CHECK_FILE(filename); |
string code = cpp(master_read_file(filename), |
filename, |
1, |
handler, |
compat_major, |
compat_minor); |
if (!code) { |
error("Required feature missing.\n"); |
} |
return compile(code, |
handler, |
compat_major, |
compat_minor, |
p, |
o); |
} |
|
|
|
|
string normalize_path( string path ) |
{ |
#ifndef __NT__ |
return path; |
#else |
return replace(path,"\\","/"); |
#endif |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mapping(string:program|NoValue) programs=(["/master":this_program]); |
mapping(program:object) documentation = ([]); |
mapping(program:string) source_cache; |
|
mapping (program:object|NoValue) objects=([ |
this_program : this, |
object_program(_static_modules): _static_modules, |
]); |
|
mapping(string:object|NoValue) fc=([]); |
|
|
|
|
|
|
|
protected mapping(program:string) rev_programs = ([]); |
protected mapping(object:program) rev_objects = ([]); |
protected mapping(mixed:string) rev_fc = ([]); |
|
string programs_reverse_lookup (program prog) |
|
{ |
|
|
|
|
if (!rev_programs) return UNDEFINED; |
if (sizeof (rev_programs) < sizeof (programs)) { |
foreach (programs; string path; program|NoValue prog) |
if (prog == no_value) |
m_delete (programs, path); |
else |
rev_programs[prog] = path; |
} |
return rev_programs[prog]; |
} |
|
program objects_reverse_lookup (object obj) |
|
{ |
|
|
if (sizeof (rev_objects) < sizeof (objects)) { |
foreach (objects; program prog; object|NoValue obj) |
if (obj == no_value) |
m_delete (rev_objects, obj); |
else |
rev_objects[obj] = prog; |
} |
return rev_objects[obj]; |
} |
|
string fc_reverse_lookup (object obj) |
|
{ |
if (sizeof (rev_fc) < sizeof (fc)) { |
foreach (fc; string path; mixed obj) |
if (obj == no_value) |
m_delete (fc, obj); |
else |
rev_fc[obj] = path; |
} |
return rev_fc[obj]; |
} |
|
array(string) query_precompiled_names(string fname) |
|
|
{ |
#ifdef PRECOMPILED_SEARCH_MORE |
|
|
|
fname = fakeroot (fname); |
|
|
foreach (pike_module_path, string path) |
if (has_prefix (fname, path)) |
return map (pike_module_path, `+, "/", fname[sizeof (path)..], ".o"); |
#endif |
return ({ fname + ".o" }); |
} |
|
int get_precompiled_mtime (string id) |
|
|
|
{ |
Stat s = master_file_stat (fakeroot (id)); |
return s && s->isreg ? s->mtime : -1; |
} |
|
string read_precompiled (string id) |
|
|
{ |
return master_read_file (id); |
} |
|
protected class CompileCallbackError |
{ |
inherit _static_modules.Builtin.GenericError; |
constant is_generic_error = 1; |
constant is_compile_callback_error = 1; |
constant is_cpp_or_compilation_error = 1; |
} |
|
protected void compile_cb_error (string msg, mixed ... args) |
|
|
|
{ |
if (sizeof (args)) msg = sprintf (msg, @args); |
throw (CompileCallbackError (msg, backtrace()[..<1])); |
} |
|
protected void compile_cb_rethrow (object|array err) |
|
|
|
{ |
array bt; |
if (array|object e = catch (bt = get_backtrace (err))) |
handle_error (e); |
throw (CompileCallbackError (call_describe_error (err), bt)); |
} |
|
protected void call_compile_warning_lineno (object handler, string file, |
int lineno, string msg, |
mixed ... args) { |
if (sizeof (args)) msg = sprintf (msg, @args); |
msg = trim (msg); |
if (handler->?compile_warning) |
handler->compile_warning (file, lineno, msg); |
else if (master()->compile_warning) |
master()->compile_warning (file, lineno, msg); |
else |
compile_warning (file, lineno, msg); |
} |
|
protected void call_compile_warning (object handler, string file, |
string msg, mixed ... args) |
{ |
call_compile_warning_lineno(handler, file, 0, msg, @args); |
} |
|
#if constant(_static_modules.Builtin.mutex) |
#define THREADED |
#endif |
|
#ifdef __NT__ |
#define FIX_CASE(X) lower_case(X) |
#else |
#define FIX_CASE(X) (X) |
#endif /* __NT__ */ |
|
protected string base_from_filename(string fname) |
{ |
string low_name = FIX_CASE(fname); |
if (has_prefix(low_name, ".#")) return 0; |
if (has_suffix(low_name, ".pike") || |
has_suffix(low_name, ".pmod")) { |
return fname[..<5]; |
} |
if (has_suffix(low_name, ".so")) { |
return fname[..<3]; |
} |
return 0; |
} |
|
protected int prio_from_filename(string fname) |
{ |
fname = FIX_CASE(fname); |
if (has_suffix(fname, ".pmod")) return 3; |
if (has_suffix(fname, ".so")) return 2; |
if (has_suffix(fname, ".pike")) return 1; |
|
|
return 0; |
} |
|
protected bool is_joinnode(mixed o) |
{ |
return objectp(o) && object_program(o)->is_resolv_joinnode; |
} |
|
protected bool is_dirnode(mixed o) |
{ |
return objectp(o) && object_program(o)->is_resolv_dirnode; |
} |
|
|
|
|
|
|
|
|
|
|
array(string) module_defined(object|program mod) |
{ |
array files = ({}); |
if (programp(mod)) |
return ({ Builtin.program_defined([program]mod) }); |
|
array mods; |
if (is_joinnode(mod)) |
mods = mod->joined_modules; |
else |
mods = ({ mod }); |
|
foreach (mods;; object mod) |
{ |
if (is_dirnode(mod)) |
files += ({ Builtin.program_defined(object_program(mod->module)) }); |
else |
files += ({ Builtin.program_defined(object_program(mod)) }); |
} |
return files; |
} |
|
|
void enable_source_cache() |
{ |
if (!source_cache) |
source_cache = ([]); |
} |
|
|
|
|
|
|
|
|
object show_doc(program|object|function obj) |
{ |
object doc_extractor = main_resolv("Tools.AutoDoc.PikeExtractor.extractClass"); |
string child; |
program prog; |
|
if (programp(obj)) |
prog = obj; |
if (functionp(obj)) |
{ |
prog = function_program(obj); |
child = ((describe_function(obj)||"")/"->")[-1]; |
} |
if (objectp(obj)) |
{ |
if (is_joinnode(obj)) |
obj = obj->joined_modules[0]; |
if (is_dirnode(obj)) |
prog = object_program(obj->module); |
else |
prog = object_program(obj); |
} |
|
|
if (prog && !documentation[prog] && doc_extractor) |
{ |
string source; |
if (source_cache && source_cache[prog]) |
source = source_cache[prog]; |
else |
{ |
array sourceref = array_sscanf(Builtin.program_defined(prog), |
"%s%[:]%[0-9]"); |
source = master_read_file(sourceref[0]); |
if (sizeof(sourceref[1]) && sizeof(sourceref[2])) |
{ |
if (programp(prog)) |
child = ((describe_program(prog)||"")/".")[-1]; |
} |
} |
|
if (source) |
{ |
catch |
{ |
documentation[prog] = doc_extractor(source, sprintf("%O", prog)); |
}; |
|
} |
} |
|
if (documentation[prog]) |
{ |
if (child) |
return documentation[prog]->findObject(child)||documentation[prog]->findChild(child); |
else |
return documentation[prog]; |
} |
} |
|
|
protected string call_describe_backtrace(array(mixed) trace, |
void|int linewidth) |
{ |
return (all_constants()["describe_backtrace"]||describe_backtrace) |
(trace, linewidth); |
} |
|
protected string call_describe_error(mixed err) |
{ |
return (all_constants()["describe_error"]||describe_error)(err); |
} |
|
protected program low_findprog(string pname, |
string ext, |
object|void handler, |
void|int mkobj) |
{ |
program ret; |
Stat s; |
string fname=pname+ext; |
|
resolv_debug("low_findprog(%O, %O, %O, %O)\n", |
pname, ext, handler, mkobj); |
|
#ifdef PIKE_MODULE_RELOC |
fname = unrelocate_module(fname); |
#endif |
|
#ifdef __NT__ |
|
if(getenv("OSTYPE")=="cygwin32") |
{ |
string tmp=fname[..1]; |
if((tmp=="//" || tmp=="\\\\") && (fname[3]=='/' || fname[3]=='\\')) |
{ |
if(!master_file_stat(fname)) |
{ |
fname=fname[2..2]+":"+fname[3..]; |
} |
} |
} |
#endif |
|
if( (s=master_file_stat(fakeroot(fname))) && s->isreg ) |
{ |
#ifdef PIKE_AUTORELOAD |
if(!autoreload_on || load_time[fname] >= s->mtime) |
#endif |
{ |
if(!undefinedp (ret=programs[fname]) && ret != no_value) { |
resolv_debug ("low_findprog %s: returning cached (no autoreload)\n", fname); |
return ret; |
} |
} |
|
AUTORELOAD_BEGIN(); |
|
#ifdef PIKE_AUTORELOAD |
if (load_time[fname] >= s->mtime) |
if (!undefinedp (ret=programs[fname]) && ret != no_value) { |
resolv_debug ("low_findprog %s: returning cached (autoreload)\n", fname); |
return ret; |
} |
#endif |
|
object compiler_lock = DefaultCompilerEnvironment->lock(); |
if(!undefinedp(ret = programs[fname]) && (ret != no_value)) { |
destruct(compiler_lock); |
resolv_debug("low_findprog %s: returning cached (from other thread).\n", |
fname); |
return ret; |
} |
|
switch(ext) |
{ |
case "": |
case ".pike": |
foreach(query_precompiled_names(fname), string oname) { |
int o_mtime = get_precompiled_mtime (oname); |
if (o_mtime >= 0) { |
if (o_mtime >= s->mtime) { |
mixed err=catch { |
object|program decoded; |
AUTORELOAD_CHECK_PRECOMPILED_FILE (oname); |
resolv_debug ("low_findprog %s: decoding dumped\n", fname); |
INC_RESOLV_MSG_DEPTH(); |
decoded = decode_value(read_precompiled (oname), |
(handler->?get_codec || |
get_codec)(fname, mkobj, handler)); |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("low_findprog %s: dump decode ok\n", fname); |
if (decoded->?this_program_does_not_exist) { |
resolv_debug ("low_findprog %s: program claims not to exist\n", |
fname); |
return programs[fname] = 0; |
} |
else { |
if (objectp(decoded)) { |
resolv_debug("low_findprog %s: decoded object %O\n", |
fname, decoded); |
objects[ret = object_program(decoded)] = decoded; |
} else { |
ret = decoded; |
} |
resolv_debug("low_findprog %s: returning %O\n", fname, ret); |
return programs[fname]=ret; |
} |
}; |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("low_findprog %s: dump decode failed\n", fname); |
programs[fname] = no_value; |
call_compile_warning (handler, oname, |
"Decode failed: " + |
call_describe_error(err)); |
|
} else if (out_of_date_warning) { |
call_compile_warning (handler, oname, |
"Compiled file is out of date"); |
} |
} |
} |
|
resolv_debug ("low_findprog %s: compiling, mkobj: %O\n", fname, mkobj); |
INC_RESOLV_MSG_DEPTH(); |
programs[fname]=ret=__empty_program(0, fname); |
AUTORELOAD_CHECK_FILE (fname); |
string src; |
if (array|object err = catch (src = master_read_file (fname))) { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("low_findprog %s: failed to read file\n", fname); |
objects[ret] = no_value; |
ret=programs[fname]=0; |
compile_cb_rethrow (err); |
} |
if ( mixed e=catch { |
ret=compile_string(src, fname, handler, |
ret, |
mkobj? (objects[ret]=__null_program()) : 0); |
} ) |
{ |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("low_findprog %s: compilation failed\n", fname); |
objects[ret] = no_value; |
ret=programs[fname]=0; |
destruct(compiler_lock); |
throw(e); |
} |
destruct(compiler_lock); |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("low_findprog %s: compilation ok\n", fname); |
break; |
|
#if constant(load_module) |
case ".so": |
if (fname == "") { |
werror( "low_findprog(%O, %O) => load_module(\"\")\n" |
"%s\n", pname, ext, call_describe_backtrace(backtrace()) ); |
} |
|
if (array|object err = catch (ret = load_module(fakeroot(fname)))) { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("low_findprog %s: failed to load binary\n", fname); |
objects[ret] = no_value; |
ret=programs[fname]=0; |
if (objectp (err) && err->is_module_load_error) |
|
|
|
|
|
|
|
|
|
call_compile_warning (handler, fname, |
"Failed to load library: %s\n", err->reason); |
else |
compile_cb_rethrow (err); |
} |
else |
resolv_debug ("low_findprog %s: loaded binary\n", fname); |
#endif /* load_module */ |
} |
|
AUTORELOAD_FINISH(ret,programs,fname); |
|
if (ret->?this_program_does_not_exist) { |
resolv_debug ("low_findprog %s: program says it doesn't exist\n", fname); |
return programs[fname] = 0; |
} |
else { |
if(!ret) |
resolv_debug("low_findprog %s: dependencies failed.\n", fname); |
else |
resolv_debug("low_findprog %s: returning %O\n", fname, ret); |
return programs[fname]=ret; |
} |
} |
|
resolv_debug ("low_findprog %s: file not found\n", fname); |
return 0; |
} |
|
|
|
|
|
|
void unregister(program p) |
{ |
|
object compiler_lock = DefaultCompilerEnvironment->lock(); |
|
if(string fname=rev_programs[p] || search(programs,p)) { |
resolv_debug("unregister %s\n", fname); |
if (m_delete (rev_programs, p)) |
m_delete (programs, fname); |
else |
programs[fname] = no_value; |
|
string name = program_path_to_name (fname); |
mixed n = has_value (name, '.') ? |
resolv ((name / ".")[..<1] * ".") : |
get_root_module(); |
if (is_dirnode(n) || is_joinnode(n)) |
n->delete_value (p); |
|
fname = dirname (fname); |
if ( fname!="" && objectp (n = fc[fname]) ) |
if (is_dirnode(n)) |
n->delete_value (p); |
} |
|
object o = m_delete(objects, p); |
if (objectp (o)) { |
m_delete(rev_objects, o); |
} |
|
foreach (fc; string name; mixed mod) |
if (objectp(mod) && object_program(mod) == p) |
if (m_delete (rev_fc, mod)) |
m_delete (fc, name); |
else |
fc[name] = no_value; |
|
|
} |
|
protected program findprog(string pname, |
string ext, |
object|void handler, |
void|int mkobj) |
{ |
switch(ext) |
{ |
case ".pike": |
case ".so": |
return low_findprog(pname,ext,handler, mkobj); |
|
default: |
pname+=ext; |
return |
low_findprog(pname,"", handler, mkobj) || |
low_findprog(pname,".pike", handler, mkobj) || |
low_findprog(pname,".so", handler, mkobj); |
} |
} |
|
program low_cast_to_program(string pname, |
string current_file, |
object|void handler, |
void|int mkobj) |
{ |
string ext; |
string nname; |
|
|
|
|
if(sscanf(reverse(BASENAME(pname)),"%s.%s",ext, nname)) |
{ |
ext="."+reverse(ext); |
pname=pname[..<sizeof(ext)]; |
} |
else { |
ext=""; |
} |
|
|
|
if(IS_ABSOLUTE_PATH(pname)) |
{ |
program|NoValue prog = programs[pname]; |
if ((!undefinedp(prog)) && (prog != no_value)) |
{ |
return prog; |
} |
#ifdef PIKE_MODULE_RELOC |
|
if (!has_prefix(pname, "/${PIKE_MODULE_PATH}/"+UPDIR)) |
#endif |
pname=combine_path("",pname); |
return findprog(pname,ext,handler,mkobj); |
} |
else { |
string cwd; |
if(current_file) |
{ |
cwd=dirname(current_file); |
} |
else { |
cwd=getcwd(); |
} |
|
if(program ret=findprog(combine_path(cwd,pname),ext,handler,mkobj)) |
return ret; |
|
foreach(pike_program_path, string path) |
if(program ret=findprog(combine_path(path,pname),ext,handler,mkobj)) |
return ret; |
|
return 0; |
} |
} |
|
|
|
|
|
|
program cast_to_program(string pname, |
string current_file, |
object|void handler) |
{ |
resolv_debug ("cast_to_program(%O, %O)\n", pname, current_file); |
INC_RESOLV_MSG_DEPTH(); |
program ret = low_cast_to_program(pname, current_file, handler); |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("cast_to_program(%O, %O) => %O\n", pname, current_file, ret); |
if (programp (ret)) return ret; |
error("Cast %O to program failed%s.\n", |
pname, |
(current_file && current_file!="-") ? sprintf(" in %O",current_file) : ""); |
} |
|
|
protected string narrowify_string(string s) |
{ |
if (Builtin.string_width(s) <= 8) return s; |
|
return map(s/"", |
lambda(string s) { |
if (Builtin.string_width(s) <= 8) return s; |
int c = s[0] & 0xffffffff; |
if (c <= 0xffff) return sprintf("\\u%04x", c); |
return sprintf("\\U%08x", c); |
}) * ""; |
} |
|
|
|
void handle_error(array|object trace) |
{ |
|
|
if(mixed x=catch { |
werror(call_describe_backtrace(trace)); |
}) { |
|
|
|
werror("Error in handle_error in master object:\n"); |
if(catch { |
|
|
catch { |
if (catch { |
string msg = [string]x[0]; |
array bt = [array]x[1]; |
werror("%s", narrowify_string(msg)); |
werror(narrowify_string(sprintf("%O\n", bt))); |
}) { |
werror(narrowify_string(sprintf("%O\n", x))); |
} |
}; |
werror(narrowify_string(sprintf("Original error:\n" |
"%O\n", trace))); |
}) { |
werror("sprintf() failed to write error.\n"); |
} |
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
optional int(0..1) handle_attribute(mixed value, string attribute) |
{ |
switch(attribute) { |
#if constant(validate_utf8) |
case "utf8": |
return stringp(value) && validate_utf8(value, 3); |
#endif |
} |
return UNDEFINED; |
} |
|
|
|
|
constant master_efuns = ({ |
"error", |
#if !constant(basename) |
"basename", |
#endif |
#if !constant(dirname) |
"dirname", |
#endif |
"is_absolute_path", |
"explode_path", |
|
"compile_string", |
"compile_file", |
"add_include_path", |
"remove_include_path", |
"add_module_path", |
"remove_module_path", |
"add_program_path", |
"remove_program_path", |
"describe_backtrace", |
"describe_error", |
"get_backtrace", |
"normalize_path", |
"true", |
"false", |
"zero", |
"getenv", |
"putenv", |
|
#ifdef GETCWD_CACHE |
"cd", |
"getcwd", |
#endif |
}); |
|
|
string include_prefix; |
|
|
string doc_prefix; |
|
|
string cflags; |
|
|
string ldflags; |
|
|
|
|
|
|
enum bool { false=0, true=1 }; |
|
|
typedef int(0..0) zero; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected void add_constants() |
{ |
#if constant(_static_modules.Builtin.__HAVE_COMPILER_NO_HANDLERS__) |
add_constant("compile", compile); |
#endif /* _static_modules.Builtin.__HAVE_COMPILER_NO_HANDLERS__ */ |
add_constant("get_active_compilation_handler", get_active_compilation_handler); |
add_constant("get_active_error_handler", get_active_error_handler); |
add_constant("CompilerEnvironment", CompilerEnvironment); |
add_constant("DefaultCompilerEnvironment", DefaultCompilerEnvironment); |
add_constant("cpp", cpp); |
|
foreach(master_efuns, string e) |
if (has_index(this, e)) |
add_constant(e, this[e]); |
else |
error("Function %O is missing from master.pike.\n", e); |
|
|
|
|
|
|
|
|
add_constant("bool", typeof([int(0..1)](mixed)0)); |
|
add_constant("__dirnode", dirnode); |
add_constant("__joinnode", joinnode); |
|
werror = locale_werror; |
add_constant("write", write); |
add_constant("werror", werror); |
|
|
|
add_constant("get_dir", high_master_get_dir ); |
add_constant("file_stat", lambda( string f, int|void d ) { return file_stat(f,d);} ); |
|
object rnd = Builtin.RandomSystem(); |
add_constant("random", rnd->random); |
add_constant("random_string", rnd->random_string); |
|
#define CO(X) add_constant(#X,Builtin.__backend->X) |
CO(call_out); |
CO(_do_call_outs); |
CO(find_call_out); |
CO(remove_call_out); |
CO(call_out_info); |
} |
|
protected void create() |
{ |
add_constants(); |
|
#if "#share_prefix#"[0]!='#' |
|
add_include_path("#share_prefix#/include"); |
add_module_path("#share_prefix#/modules"); |
#endif |
|
#if "#lib_prefix#"[0]!='#' |
|
add_include_path("#lib_prefix#/include"); |
add_module_path("#lib_prefix#/modules"); |
#endif |
|
#if "#cflags# "[0]!='#' |
cflags = "#cflags#"; |
#endif |
|
#if "#ldflags# "[0]!='#' |
ldflags = "#ldflags#"; |
#endif |
|
#if "#include_prefix#"[0]!='#' |
include_prefix = "#include_prefix#"; |
cflags = (cflags || "") + " -I" + dirname(include_prefix); |
#endif |
|
#if "#doc_prefix#"[0]!='#' |
doc_prefix = "#doc_prefix#"; |
#endif |
|
#if constant(__embedded_resource_directory) |
|
|
add_include_path(__embedded_resource_directory + "/lib/include"); |
add_module_path(__embedded_resource_directory + "/lib/modules"); |
add_module_path(__embedded_resource_directory + "/" + replace(uname()->machine, " ", "_") + "/modules"); |
|
#endif |
system_module_path=pike_module_path; |
} |
|
|
|
|
|
|
|
|
|
|
|
program handle_inherit(string pname, string current_file, object|void handler) |
{ |
resolv_debug ("handle_inherit(%O, %O)\n", pname, current_file); |
INC_RESOLV_MSG_DEPTH(); |
program ret = cast_to_program(pname, current_file, handler); |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("handle_inherit(%O, %O) => %O\n", pname, current_file, ret); |
return ret; |
} |
|
object low_cast_to_object(string oname, string current_file, |
object|void current_handler) |
{ |
program p; |
object o; |
|
p = low_cast_to_program(oname, current_file, current_handler, 1); |
if(!p) return 0; |
if(!objectp(o = objects[p])) { |
object compiler_lock = DefaultCompilerEnvironment->lock(); |
|
if(!objectp(o = objects[p])) o = objects[p] = p(); |
destruct(compiler_lock); |
} |
return o; |
} |
|
|
|
|
object cast_to_object(string oname, string current_file, |
object|void current_handler) |
{ |
resolv_debug ("cast_to_object(%O, %O)\n", oname, current_file); |
INC_RESOLV_MSG_DEPTH(); |
object o = low_cast_to_object(oname, current_file, current_handler); |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("cast_to_object(%O, %O) => %O\n", oname, current_file, o); |
if (objectp (o)) return o; |
error("Cast %O to object failed%s.\n", |
oname, |
(current_file && current_file!="-") ? sprintf(" in %O",current_file) : ""); |
} |
|
|
|
protected class ZERO_TYPE {}; |
|
protected object Unicode; |
|
void try_issue_deprecation_warning(object compilation_handler) |
{ |
if (object active_compiler = get_active_compiler()) { |
if (!active_compiler->suppress_deprecation_warnings()) { |
call_compile_warning_lineno(compilation_handler, |
active_compiler->current_file, |
active_compiler->current_line, |
"Using a deprecated value."); |
} |
} |
} |
|
|
|
|
|
class dirnode (string dirname, object|void compilation_handler, |
string|void name) |
{ |
constant is_resolv_dirnode = 1; |
|
|
mixed module; |
mapping(string:mixed) cache=([]); |
mapping(string:int(0..1)) deprecated_cache=([]); |
|
|
|
protected mapping(string:array(string)) file_paths = ([]); |
|
#ifdef __NT__ |
#define FIX_CASE(X) lower_case(X) |
#else |
#define FIX_CASE(X) (X) |
#endif /* __NT__ */ |
|
protected string base_from_filename(string fname) |
{ |
string low_name = FIX_CASE(fname); |
catch { |
|
low_name = utf8_to_string(low_name); |
if (Builtin.string_width(low_name) > 8) { |
|
|
|
if (!Unicode) { |
Unicode = resolv("Unicode"); |
} |
low_name = Unicode.normalize(low_name, "NFC"); |
} |
}; |
if (has_prefix(low_name, ".#")) return 0; |
if (has_suffix(low_name, ".pike") || |
has_suffix(low_name, ".pmod")) { |
return fname[..<5]; |
} |
if (has_suffix(low_name, ".so")) { |
return fname[..<3]; |
} |
return 0; |
} |
|
protected int prio_from_filename(string fname) |
{ |
fname = FIX_CASE(fname); |
if (has_suffix(fname, ".pmod")) return 3; |
if (has_suffix(fname, ".so")) return 2; |
if (has_suffix(fname, ".pike")) return 1; |
return 0; |
} |
|
protected void create() |
{ |
if (!dirname) { |
error("Attempt to create a dirnode without a directory.\n" |
"Have you inherited a dirnode?\n"); |
} |
|
resolv_debug ("dirnode(%O,%O) created with name %O\n", dirname, |
compilation_handler, name); |
fc[dirname]=this; |
if (!sizeof(dirname)) return; |
array(string) files = sort(master_get_dir(dirname)||({})); |
array(string) bases = map(files, base_from_filename); |
files = filter(files, bases); |
bases = filter(bases, bases); |
resolv_debug("dirnode(%O,%O) got %d files.\n", |
dirname, compilation_handler, sizeof(bases)); |
if (!sizeof(files)) return; |
|
foreach(files; int no; string fname) { |
fname = combine_path(dirname, fname); |
string base = bases[no]; |
if (base == "module") { |
|
module = module_checker(); |
} |
array(string) paths = file_paths[base]; |
if (!paths) { |
|
file_paths[base] = ({ fname }); |
continue; |
} |
|
|
|
int prio = prio_from_filename(fname); |
int index; |
foreach(paths; index; string other_fname) { |
if (prio_from_filename(other_fname) <= prio) break; |
} |
file_paths[base] = paths[..index-1] + ({ fname }) + paths[index..]; |
} |
} |
|
protected class module_checker |
{ |
protected int `!() |
{ |
resolv_debug ("dirnode(%O)->module_checker()->`!()\n",dirname); |
|
if (mixed err = catch { |
|
if (module = cache["module"] || low_ind("module", 1)) { |
|
|
|
|
cache=([]); |
deprecated_cache=([]); |
_cache_full=0; |
} |
resolv_debug("dirnode(%O)->module_checker()->`!() => %s\n", |
dirname, !module ? "doesn't exist" : "exists"); |
return !module; |
}) { |
|
|
|
|
|
|
|
|
resolv_debug("dirnode(%O)->module_checker()->`!() => failure, doesn't exist\n", |
dirname); |
return 1; |
} |
} |
|
protected mixed `[](string index) |
{ |
resolv_debug ("dirnode(%O)->module_checker()[%O] => %O\n", |
dirname, index, module[?index]); |
return module[?index]; |
} |
protected array(string) _indices() { if(module) return indices(module); } |
protected array _values() { if(module) return values(module); } |
} |
|
protected mixed low_ind(string index, int(0..1)|void set_module) |
{ |
array(string) paths; |
|
INC_RESOLV_MSG_DEPTH(); |
|
if (!(paths = file_paths[index])) { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug("dirnode(%O)->ind(%O) => no file match\n", |
dirname, index); |
return UNDEFINED; |
} |
|
foreach(paths, string fname) { |
resolv_debug("dirnode(%O)->ind(%O) Trying file %O...\n", |
dirname, index, fname); |
Stat stat = master_file_stat(fakeroot(fname)); |
if (!stat) { |
resolv_debug("dirnode(%O)->ind(%O) file %O disappeared!\n", |
dirname, index, fname); |
continue; |
} |
if (has_suffix(fname, ".pmod")) { |
if (stat->isdir) { |
if (dirnode n = fc[fname]) { |
|
|
|
resolv_debug("dirnode(%O)->ind(%O) => found subdirectory %O, " |
"returning old dirnode\n", dirname, index, fname); |
return n; |
} |
resolv_debug("dirnode(%O)->ind(%O) => found subdirectory %O, " |
"creating new dirnode\n", dirname, index, fname); |
return fc[fname] = dirnode(fname, compilation_handler, |
name && (name == "predef::" ? |
index : name + "." + index)); |
} |
resolv_debug("dirnode(%O)->ind(%O) casting (object)%O\n", |
dirname, index, fname); |
|
|
|
|
|
mixed ret; |
if (ret = catch { |
if (objectp(ret = low_cast_to_object(fname, 0, compilation_handler))) { |
|
if (set_module) module = ret; |
if(mixed tmp=ret->_module_value) ret=tmp; |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug("dirnode(%O)->ind(%O) => found submodule %O:%O\n", |
dirname, index, fname, ret); |
return ret; |
} |
}) { |
resolv_debug("dirnode(%O)->ind(%O) ==> Cast to object failed: %s\n", |
dirname, index, call_describe_backtrace(ret)); |
} |
} else { |
resolv_debug("dirnode(%O)->ind(%O) casting (program)%O\n", |
dirname, index, fname); |
program|object ret; |
if (ret = low_cast_to_program(fname, 0, compilation_handler)) { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug("dirnode(%O)->ind(%O) => found subprogram %O:%O\n", |
dirname, index, fname, ret); |
#if constant(load_module) |
if (has_suffix(fname, ".so")) { |
|
if (!ret->_module_value) { |
object o; |
|
if(!objectp(o = objects[ret])) { |
object compiler_lock = DefaultCompilerEnvironment->lock(); |
if(!objectp(o = objects[ret])) o = objects[ret] = ret(); |
destruct(compiler_lock); |
} |
ret = o; |
} |
if(mixed tmp=ret->_module_value) ret=tmp; |
} |
#endif |
return ret; |
} |
} |
resolv_debug("dirnode(%O)->ind(%O) => failure for file %O\n", |
dirname, index, fname); |
} |
|
resolv_debug("dirnode(%O)->ind(%O) => UNDEFINED\n", |
dirname, index); |
return UNDEFINED; |
} |
|
protected mixed ind(string index) |
{ |
resolv_debug ("dirnode(%O)->ind(%O)\n", dirname, index); |
INC_RESOLV_MSG_DEPTH(); |
|
if (_cache_full) { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug("dirnode(%O)->ind(%O) => cache_full %O\n", |
dirname, index, cache[index]); |
return cache[index]; |
} |
|
if(module) |
{ |
mixed o; |
if(!undefinedp(o=module[index])) |
{ |
mixed t; |
|
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("dirnode(%O)->ind(%O) => found %O\n", |
dirname, index, o); |
|
|
|
|
|
|
if (objectp(module)) |
t = typeof_identifier(object_program(module), index); |
|
if (t && deprecated_typep(t)) |
{ |
deprecated_cache[index] = 1; |
try_issue_deprecation_warning(compilation_handler); |
} |
return o; |
} |
resolv_debug ("dirnode(%O)->ind(%O) => not found in module\n", |
dirname, index); |
} |
else |
resolv_debug ("dirnode(%O)->ind(%O) => no module\n", dirname, index); |
|
DEC_RESOLV_MSG_DEPTH(); |
return low_ind(index); |
} |
|
protected mixed `[]=(string index, mixed value) |
{ |
if(module && has_index(module, index)) |
return module[index]=value,cache[index]=value; |
error("No such variable (%s) in object.\n", index); |
} |
|
protected mixed `->=(string index, mixed value) |
{ |
return `[]=(index, value); |
} |
|
protected mixed `[](string index) |
{ |
mixed ret; |
|
#ifdef MODULE_TRACE |
werror("%*nDirnode(%O) cache[%O] ?????\n", |
sizeof(backtrace()),dirname,index); |
#endif |
if(!undefinedp(ret=cache[index])) |
{ |
#ifdef MODULE_TRACE |
werror("%*nDirnode(%O) cache[%O] => %O%s\n", |
sizeof(backtrace()),dirname,index, ret, |
(ret != ZERO_TYPE)?"":" (zero_type)"); |
#endif |
if (ret != ZERO_TYPE) |
{ |
if (deprecated_cache[index]) |
try_issue_deprecation_warning(compilation_handler); |
return ret; |
} |
#ifdef MODULE_TRACE |
werror("%*nDirnode(%O) ZERO_TYPE!\n", |
sizeof(backtrace()),dirname); |
#endif |
return UNDEFINED; |
} |
ret=ind(index); |
|
|
|
if(ret == predef::__placeholder_object) { |
#ifdef MODULE_TRACE |
werror("%*nDirnode(%O) PLACE_HOLDER.\n", |
sizeof(backtrace()),dirname); |
#endif |
return ret; |
} |
|
cache[index] = undefinedp(ret) ? ZERO_TYPE : ret; |
return ret; |
} |
|
protected mixed `->(string index) |
{ |
if( (< "dirname", "name", "is_resolv_dirnode", |
"module", "delete_value", "identifier_deprecatedp" >)[index] ) |
return ::`->(index); |
return `[](index); |
} |
|
protected mixed safe_index(string index) |
{ |
mixed err; |
resolv_debug ("dirnode(%O): %O...\n", dirname, index); |
if (err = catch { return `[](index); }) { |
call_compile_warning (compilation_handler, |
dirname+"."+fname, |
"Compilation failed: " + |
call_describe_error(err)); |
} |
return UNDEFINED; |
} |
|
int(0..1) identifier_deprecatedp(string index) |
{ |
if (has_index(cache, index) || deprecated_cache[index]) |
return deprecated_cache[index]; |
safe_index(index); |
return deprecated_cache[index]; |
} |
|
protected int(0..1) _cache_full; |
protected void fill_cache() |
{ |
if (_cache_full) { |
return; |
} |
|
resolv_debug ("dirnode(%O) => Filling cache...\n", dirname); |
|
|
|
|
|
if (module) { |
resolv_debug("dirnode(%O): module: %O, indices:%{%O, %}\n", |
dirname, module, indices(module)); |
map(indices(module), safe_index); |
} |
|
map(indices(file_paths), safe_index); |
_cache_full = (object_program(module) != __null_program); |
resolv_debug ("dirnode(%O) => Cache %s.\n", dirname, |
_cache_full?"full":"partially filled"); |
} |
|
protected array(string) _indices() |
{ |
fill_cache(); |
|
|
|
|
return filter (indices (cache), map (values (cache), `!=, ZERO_TYPE)); |
} |
|
protected array(mixed) _values() |
{ |
fill_cache(); |
return values(cache) - ({ZERO_TYPE}); |
} |
|
void delete_value (mixed val) |
{ |
if (string name = search (cache, val)) { |
m_delete (cache, name); |
m_delete (deprecated_cache, name); |
_cache_full = 0; |
} |
} |
|
protected int(0..) _sizeof() { |
return sizeof(_values()); |
} |
|
protected string _sprintf(int as) |
{ |
return as=='O' && (name || sprintf("master()->dirnode(%O:%O)", |
dirname, module && module)); |
} |
} |
|
|
|
|
|
|
class joinnode (array(object|mapping) joined_modules, |
object|void compilation_handler, |
joinnode|mapping(mixed:int(0..0))|void fallback_module, |
string|void name) |
{ |
constant is_resolv_joinnode = 1; |
|
mapping(string:mixed) cache=([]); |
mapping(string:int(0..1)) deprecated_cache=([]); |
|
protected string _sprintf(int as) |
{ |
if (as != 'O') return 0; |
if (name) { |
if (has_value (name, '|')) |
return "joinnode(" + name + ")"; |
else |
return name; |
} |
else |
return sprintf("master()->joinnode(%O)", joined_modules); |
} |
|
protected void create() |
{ |
if( !fallback_module ) { |
|
|
fallback_module = ([]); |
} |
|
if (!joined_modules) { |
error("Attempt to create a joinnode without joined modules.\n" |
"Have you inherited a joinnode?\n"); |
} |
|
if (!name) |
{ |
mapping(string:int(1..1)) names = ([]); |
foreach (joined_modules, object|mapping m) { |
if (objectp (m) && stringp (m->name)) |
names[m->name] = 1; |
} |
if (sizeof (names)) |
name = sort (indices (names)) * "|"; |
} |
|
resolv_debug ("joinnode(%O) created with name %O\n", joined_modules, name); |
} |
|
void add_path(string path) |
{ |
path = combine_path(getcwd(), path); |
dirnode node = fc[path] || |
(fc[path] = dirnode(path, compilation_handler, |
name && !has_value (name, '|') && name)); |
if (sizeof(joined_modules) && |
joined_modules[0] == node) return; |
joined_modules = ({ node }) + (joined_modules - ({ node })); |
cache = ([]); |
deprecated_cache = ([]); |
} |
|
void rem_path(string path) |
{ |
path = combine_path(getcwd(), path); |
joined_modules = filter(joined_modules, |
lambda(dirnode node) { |
return !is_dirnode(node) || |
(node->dirname != path); |
}); |
cache = ([]); |
deprecated_cache = ([]); |
} |
|
protected mixed ind(string index) |
{ |
resolv_debug ("joinnode(%O)->ind(%O)\n", joined_modules, index); |
INC_RESOLV_MSG_DEPTH(); |
|
array(mixed) res = ({}); |
foreach(joined_modules, object|mapping o) |
{ |
mixed ret; |
if (!undefinedp(ret = o[index])) |
{ |
if (is_dirnode(ret) || is_joinnode(ret)) |
{ |
|
res += ({ ret }); |
if (o->identifier_deprecatedp(index)) |
deprecated_cache[index] = 1; |
} else { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("joinnode(%O)->ind(%O) => found %O\n", |
joined_modules, index, ret); |
|
if (objectp(o) && o->identifier_deprecatedp(index)) |
{ |
deprecated_cache[index] = 1; |
try_issue_deprecation_warning(compilation_handler); |
} |
return (ret); |
} |
} |
} |
|
if (sizeof(res)) { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug("joinnode(%O)->ind(%O) => new joinnode, fallback: %O\n", |
joined_modules, index, fallback_module[index]); |
return joinnode(res, compilation_handler, fallback_module[index], |
name && !has_value (name, '|') && |
(name == "predef::" ? index : name + "." + index)); |
} |
|
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("joinnode(%O)->ind(%O) => not found. Trying fallback %O\n", |
joined_modules, index, fallback_module); |
return fallback_module[index]; |
} |
|
protected mixed `[]=(string index, mixed value) |
{ |
foreach(joined_modules, object|mapping o) |
if(has_index(o, index)) |
return o[index]=value,cache[index]=value; |
error("No such variable (%s) in object.\n", index); |
} |
|
protected mixed `->=(string index, mixed value) |
{ |
if( index=="fallback_module" ) |
return fallback_module=value; |
return `[]=(index, value); |
} |
|
protected mixed `[](string index) |
{ |
mixed ret; |
|
if (!undefinedp(ret = cache[index])) { |
if (ret != ZERO_TYPE) { |
if (deprecated_cache[index]) |
try_issue_deprecation_warning(compilation_handler); |
return ret; |
} |
return UNDEFINED; |
} |
ret = ind(index); |
|
|
|
if(ret == predef::__placeholder_object) return ret; |
|
if (undefinedp(ret)) { |
cache[index] = ZERO_TYPE; |
} else { |
cache[index] = ret; |
} |
return ret; |
} |
|
protected mixed `->(string index) |
{ |
if( (< "joined_modules", "fallback_module", "name", "is_resolv_joinnode", |
"add_path", "rem_path", "delete_value", "_encode", |
"_decode", "identifier_deprecatedp" >)[index] ) |
return ::`->(index); |
return `[](index); |
} |
|
int(0..1) identifier_deprecatedp(string index) |
{ |
if (has_index(cache, index) || deprecated_cache[index]) |
return deprecated_cache[index]; |
`[](index); |
return deprecated_cache[index]; |
} |
|
protected int _cache_full; |
|
protected void fill_cache() |
{ |
if (_cache_full) { |
return; |
} |
foreach(joined_modules, object|mapping|program o) { |
foreach(indices(o), string index) { |
if (!has_index(cache, index)) { |
`[](index); |
} |
} |
} |
foreach(indices(fallback_module), string index) { |
`[](index); |
} |
_cache_full = 1; |
} |
|
protected array(string) _indices() |
{ |
fill_cache(); |
|
|
|
|
return filter (indices (cache), map (values (cache), `!=, ZERO_TYPE)); |
} |
|
protected array(mixed) _values() |
{ |
fill_cache(); |
return values(cache) - ({ZERO_TYPE}); |
} |
|
protected int(0..) _sizeof() |
{ |
return sizeof(_values()); |
} |
|
void delete_value (mixed val) |
{ |
if (string name = search (cache, val)) |
{ |
m_delete (cache, name); |
m_delete (deprecated_cache, name); |
} |
for (int i = 0; i < sizeof (joined_modules); i++) { |
object|mapping|program o = joined_modules[i]; |
if (o == val) { |
joined_modules = joined_modules[..i - 1] + joined_modules[i + 1..]; |
i--; |
} |
else if (is_dirnode(o) || is_joinnode(o)) |
o->delete_value (val); |
else if (string name = mappingp (o) && search (o, val)) |
m_delete (o, name); |
} |
} |
|
protected int `== (mixed other) |
{ |
|
|
|
return is_joinnode(other) && |
equal (mkmultiset (joined_modules), mkmultiset (other->joined_modules)); |
} |
|
array(object) _encode() |
{ |
return joined_modules; |
} |
|
void _decode (array(object) joined_modules) |
{ |
this::joined_modules = joined_modules; |
} |
} |
|
joinnode handle_import(string path, string|void current_file, |
object|void current_handler) |
{ |
if(current_file) |
{ |
path = combine_path_with_cwd(dirname(current_file), path); |
} else { |
path = combine_path_with_cwd(path); |
} |
|
|
#if 0 |
|
|
|
|
if (module_node_cache[current_handler]) { |
if (module_node_cache[current_handler][path]) { |
return module_node_cache[current_handler][path]; |
} |
} else { |
module_node_cache[current_handler] = ([]); |
} |
module_node node = module_node_cache[current_handler][path] = |
module_node("import::"+path, 0, current_handler); |
#endif /* 0 */ |
joinnode node = joinnode(({}), current_handler); |
#ifdef PIKE_MODULE_RELOC |
|
|
string tmp; |
array(string) paths; |
if(path == "/${PIKE_MODULE_PATH}" || |
has_prefix(path, "/${PIKE_MODULE_PATH}/")) { |
tmp = path[21..]; |
paths = pike_module_path; |
} else { |
tmp = 0; |
paths = ({ path }); |
} |
foreach(paths, string prefix) { |
path = (tmp && sizeof(tmp)? combine_path(prefix, tmp) : prefix); |
auto path_stat = file_stat(path); |
if (!path_stat && tmp) |
continue; |
#else |
auto path_stat = file_stat(path); |
#endif /* PIKE_MODULE_RELOC */ |
if (!path_stat) |
compile_cb_error("Failed to stat file: %O\n", path); |
if (path_stat->isreg) { |
node->joined_modules += ({ low_cast_to_object(path, current_file, current_handler) }); |
} |
else if (path_stat->isdir) { |
node->add_path(path); |
} |
#ifdef PIKE_MODULE_RELOC |
} |
#endif /* PIKE_MODULE_RELOC */ |
return node; |
} |
|
program|object findmodule(string fullname, object|void handler, |
void|string name) |
{ |
program|object o; |
|
resolv_debug ("findmodule(%O)\n", fullname); |
if(!undefinedp(o=fc[fullname]) && o != no_value) |
{ |
if (objectp(o) || programp(o) || o != 0) { |
resolv_debug ("findmodule(%O) => found %O (cached)\n", fullname, o); |
return o; |
} |
resolv_debug ("findmodule(%O) => not found (cached)\n", fullname); |
return UNDEFINED; |
} |
|
if(Stat stat=master_file_stat(fakeroot(fullname))) |
{ |
if(stat->isdir) |
{ |
resolv_debug ("findmodule(%O) => new dirnode\n", fullname); |
return fc[fullname] = dirnode(fullname, handler, name); |
} |
#if constant (load_module) |
else if (has_suffix (fullname, ".so")) { |
o = fc[fullname] = low_cast_to_object(fullname, "/.", handler); |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("findmodule(%O) => got .so object %O\n", fullname, o); |
return o; |
} |
#endif |
} |
|
INC_RESOLV_MSG_DEPTH(); |
|
if(objectp (o = low_cast_to_object(fullname, "/.", handler))) { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("findmodule(%O) => got object %O\n", fullname, o); |
return fc[fullname]=o; |
} |
|
if (programp (o = low_cast_to_program(fullname, "/.", handler))) { |
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("findmodule(%O) => got .pike program %O\n", fullname, o); |
return fc[fullname] = o; |
} |
|
DEC_RESOLV_MSG_DEPTH(); |
resolv_debug ("findmodule(%O) => not found\n", fullname); |
return fc[fullname] = 0; |
} |
|
#if 0 |
mixed handle_import(string what, string|void current_file, object|void handler) |
{ |
string path; |
if(current_file) |
{ |
path = combine_path_with_cwd(dirname(current_file), what); |
} else { |
path = combine_path_with_cwd(what); |
} |
|
#if 0 |
|
|
|
if (handler) { |
resolv_debug ("handle_import(%O, %O, %O) => new dirnode with handler\n", |
what, current_file, handler); |
return dirnode(path, handler); |
} |
#endif |
|
if(objectp (fc[path])) { |
resolv_debug ("handle_import(%O, %O) => found %O (cached)\n", |
object s = file_stat(tmp); |
if(s && s->isreg) |
{ |
object fs; |
catch(fs = resolv("Filesystem.Zip")(tmp)); |
if(fs) add_filesystem_handler(tmp, fs); |
tmp = combine_path(tmp, "include"); |
} |
what, current_file, fc[path]); |
return fc[path]; |
} |
resolv_debug ("handle_import(%O, %O) => new dirnode\n", what, current_file); |
#ifdef PIKE_MODULE_RELOC |
|
|
|
if(path == "/${PIKE_MODULE_PATH}" || |
has_prefix(path, "/${PIKE_MODULE_PATH}/")) { |
string tmp = path[21..]; |
array(dirnode) dirnodes = ({}); |
foreach(pike_module_path, string prefix) { |
string s2 = fakeroot(sizeof(tmp)? combine_path(prefix, tmp) : prefix); |
|
|
if(fs_map[tmp]) |
tmp = combine_path(tmp, "modules"); |
|
if(master_file_stat(s2)) |
dirnodes += ({ dirnode(s2, handler) }); |
} |
resolv_debug("handle_import(%O, %O) => Found %d dirnodes\n", |
what, current_file, sizeof(dirnodes)); |
if (sizeof(dirnodes) > 1) return fc[path] = joinnode(dirnodes); |
if (sizeof(dirnodes)) return fc[path] = dirnodes[0]; |
return UNDEFINED; |
} |
#endif /* PIKE_MODULE_RELOC */ |
return fc[path] = dirnode(fakeroot(path), handler); |
} |
#endif /* 0 */ |
|
multiset no_resolv = (<>); |
|
|
class CompatResolver |
{ |
|
joinnode root_module = |
joinnode(({instantiate_static_modules(predef::_static_modules)}), |
0, 0, "predef::"); |
|
|
mapping(object:joinnode) handler_root_modules = ([]); |
|
|
array(string) system_module_path=({}); |
|
|
array(string) pike_module_path=({}); |
|
|
array(string) pike_include_path=({}); |
|
|
array(string) pike_program_path=({}); |
|
mapping(string:string) predefines = master()->initial_predefines; |
string ver; |
|
|
|
|
|
CompatResolver fallback_resolver; |
|
|
|
|
|
protected void create(mixed version, CompatResolver|void fallback_resolver) |
{ |
resolv_debug("CompatResolver(%O, %O)\n", version, fallback_resolver); |
ver=(string)version; |
#if 0 |
if (version) { |
root_module->symbol = ver + "::"; |
} |
#endif |
if (CompatResolver::fallback_resolver = fallback_resolver) { |
root_module->fallback_module = fallback_resolver->root_module; |
} |
predefines = initial_predefines; |
} |
|
|
|
|
|
|
|
|
|
|
|
|
void add_include_path(string tmp) |
{ |
tmp=normalize_path(combine_path_with_cwd(tmp)); |
pike_include_path-=({tmp}); |
pike_include_path=({tmp})+pike_include_path; |
} |
|
|
|
|
|
|
|
|
void remove_include_path(string tmp) |
{ |
tmp=normalize_path(combine_path_with_cwd(tmp)); |
pike_include_path-=({tmp}); |
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void add_module_path(string path, string|void subpath) |
{ |
path=normalize_path(combine_path_with_cwd(path)); |
|
object s = file_stat(path); |
if(s && s->isreg) |
{ |
object fs; |
catch(fs = resolv("Filesystem.Zip")(path)); |
if(fs) add_filesystem_handler(path, fs); |
if(!subpath) subpath = "modules"; |
path = combine_path(path, subpath); |
} |
|
root_module->add_path(path); |
pike_module_path = ({ path }) + (pike_module_path - ({ path })); |
} |
|
|
|
|
|
|
|
|
void remove_module_path(string tmp) |
{ |
tmp=normalize_path(combine_path_with_cwd(tmp)); |
root_module->rem_path(tmp); |
pike_module_path -= ({ tmp }); |
} |
|
|
|
|
|
|
|
|
void add_program_path(string tmp) |
{ |
tmp=normalize_path(combine_path_with_cwd(tmp)); |
pike_program_path-=({tmp}); |
pike_program_path=({tmp})+pike_program_path; |
} |
|
|
|
|
|
|
|
|
void remove_program_path(string tmp) |
{ |
tmp=normalize_path(combine_path_with_cwd(tmp)); |
pike_program_path-=({tmp}); |
} |
|
|
|
void add_predefine (string name, mixed value) |
{ |
predefines[name] = value; |
} |
|
|
|
void remove_predefine (string name) |
{ |
m_delete (predefines, name); |
} |
|
|
mapping get_predefines() |
{ |
return predefines; |
} |
|
|
|
protected mapping(string:mixed) instantiate_static_modules(object|mapping static_modules) |
{ |
mapping(string:mixed) res = ([]), joins = ([]); |
foreach(indices(static_modules), string name) { |
mixed val = static_modules[name]; |
if (!val->_module_value) |
val = val(); |
if(mixed tmp=val->_module_value) val=tmp; |
if(!has_value(name, '.')) |
res[name] = val; |
else { |
mapping(string:mixed) level = joins; |
string pfx; |
while(2 == sscanf(name, "%s.%s", pfx, name)) |
level = (level[pfx] || (level[pfx] = ([]))); |
level[name] = val; |
} |
} |
joinnode joinify(mapping m) |
{ |
foreach(m; string n; mixed v) |
if(mappingp(v)) |
m[n]=joinify(v); |
return joinnode(({m})); |
}; |
foreach(joins; string n; mixed v) { |
if(mappingp(v)) |
v = joinify(v); |
if(res[n]) |
res[n] = joinnode(({res[n], v}), 0, 0, n); |
else |
res[n] = v; |
} |
return res; |
} |
|
|
|
|
|
|
mapping get_default_module() |
{ |
resolv_debug ("%O->get_default_module()\n", this); |
|
|
|
|
|
|
|
int saved_compat_minor=compat_minor; |
int saved_compat_major=compat_major; |
compat_minor=-1; |
compat_major=-1; |
|
mixed x; |
mixed err =catch { |
if(resolv("__default") && (x=resolv("__default.all_constants"))) |
x=x(); |
}; |
|
compat_major=saved_compat_major; |
compat_minor=saved_compat_minor; |
if(err) throw(err); |
return x; |
} |
|
|
|
|
joinnode get_root_module(object|void current_handler) |
{ |
if (!root_module) { |
error("get_root_module(%O): No default root module!\n", |
current_handler); |
} |
if (!current_handler) return root_module; |
joinnode node = handler_root_modules[current_handler]; |
if (node) return node; |
|
|
mixed static_modules = _static_modules; |
if (current_handler->get_default_module) { |
mapping(string:mixed) default_module = |
current_handler->get_default_module(); |
if (default_module) { |
static_modules = default_module["_static_modules"] || ([]); |
} |
} |
|
node = joinnode(({ |
|
([ "_static_modules" : static_modules ] |