ec94462002-05-01Martin Stjernholm // -*- Pike -*-
2f520e2002-04-28Martin Nilsson // // Master Control Program for Pike. // // This file is part of Pike. For copyright information see COPYRIGHT.
59e32d2002-06-01Martin Nilsson // Pike is distributed under GPL, LGPL and MPL. See the file COPYING // for more information.
2f520e2002-04-28Martin Nilsson //
c896b41998-04-29Henrik Grubbström (Grubba) 
a580e12000-09-27Fredrik Hübinette (Hubbe) #pike __REAL_VERSION__
7c386d2018-12-08Marcus Comstedt //#charset iso-8859-1 // hardcoded, can not be changed
0fcf0c2004-03-05Martin Nilsson //#pragma strict_types
0ffc192016-11-05Tobias S. Josefowitz #pragma dynamic_dot
2f520e2002-04-28Martin Nilsson 
d5e23b2008-06-01Henrik Grubbström (Grubba) //! @appears predef::MasterObject //! //! Master control program for Pike. //! //! @seealso //! @[predef::master()], @[predef::replace_master()]
2f520e2002-04-28Martin Nilsson // --- Some configurable parameters
bec57d1999-09-06Fredrik Hübinette (Hubbe) #define PIKE_AUTORELOAD
2f520e2002-04-28Martin Nilsson #define GETCWD_CACHE
99b4732009-06-04Per Hedbor //#define FILE_STAT_CACHE
2f520e2002-04-28Martin Nilsson 
77e4f22002-07-09Martin Nilsson // This define is searched and replaced by bin/install.pike.
2f520e2002-04-28Martin Nilsson #undef PIKE_MODULE_RELOC #ifndef PIKE_WARNINGS
51a8f42002-05-15Henrik Grubbström (Grubba) #define PIKE_WARNINGS 1
2f520e2002-04-28Martin Nilsson #endif /* PIKE_WARNINGS */
d9786a2018-11-30William Welliver int want_load_announcements = 0; #define PROGRAM_LOADED(A,B,C) (want_load_announcements?(A[B]=program_loaded(B, (C))):(A[B]=(C)))
2f520e2002-04-28Martin Nilsson  // --- Global constants and variables
bec57d1999-09-06Fredrik Hübinette (Hubbe) 
c896b41998-04-29Henrik Grubbström (Grubba) // Used by describe_backtrace() et al. #if !defined(BT_MAX_STRING_LEN) || (BT_MAX_STRING_LEN <= 0) #undef BT_MAX_STRING_LEN
a858201999-10-15Fredrik Hübinette (Hubbe) #define BT_MAX_STRING_LEN 200
c896b41998-04-29Henrik Grubbström (Grubba) #endif /* !defined(BT_MAX_STRING_LEN) || (BT_MAX_STRING_LEN <= 0) */
d4fd0a1999-12-06Henrik Grubbström (Grubba) constant bt_max_string_len = BT_MAX_STRING_LEN;
6df5a52001-11-07Martin Nilsson //! @decl constant bt_max_string_len = 200
8a49852002-03-10Martin Stjernholm //! This constant contains the maximum length of a function entry in a //! backtrace. Defaults to 200 if no BT_MAX_STRING_LEN define has been
6df5a52001-11-07Martin Nilsson //! given.
97e5c72001-07-28Martin Nilsson 
401fa02002-12-02Martin Stjernholm // Enables the out of date warning in low_findprog().
e115cb1999-12-09Henrik Grubbström (Grubba) #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;
83ccb42004-04-11Henrik Grubbström (Grubba) // FIXME: PATH_SEPARATOR and UPDIR should probably be exported, // or at least some functions that use them should be. // cf Tools.Shoot.runpike. // /grubba 2004-04-11
12afb42018-01-12Stephen R. van den Berg #if defined(__NT__)
929cf72003-08-19Martin Nilsson #define PATH_SEPARATOR ";" #else #define PATH_SEPARATOR ":" #endif
61b41f2003-12-18Marcus Comstedt #define UPDIR "../"
6df5a52001-11-07Martin Nilsson //! @decl constant out_of_date_warning = 1 //! Should Pike complain about out of date compiled files. //! 1 means yes and 0 means no. Controlled by the OUT_OF_DATE_WARNING //! define.
97e5c72001-07-28Martin Nilsson 
2f520e2002-04-28Martin Nilsson //! If not zero compilation warnings will be written out on stderr. int want_warnings = PIKE_WARNINGS;
df2c632000-08-02Henrik Grubbström (Grubba) 
196b8e2017-12-04Henrik Grubbström (Grubba) //! Major pike version to emulate.
2f520e2002-04-28Martin Nilsson //!
196b8e2017-12-04Henrik Grubbström (Grubba) //! This is typically set via the option @expr{"-V"@}. //! //! @seealso //! @[compat_minor]
2f520e2002-04-28Martin Nilsson int compat_major=-1;
4839dd2001-09-02Marcus Comstedt 
196b8e2017-12-04Henrik Grubbström (Grubba) //! Minor pike version to emulate.
2f520e2002-04-28Martin Nilsson //!
196b8e2017-12-04Henrik Grubbström (Grubba) //! This is typically set via the option @expr{"-V"@}. //! //! @seealso //! @[compat_major]
2f520e2002-04-28Martin Nilsson int compat_minor=-1;
196b8e2017-12-04Henrik Grubbström (Grubba) //! Show compilation warnings from compilation of @[cpp()] //! @expr{#if constant()@} expressions.
f6da7b2004-06-27Martin Nilsson //!
196b8e2017-12-04Henrik Grubbström (Grubba) //! This is typically set via the option @expr{"--picky-cpp"@}.
f6da7b2004-06-27Martin Nilsson int show_if_constant_errors = 0;
2f520e2002-04-28Martin Nilsson 
b01e7e2010-07-29Martin Stjernholm int is_pike_master = 0; // This integer variable should exist in any object that aspires to be // the master. It gets set to 1 when the master is installed, and is // therefore set in any object that is or has been the master. That // makes the Encoder class encode references to the master and all // ex-masters as references to the current master object.
00f4802018-11-15William Welliver protected object debugger;
fba2e22014-12-05Bill Welliver mapping(string:object) fs_map = ([]); object root_fs;
2f520e2002-04-28Martin Nilsson // --- Functions begin here.
677d262003-11-14Martin Stjernholm // Have to access some stuff without going through the resolver.
7d016d2008-03-26Henrik Grubbström (Grubba) private object(_static_modules.Builtin) Builtin = _static_modules.Builtin();
59db4f2013-06-11Martin Nilsson private constant Files = _static_modules._Stdio;
677d262003-11-14Martin Stjernholm  #define Stat Files.Stat
2f520e2002-04-28Martin Nilsson #define capitalize(X) (upper_case((X)[..0])+(X)[1..])
8ff89d2016-07-04Martin Nilsson #define trim(X) (Builtin.string_trim (X))
c896b41998-04-29Henrik Grubbström (Grubba) 
d4140e2004-07-04Stephen R. van den Berg private function write = Files()->_stdout->write; private function werror = Files()->_stderr->write;
e3276e2004-07-04Stephen R. van den Berg 
6857b12008-10-12Martin Stjernholm // Tell Pike.count_memory this is global. constant pike_cycle_depth = 0;
0e22d12011-09-11Martin Stjernholm //#define RECUR_COMPILE_DEBUG // More brief than RESOLV_DEBUG. Usually enough to find those pesky // "Recursive module dependency" bugs. :P #if defined (RESOLV_DEBUG) || defined (RECUR_COMPILE_DEBUG)
3d21a62003-03-27Martin Stjernholm  #if constant (thread_local)
0e22d12011-09-11Martin Stjernholm protected object _msg_depth = thread_local();
97f8142003-09-18Henrik Grubbström (Grubba) // NOTE: May be used before __INIT has completed.
0e22d12011-09-11Martin Stjernholm #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))
3d21a62003-03-27Martin Stjernholm #else
0e22d12011-09-11Martin Stjernholm protected int _msg_depth; #define GET_MSG_DEPTH _msg_depth #define INC_MSG_DEPTH() (++_msg_depth) #define DEC_MSG_DEPTH() (--_msg_depth)
3d21a62003-03-27Martin Stjernholm #endif
0e22d12011-09-11Martin Stjernholm #endif #ifdef RESOLV_DEBUG #define GET_RESOLV_MSG_DEPTH GET_MSG_DEPTH
3054c02013-05-16Arne Goedeke #define INC_RESOLV_MSG_DEPTH() INC_MSG_DEPTH() #define DEC_RESOLV_MSG_DEPTH() DEC_MSG_DEPTH()
0e22d12011-09-11Martin Stjernholm 
075a2e2008-08-31Henrik Grubbström (Grubba) void resolv_debug (sprintf_format fmt, sprintf_args... args)
3d21a62003-03-27Martin Stjernholm { string pad = " " * GET_RESOLV_MSG_DEPTH; if (sizeof (args)) fmt = sprintf (fmt, @args); if (fmt[-1] == '\n')
35320b2004-10-30Martin Stjernholm  fmt = pad + replace (fmt[..<1], "\n", "\n" + pad) + "\n";
3d21a62003-03-27Martin Stjernholm  else fmt = pad + replace (fmt, "\n", "\n" + pad);
7749332004-12-27Henrik Grubbström (Grubba)  if (!werror) werror = Files()->_stderr->write;
3d21a62003-03-27Martin Stjernholm  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
075a2e2008-08-31Henrik Grubbström (Grubba) constant no_value = (<>); constant NoValue = typeof (no_value);
b784022008-05-28Henrik Grubbström (Grubba) // Some API compatibility stuff.
2fe88b2014-10-05Martin Nilsson //! Pike 7.8 master compatibility interface.
87ce122008-05-29Henrik Grubbström (Grubba) //!
4ee6a62008-09-13Henrik Grubbström (Grubba) //! Most of the interface is implemented via mixin, //! or overloading by more recent masters. //! //! This interface is used for compatibility with
2fe88b2014-10-05Martin Nilsson //! Pike 7.8.
87ce122008-05-29Henrik Grubbström (Grubba) //!
21c85e2008-06-01Henrik Grubbström (Grubba) //! @deprecated predef::MasterObject //!
87ce122008-05-29Henrik Grubbström (Grubba) //! @seealso
21c85e2008-06-01Henrik Grubbström (Grubba) //! @[get_compat_master()], @[master()], @[predef::MasterObject]
2fe88b2014-10-05Martin Nilsson protected class Pike_7_8_master
b784022008-05-28Henrik Grubbström (Grubba) {
87ce122008-05-29Henrik Grubbström (Grubba)  extern array(string) pike_include_path; extern array(string) pike_module_path; extern array(string) pike_program_path;
b784022008-05-28Henrik Grubbström (Grubba) #ifdef GETCWD_CACHE
87ce122008-05-29Henrik Grubbström (Grubba)  extern string current_path;
b784022008-05-28Henrik Grubbström (Grubba)  int cd(string s); string getcwd(); #endif string combine_path_with_cwd(string path); #ifdef FILE_STAT_CACHE
87ce122008-05-29Henrik Grubbström (Grubba)  extern int invalidate_time;
6f89182008-05-29Henrik Grubbström (Grubba)  extern mapping(string:multiset(string)) dir_cache;
0217a62009-06-10Henrik Grubbström (Grubba) #endif
fc2a322008-06-07Henrik Grubbström (Grubba) 
49c1bc2008-06-07Henrik Grubbström (Grubba)  string|mapping(string:string) getenv(string|void s); void putenv(string|void varname, string|void value);
b784022008-05-28Henrik Grubbström (Grubba)  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;
21c85e2008-06-01Henrik Grubbström (Grubba) 
87ce122008-05-29Henrik Grubbström (Grubba)  extern mapping(program:object) objects;
b784022008-05-28Henrik Grubbström (Grubba)  object cast_to_object(string oname, string current_file); class dirnode {};
87ce122008-05-29Henrik Grubbström (Grubba)  extern string _master_file_name;
b784022008-05-28Henrik Grubbström (Grubba)  void _main(array(string) orig_argv, array(string) env);
87ce122008-05-29Henrik Grubbström (Grubba)  extern mixed inhibit_compile_errors;
6f89182008-05-29Henrik Grubbström (Grubba)  void set_inhibit_compile_errors(mixed f);
b784022008-05-28Henrik Grubbström (Grubba)  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);
e3ba082008-09-14Henrik Grubbström (Grubba)  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);
b784022008-05-28Henrik Grubbström (Grubba)  class Codec {};
6f89182008-05-29Henrik Grubbström (Grubba)  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;
a41ee62008-09-14Henrik Grubbström (Grubba)  extern mapping(string:int) load_time;
6f89182008-05-29Henrik Grubbström (Grubba) #endif string master_read_file(); string normalize_path(string X);
a41ee62008-09-14Henrik Grubbström (Grubba)  array(string) query_precompiled_names(string fname);
6f89182008-05-29Henrik Grubbström (Grubba)  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);
067ddd2014-08-11Martin Nilsson  // ---
b784022008-05-28Henrik Grubbström (Grubba) 
6f89182008-05-29Henrik Grubbström (Grubba) #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);
e3d6bd2008-09-14Henrik Grubbström (Grubba)  extern multiset no_resolv; extern string ver; mapping get_default_module();
6f89182008-05-29Henrik Grubbström (Grubba)  void runtime_warning(string where, string what, mixed ... args);
35f51c2008-06-28Martin Nilsson  protected int clipped; protected int canclip; protected string stupid_describe(mixed m, int maxlen); protected string stupid_describe_comma_list(array x, int maxlen);
6f89182008-05-29Henrik Grubbström (Grubba)  class Describer {}; string describe_function(function f); class CompatResolver {};
075a2e2008-08-31Henrik Grubbström (Grubba)  int(0..1) asyncp();
6f89182008-05-29Henrik Grubbström (Grubba)  class Version {}; extern object currentversion; extern mapping(object:object) compat_handler_cache; object get_compilation_handler(int major, int minor);
e3d6bd2008-09-14Henrik Grubbström (Grubba) 
ec80082014-08-24Martin Nilsson  // ---
6f89182008-05-29Henrik Grubbström (Grubba) 
075a2e2008-08-31Henrik Grubbström (Grubba) #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;
05658f2008-09-14Henrik Grubbström (Grubba)  extern mapping(string:string) predefines;
abe9fe2014-09-18Martin Nilsson 
69fbcc2008-08-30Marcus Comstedt  void add_predefine (string name, string value); void remove_predefine (string name); mapping get_predefines();
075a2e2008-08-31Henrik Grubbström (Grubba) #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 {};
05658f2008-09-14Henrik Grubbström (Grubba)  extern mapping(string:Codec) codecs; Codec get_codec(string|void fname, int|void mkobj); // The following come from the inherit of Codec. */ // Codec::Encoder: extern mixed encoded; string|array nameof (mixed what, void|array(object) module_object); mixed encode_object(object x); // Codec::Decoder: 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);
075a2e2008-08-31Henrik Grubbström (Grubba)  string _sprintf(int t);
ec80082014-08-24Martin Nilsson 
abe9fe2014-09-18Martin Nilsson  // ---
7729db2010-11-19Henrik Grubbström (Grubba)  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);
2fe88b2014-10-05Martin Nilsson  local protected object Pike_7_8_compat_handler;
7729db2010-11-19Henrik Grubbström (Grubba)  local mixed resolv_or_error(string identifier, string|void current_file, void|object current_handler) {
2fe88b2014-10-05Martin Nilsson  if (!Pike_7_8_compat_handler) { Pike_7_8_compat_handler = global::get_compilation_handler(7, 8);
7729db2010-11-19Henrik Grubbström (Grubba)  }
2fe88b2014-10-05Martin Nilsson  return Pike_7_8_compat_handler->resolv_or_error(identifier, current_file,
7729db2010-11-19Henrik Grubbström (Grubba)  current_handler); }
6f89182008-05-29Henrik Grubbström (Grubba)  local mixed resolv(string identifier, string|void current_file) {
2fe88b2014-10-05Martin Nilsson  if (!Pike_7_8_compat_handler) { Pike_7_8_compat_handler = global::get_compilation_handler(7, 8);
6f89182008-05-29Henrik Grubbström (Grubba)  }
2fe88b2014-10-05Martin Nilsson  return Pike_7_8_compat_handler->resolv(identifier, current_file);
6f89182008-05-29Henrik Grubbström (Grubba)  }
b3926d2008-06-05Martin Stjernholm  array get_backtrace (object|array err);
6f89182008-05-29Henrik Grubbström (Grubba)  object get_compat_master(int major, int minor) {
2fe88b2014-10-05Martin Nilsson  // 0.0 .. 7.8 if (major < 8)
8e06a32014-09-30Martin Nilsson  return this::this;
4ee6a62008-09-13Henrik Grubbström (Grubba)  return get_compat_master(major, minor);
6f89182008-05-29Henrik Grubbström (Grubba)  }
7729db2010-11-19Henrik Grubbström (Grubba)  /* No missing symbols. */
6f89182008-05-29Henrik Grubbström (Grubba) }
2fe88b2014-10-05Martin Nilsson //! Pike 8.0 master compatibility interface.
0e26162010-12-23Henrik Grubbström (Grubba) //! //! Most of the interface is implemented via mixin, //! or overloading by more recent masters. //! //! This interface is used for compatibility with
2fe88b2014-10-05Martin Nilsson //! Pike 8.0.
0e26162010-12-23Henrik Grubbström (Grubba) //! //! @deprecated predef::MasterObject //! //! @seealso //! @[get_compat_master()], @[master()], @[predef::MasterObject]
2fe88b2014-10-05Martin Nilsson protected class Pike_8_0_master
0e26162010-12-23Henrik Grubbström (Grubba) {
2fe88b2014-10-05Martin Nilsson  inherit Pike_7_8_master;
0e26162010-12-23Henrik Grubbström (Grubba) 
2fe88b2014-10-05Martin Nilsson  local protected object Pike_8_0_compat_handler;
0e26162010-12-23Henrik Grubbström (Grubba)  local mixed resolv_or_error(string identifier, string|void current_file, void|object current_handler) {
2fe88b2014-10-05Martin Nilsson  if (!Pike_8_0_compat_handler) { Pike_8_0_compat_handler = global::get_compilation_handler(8, 0);
0e26162010-12-23Henrik Grubbström (Grubba)  }
2fe88b2014-10-05Martin Nilsson  return Pike_8_0_compat_handler->resolv_or_error(identifier, current_file,
0e26162010-12-23Henrik Grubbström (Grubba)  current_handler); } local mixed resolv(string identifier, string|void current_file) {
2fe88b2014-10-05Martin Nilsson  if (!Pike_8_0_compat_handler) { Pike_8_0_compat_handler = global::get_compilation_handler(8, 0);
0e26162010-12-23Henrik Grubbström (Grubba)  }
2fe88b2014-10-05Martin Nilsson  return Pike_8_0_compat_handler->resolv(identifier, current_file);
0e26162010-12-23Henrik Grubbström (Grubba)  } object get_compat_master(int major, int minor) {
2fe88b2014-10-05Martin Nilsson  if (major < 8) return Pike_7_8_master::get_compat_master(major, minor); // 8.0 if ((major == 8) && (minor < 1))
8e06a32014-09-30Martin Nilsson  return this::this;
0e26162010-12-23Henrik Grubbström (Grubba)  return get_compat_master(major, minor); } }
d5e23b2008-06-01Henrik Grubbström (Grubba) //! Namespaces for compat masters. //! //! This inherit is used to provide compatibility namespaces //! for @[get_compat_master()]. //! //! @seealso //! @[get_compat_master()]
2fe88b2014-10-05Martin Nilsson protected inherit Pike_8_0_master;
b784022008-05-28Henrik Grubbström (Grubba) 
59f9822018-02-08Henrik Grubbström (Grubba) //! @namespace predef::
01f7f32002-05-22Johan Sundström //! Throws an error. A more readable version of the code
e5ef062003-04-01Martin Nilsson //! @expr{throw( ({ sprintf(f, @@args), backtrace() }) )@}.
075a2e2008-08-31Henrik Grubbström (Grubba) void error(sprintf_format f, sprintf_args ... args) {
4f64a52002-05-22Martin Nilsson  if (sizeof(args)) f = sprintf(f, @args);
35320b2004-10-30Martin Stjernholm  throw( ({ f, backtrace()[..<1] }) );
4f64a52002-05-22Martin Nilsson }
6df5a52001-11-07Martin Nilsson // FIXME: Should the pikeroot-things be private?
26f3da2000-07-11Fredrik Hübinette (Hubbe) #ifdef PIKE_FAKEROOT object o; string fakeroot(string s) { string tmp1=combine_path_with_cwd(s); #ifdef PIKE_FAKEROOT_OMIT
929cf72003-08-19Martin Nilsson  foreach(PIKE_FAKEROOT_OMIT/PATH_SEPARATOR, string x)
26f3da2000-07-11Fredrik Hübinette (Hubbe)  if(glob(x,tmp1)) return s; #endif return PIKE_FAKEROOT+tmp1; } #else #define fakeroot(X) X
2f520e2002-04-28Martin Nilsson #endif // PIKE_FAKEROOT
26f3da2000-07-11Fredrik Hübinette (Hubbe) 
4839dd2001-09-02Marcus Comstedt #ifdef PIKE_MODULE_RELOC string relocate_module(string s) {
57b52d2003-05-31Martin Stjernholm  if(s == "/${PIKE_MODULE_PATH}" || has_prefix (s, "/${PIKE_MODULE_PATH}/")) {
4839dd2001-09-02Marcus Comstedt  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) {
57b52d2003-05-31Martin Stjernholm  if(s == "/${PIKE_MODULE_PATH}" || has_prefix (s, "/${PIKE_MODULE_PATH}/"))
4839dd2001-09-02Marcus Comstedt  return s; foreach(pike_module_path, string path) if(s == path) return "/${PIKE_MODULE_PATH}"; else {
57b52d2003-05-31Martin Stjernholm  path = combine_path(path, ""); if(has_prefix (s, path)) return "/${PIKE_MODULE_PATH}/"+s[sizeof(path)..];
4839dd2001-09-02Marcus Comstedt  }
57b52d2003-05-31Martin Stjernholm  /* This is necessary to find compat modules... */ foreach(pike_module_path, string path) {
61b41f2003-12-18Marcus Comstedt  path = combine_path(path, UPDIR, "");
57b52d2003-05-31Martin Stjernholm  if(has_prefix (s, path))
61b41f2003-12-18Marcus Comstedt  return "/${PIKE_MODULE_PATH}/"+UPDIR+s[sizeof(path)..];
57b52d2003-05-31Martin Stjernholm  }
4839dd2001-09-02Marcus Comstedt  return s; }
57b52d2003-05-31Martin Stjernholm 
4839dd2001-09-02Marcus Comstedt #ifdef fakeroot #undef fakeroot #endif #define fakeroot relocate_module
2f520e2002-04-28Martin Nilsson #endif // PIKE_MODULE_RELOC
4839dd2001-09-02Marcus Comstedt 
26f3da2000-07-11Fredrik Hübinette (Hubbe) 
8f45692001-01-14Henrik Grubbström (Grubba) //! Check if a path @[p] is fully qualified (ie not relative). //! //! @returns //! Returns 1 if the path is absolute, 0 otherwise.
ca2b071998-03-28Henrik Grubbström (Grubba) int is_absolute_path(string p) {
12afb42018-01-12Stephen R. van den Berg #if defined(__NT__)
ca2b071998-03-28Henrik Grubbström (Grubba)  p=replace(p,"\\","/");
e49e542001-01-22Fredrik Hübinette (Hubbe)  if(sscanf(p,"%[a-zA-Z]:%*c",string s)==2 && sizeof(s)==1)
ca2b071998-03-28Henrik Grubbström (Grubba)  return 1;
471ed91998-04-24Fredrik Hübinette (Hubbe) #define IS_ABSOLUTE_PATH is_absolute_path #else
39033d2003-04-10Martin Stjernholm #define IS_ABSOLUTE_PATH(X) has_prefix((X),"/")
ca2b071998-03-28Henrik Grubbström (Grubba) #endif
39033d2003-04-10Martin Stjernholm  return has_prefix(p,"/");
ca2b071998-03-28Henrik Grubbström (Grubba) }
12afb42018-01-12Stephen R. van den Berg #if defined(__NT__)
4619bd2002-07-29Martin Nilsson #define EXPLODE_PATH(X) (replace((X),"\\","/")/"/") #else #define EXPLODE_PATH(X) ((X)/"/") #endif
8f45692001-01-14Henrik Grubbström (Grubba) //! Split a path @[p] into its components. //! //! This function divides a path into its components. This might seem like //! it could be done by dividing the string on <tt>"/"</tt>, but that will
0dd3c22004-01-12Marcus Comstedt //! not work on some operating systems. To turn the components back into //! a path again, use @[combine_path()].
8f45692001-01-14Henrik Grubbström (Grubba) //!
bbf4702000-04-10Henrik Grubbström (Grubba) array(string) explode_path(string p)
ca2b071998-03-28Henrik Grubbström (Grubba) {
0dd3c22004-01-12Marcus Comstedt  array(string) r = EXPLODE_PATH(p); if(r[0] == "" && sizeof(p)) r[0] = "/"; return r;
ca2b071998-03-28Henrik Grubbström (Grubba) }
77e4f22002-07-09Martin Nilsson //! Returns all but the last segment of a path. Some example inputs and //! outputs: //! //! @xml{<matrix> //! <r><c><b>Expression</b></c><c><b>Value</b></c></r>
943ea82003-12-19Marcus Comstedt //! <r><c>dirname("/a/b")</c><c>"/a"</c></r> //! <r><c>dirname("/a/")</c><c>"/a"</c></r>
77e4f22002-07-09Martin Nilsson //! <r><c>dirname("/a")</c><c>"/"</c></r> //! <r><c>dirname("/")</c><c>"/"</c></r> //! <r><c>dirname("")</c><c>""</c></r> //! </matrix>@}
8f45692001-01-14Henrik Grubbström (Grubba) //! //! @seealso //! @[basename()], @[explode_path()]
ca2b071998-03-28Henrik Grubbström (Grubba) string dirname(string x) {
77e4f22002-07-09Martin Nilsson  if(x=="") return "";
aea4b42003-12-19Marcus Comstedt  array(string) tmp=x/":"; array(string) tmp2=tmp[-1]/"/";
35320b2004-10-30Martin Stjernholm  tmp[-1]=tmp2[..<1]*"/";
2510d42003-12-19Marcus Comstedt  if(sizeof(tmp2) >= 2 && tmp2[-2]=="") tmp[-1]+="/";
aea4b42003-12-19Marcus Comstedt  return tmp*":";
ca2b071998-03-28Henrik Grubbström (Grubba) }
8f45692001-01-14Henrik Grubbström (Grubba) //! Returns the last segment of a path. //! //! @seealso //! @[dirname()], @[explode_path()]
ca2b071998-03-28Henrik Grubbström (Grubba) string basename(string x) {
afa1292000-02-19Martin Nilsson  array(string) tmp=EXPLODE_PATH(x);
ca2b071998-03-28Henrik Grubbström (Grubba)  return tmp[-1];
471ed91998-04-24Fredrik Hübinette (Hubbe) #define BASENAME(X) (EXPLODE_PATH(X)[-1])
aea4b42003-12-19Marcus Comstedt }
ca2b071998-03-28Henrik Grubbström (Grubba) 
bec57d1999-09-06Fredrik Hübinette (Hubbe) #ifdef PIKE_AUTORELOAD int autoreload_on; int newest; #define AUTORELOAD_BEGIN() \ int ___newest=newest; \ newest=0
1a03e72005-11-09Henrik Grubbström (Grubba) #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)
e15f7f2009-04-25Martin Stjernholm #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)
57b52d2003-05-31Martin Stjernholm #define AUTORELOAD_FINISH(VAR, CACHE, FILE) \ if(autoreload_on) { \ mixed val = CACHE[FILE]; \
65340d2014-08-15Martin Nilsson  if(!undefinedp (val) && val != no_value && \
1a03e72005-11-09Henrik Grubbström (Grubba)  newest <= load_time[FILE]) { \
57b52d2003-05-31Martin Stjernholm  VAR = val; \ } \ } \
1a03e72005-11-09Henrik Grubbström (Grubba)  load_time[FILE] = newest; \
57b52d2003-05-31Martin Stjernholm  if(___newest > newest) newest=___newest;
bec57d1999-09-06Fredrik Hübinette (Hubbe)  mapping(string:int) load_time=([]); #else #define AUTORELOAD_CHECK_FILE(X) #define AUTORELOAD_BEGIN() #define AUTORELOAD_FINISH(VAR,CACHE,FILE)
2f520e2002-04-28Martin Nilsson #endif // PIKE_AUTORELOAD
a20af62000-09-26Fredrik Hübinette (Hubbe) 
8601232018-12-27Henrik Grubbström (Grubba) //!
0de46d2018-08-06Henrik Grubbström (Grubba) protected class CompilerEnvironment {
8601232018-12-27Henrik Grubbström (Grubba)  //!
0de46d2018-08-06Henrik Grubbström (Grubba)  inherit predef::CompilerEnvironment : OrigCompilerEnvironment;
8601232018-12-27Henrik Grubbström (Grubba)  //!
4b61e12018-10-05Henrik Grubbström (Grubba)  mixed resolv(string identifier, string filename, object|void handler, object|void compat_handler) { return master()->resolv(identifier, filename, handler, compat_handler); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
4b61e12018-10-05Henrik Grubbström (Grubba)  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); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
4b61e12018-10-05Henrik Grubbström (Grubba)  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); }
ad505d2018-08-12Henrik Grubbström (Grubba)  object get_compilation_handler(int major, int minor) { return master()->get_compilation_handler(major, minor); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
0de46d2018-08-06Henrik Grubbström (Grubba)  int compile_exception(mixed err) {
2c4fe52018-08-06Henrik Grubbström (Grubba)  function(mixed:int) fun = master()->compile_exception; return fun && fun(err);
0de46d2018-08-06Henrik Grubbström (Grubba)  }
8601232018-12-27Henrik Grubbström (Grubba)  //!
0de46d2018-08-06Henrik Grubbström (Grubba)  string format_exception(mixed err) { return 0; }
8601232018-12-27Henrik Grubbström (Grubba)  //!
0de46d2018-08-06Henrik Grubbström (Grubba)  class CPP {
8601232018-12-27Henrik Grubbström (Grubba)  //!
0de46d2018-08-06Henrik Grubbström (Grubba)  inherit ::this_program;
026fa32018-10-08Henrik Grubbström (Grubba) #if constant(_static_modules.Builtin.__HAVE_CPP_NO_HANDLERS__)
8601232018-12-27Henrik Grubbström (Grubba)  //!
026fa32018-10-08Henrik Grubbström (Grubba)  object handler; object compat_handler; #endif
8601232018-12-27Henrik Grubbström (Grubba)  //!
0de46d2018-08-06Henrik Grubbström (Grubba)  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); }
2d96302018-08-09Henrik Grubbström (Grubba)  //! @decl void report(SeverityLevel severity, @ //! string filename, int(1..) linenumber, @ //! string subsystem, @ //! sprintf_format message, sprintf_args ... extra_args) //! //! Report a diagnostic from the preprocessor. //! //! @param severity //! The severity of the diagnostic. //! //! @param filename //! @param linenumber //! Location which triggered the diagnostic. //! //! @param subsystem //! Typically @expr{"cpp"@}. //! //! @param message //! String with the diagnostic message, with optional //! @[sprintf()]-style formatting (if any @[extra_args]). //! //! @param extra_args //! Extra arguments to @[sprintf()]. //! //! The default implementation does the following: //! //! @ul //! @item //! If there's a handler which implements @[Reporter()->report()], //! call it with the same arguments. //! @item //! Otherwise if there's a handler which implements //! @[compile_warning()] or @[compile_error()] that matches //! @[severity], call it with suitable arguments. //! @item //! Otherwise if there's a compat handler, use it in the same //! manner as the handler. //! @item //! Otherwise fall back to calling @[::report()] with the //! same arguments. //! @endul //! //! @note //! In Pike 8.0 and earlier @[MasterObject()->report()] was not called. //! //! @seealso //! @[Reporter()->report()] 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); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
ad505d2018-08-12Henrik Grubbström (Grubba)  object get_compilation_handler(int major, int minor) { return apply_handler(__func__, major, minor); }
026fa32018-10-08Henrik Grubbström (Grubba) #if constant(_static_modules.Builtin.__HAVE_CPP_NO_HANDLERS__)
8601232018-12-27Henrik Grubbström (Grubba)  //!
026fa32018-10-08Henrik Grubbström (Grubba)  mapping(string:string|function|object) get_predefines() { return apply_handler(__func__); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
026fa32018-10-08Henrik Grubbström (Grubba)  mixed resolv(string sym) { return apply_handler(__func__, sym, current_file, handler, compat_handler); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
026fa32018-10-08Henrik Grubbström (Grubba)  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); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
026fa32018-10-08Henrik Grubbström (Grubba)  string read_include(string filename) { return apply_handler(__func__, filename); } string decode_charset(string data, string charset) { return apply_handler(__func__, data, charset); } #endif
a3ca4d2018-08-14Henrik Grubbström (Grubba)  string evaluate_define(string def, string|void arguments) { return apply_handler(__func__, def, arguments); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
ad505d2018-08-12Henrik Grubbström (Grubba)  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); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
0de46d2018-08-06Henrik Grubbström (Grubba)  int compile_exception(mixed err) { return apply_handler(__func__, err); }
8601232018-12-27Henrik Grubbström (Grubba)  //!
0de46d2018-08-06Henrik Grubbström (Grubba)  string format_exception(mixed err) { string ret = apply_handler(__func__, err); if (ret) return ret; if (compile_exception(err)) { return ""; } return 0; }
026fa32018-10-08Henrik Grubbström (Grubba)  #if constant(_static_modules.Builtin.__HAVE_CPP_NO_HANDLERS__)
40d6ca2018-12-29Henrik Grubbström (Grubba)  //! @decl 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) //! @decl void create(mapping(string:mixed) options) //! //! Initialize the preprocessor. //! //! @param options //! If the first argument is a mapping, no other arguments may follow. //! Instead, they have to be given as members of the mapping (if wanted). //! The following members are then recognized: //! //! @mapping //! @member string "current_file" //! Name of the current file. It is used for generating //! #line directives and for locating include files. //! @member int|string "charset" //! Charset to use when processing @expr{data@}. //! @member object "handler" //! Compilation handler. //! @member int "compat_major" //! Sets the major pike version used for compat handling. //! @member int "compat_minor" //! Sets the minor pike version used for compat handling. //! @member int "picky_cpp" //! Generate more warnings. //! @member int "keep_comments" //! This option keeps @[cpp()] from removing comments. //! Useful in combination with the prefix feature below. //! @member string "prefix" //! If a prefix is given, only prefixed directives will be //! processed. For example, if the prefix is @expr{"foo"@}, then //! @expr{#foo_ifdef COND@} and @expr{foo___LINE__@} would be //! processed, @expr{#ifdef COND@} and @expr{__LINE__@} //! would not. //! @endmapping //! //! @param current_file //! If the @[current_file] argument has not been specified, //! it will default to @expr{"-"@}. //! //! @param charset //! Turn on automatic character set detection if @expr{1@}, otherwise //! specifies the character set used by the input. //! Defaults to @expr{"ISO-10646"@}. //! //! @seealso //! @[compile()]
026fa32018-10-08Henrik Grubbström (Grubba)  protected void create(mapping(string:mixed) options) { // werror("CPP(%O)\n", 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
0de46d2018-08-06Henrik Grubbström (Grubba)  } } protected CompilerEnvironment DefaultCompilerEnvironment = CompilerEnvironment(); 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) {
68f9952018-08-07Henrik Grubbström (Grubba)  CompilerEnvironment.CPP cpp_obj = DefaultCompilerEnvironment->CPP(current_file, charset, handler || UNDEFINED, compat_major, compat_minor, picky_cpp); cpp_obj->init_pike_cpp();
a975cb2018-08-08Henrik Grubbström (Grubba)  return cpp_obj->high_cpp(data);
0de46d2018-08-06Henrik Grubbström (Grubba) }
56cd002001-10-28Martin Nilsson //! Compile the Pike code in the string @[source] into a program.
e5ef062003-04-01Martin Nilsson //! If @[filename] is not specified, it will default to @expr{"-"@}.
8f45692001-01-14Henrik Grubbström (Grubba) //!
e5ef062003-04-01Martin Nilsson //! Functionally equal to @expr{@[compile](@[cpp](@[source], @[filename]))@}.
8f45692001-01-14Henrik Grubbström (Grubba) //! //! @seealso //! @[compile()], @[cpp()], @[compile_file()] //! program compile_string(string source, void|string filename,
c2e10c2003-11-18Martin Stjernholm  object|void handler, void|program p,
f6da7b2004-06-27Martin Nilsson  void|object o, void|int _show_if_constant_errors)
ca2b071998-03-28Henrik Grubbström (Grubba) {
0e22d12011-09-11Martin Stjernholm #ifdef RECUR_COMPILE_DEBUG werror ("%*s>>> compile_string %O\n", GET_MSG_DEPTH, "", filename); INC_MSG_DEPTH(); #endif
9565132014-02-14Martin Nilsson  string code = cpp(source, filename||"-", 1, handler, compat_major, compat_minor,
65340d2014-08-15Martin Nilsson  (undefinedp(_show_if_constant_errors)?
9565132014-02-14Martin Nilsson  show_if_constant_errors: _show_if_constant_errors)); program ret; if(code) ret = compile(code, handler, compat_major, compat_minor, p, o);
b73c652007-06-13Martin Bähr  if (source_cache) source_cache[ret] = source;
0e22d12011-09-11Martin Stjernholm #ifdef RECUR_COMPILE_DEBUG DEC_MSG_DEPTH(); werror ("%*s<<< compile_string %O\n", GET_MSG_DEPTH, "", filename); #endif
6f46aa2007-06-12Martin Bähr  return ret;
ca2b071998-03-28Henrik Grubbström (Grubba) }
59f9822018-02-08Henrik Grubbström (Grubba) //! @endnamespace
9bc32d2017-12-05Henrik Grubbström (Grubba) //! Read a file from the master filesystem.
97e5c72001-07-28Martin Nilsson //!
9bc32d2017-12-05Henrik Grubbström (Grubba) //! The master filesystem defaults to the system filesystem, //! but additional mountpoints may be added via //! @[add_filesystem_handler()]. //! //! All file I/O performed by the @[MasterObject] is performed //! via this function and its related functions. //! //! @seealso //! @[add_filesystem_handler()], @[find_handler_for_path()], //! @[master_get_dir()], @[master_file_stat()]
d8a6fc2000-03-25Fredrik Hübinette (Hubbe) string master_read_file(string file) {
fba2e22014-12-05Bill Welliver  string x = find_handler_for_path(file); if(x) { object h = fs_map[x]; file = file[sizeof(x)+1..];
3524712015-05-26Martin Nilsson 
fba2e22014-12-05Bill Welliver  if(h = h->open(fakeroot(file),"r") ) { string q = ([function(void : string)]h->read)(); return q; }
3524712015-05-26Martin Nilsson  // TODO: should we be falling back here, or is this a hidden problem?
fba2e22014-12-05Bill Welliver  }
677d262003-11-14Martin Stjernholm  object o=Files()->Fd();
da24482002-05-24Martin Nilsson  if( ([function(string, string : int)]o->open)(fakeroot(file),"r") ) return ([function(void : string)]o->read)();
d8a6fc2000-03-25Fredrik Hübinette (Hubbe)  return 0; }
ca2b071998-03-28Henrik Grubbström (Grubba) #ifdef GETCWD_CACHE
35f51c2008-06-28Martin Nilsson protected string current_path;
ca2b071998-03-28Henrik Grubbström (Grubba) int cd(string s) { current_path=0; return predef::cd(s); } string getcwd() { return current_path || (current_path=predef::getcwd()); }
2f520e2002-04-28Martin Nilsson #endif // GETCWD_CACHE
ca2b071998-03-28Henrik Grubbström (Grubba) 
fba2e22014-12-05Bill Welliver constant high_master_get_dir = predef::get_dir;
15af9c2003-12-19Marcus Comstedt string combine_path_with_cwd(string ... paths)
ca2b071998-03-28Henrik Grubbström (Grubba) {
15af9c2003-12-19Marcus Comstedt  return combine_path(IS_ABSOLUTE_PATH(paths[0])?"":getcwd(),@paths);
ca2b071998-03-28Henrik Grubbström (Grubba) } #ifdef FILE_STAT_CACHE #define FILE_STAT_CACHE_TIME 20 int invalidate_time; mapping(string:multiset(string)) dir_cache = ([]);
8ac7b02004-12-26Per Hedbor 
7749332004-12-27Henrik Grubbström (Grubba) array(string) master_get_dir(string|void x)
8ac7b02004-12-26Per Hedbor {
3524712015-05-26Martin Nilsson  string y = find_handler_for_path(file);
fba2e22014-12-05Bill Welliver  if(y) { object h = fs_map[y]; x = x[sizeof(y)+1..]; return h->get_dir(x); } else return predef::get_dir(x);
8ac7b02004-12-26Per Hedbor }
61a4242000-08-27Mirar (Pontus Hagland) Stat master_file_stat(string x)
ca2b071998-03-28Henrik Grubbström (Grubba) {
fba2e22014-12-05Bill Welliver  object y = find_handler_for_path(file);
da24482002-05-24Martin Nilsson  string dir = combine_path_with_cwd(x); string file = BASENAME(dir); dir = dirname(dir);
ca2b071998-03-28Henrik Grubbström (Grubba)  if(time() > invalidate_time) {
da24482002-05-24Martin Nilsson  dir_cache = ([]); invalidate_time = time()+FILE_STAT_CACHE_TIME;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
da24482002-05-24Martin Nilsson  multiset(string) d = dir_cache[dir];
65340d2014-08-15Martin Nilsson  if( undefinedp(d) )
ca2b071998-03-28Henrik Grubbström (Grubba)  {
8ac7b02004-12-26Per Hedbor  array(string) tmp = master_get_dir(dir);
da24482002-05-24Martin Nilsson  if(tmp)
ca2b071998-03-28Henrik Grubbström (Grubba)  {
fc398b2001-05-31Fredrik Hübinette (Hubbe) #ifdef __NT__
da24482002-05-24Martin Nilsson  tmp = map(tmp, lower_case);
fc398b2001-05-31Fredrik Hübinette (Hubbe) #endif
99b4732009-06-04Per Hedbor  d = dir_cache[dir] = (multiset)tmp;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
da24482002-05-24Martin Nilsson  else dir_cache[dir]=0;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
eba0232004-01-13Martin Nilsson 
fc398b2001-05-31Fredrik Hübinette (Hubbe) #ifdef __NT__
da24482002-05-24Martin Nilsson  file = lower_case(file);
fc398b2001-05-31Fredrik Hübinette (Hubbe) #endif
ca2b071998-03-28Henrik Grubbström (Grubba)  if(d && !d[file]) return 0;
fba2e22014-12-05Bill Welliver  if(y) { object h = fs_map[y]; x = x[sizeof(y)+1..]; return h->stat(x); } else return predef::file_stat(x);
ca2b071998-03-28Henrik Grubbström (Grubba) } #else
fba2e22014-12-05Bill Welliver //constant master_file_stat = predef::file_stat; //constant master_get_dir = predef::get_dir; 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..];
3524712015-05-26Martin Nilsson 
fba2e22014-12-05Bill Welliver  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..];
3524712015-05-26Martin Nilsson  return h->get_dir(file);
fba2e22014-12-05Bill Welliver  } else return predef::get_dir(file); }
2f520e2002-04-28Martin Nilsson #endif // FILE_STAT_CACHE
ca2b071998-03-28Henrik Grubbström (Grubba) 
fba2e22014-12-05Bill Welliver //! mount a filesystem handler to be used by the resolver. on its own does noting, //! but may be used with @[add_module_path] and friends to enable modules to be loaded //! from Filesystem objects. //! //! @param mountpoint //! the location in the filesystem to mount the handler //! //! @param filesystem //! a filesystem object that will handle requests for the given mountpoint. //! //! @example //! master()->add_filesystem_handler("/foo/bar.zip", Filesystem.Zip("/foo/bar.zip")); //! master()->add_module_path("/foo/bar.zip/lib"); //!
9bc32d2017-12-05Henrik Grubbström (Grubba) //! @seealso //! @[find_handler_for_path()]
fba2e22014-12-05Bill Welliver mixed add_filesystem_handler(string mountpoint, object /*Filesystem.Base*/ filesystem) { mixed rv = fs_map[mountpoint]; fs_map[mountpoint] = filesystem; return rv; }
9bc32d2017-12-05Henrik Grubbström (Grubba) //! Return the mountpoint for the filesystem handler handling the //! @[file] (if any). //! //! @seealso //! @[add_filesystem_handler()]
fba2e22014-12-05Bill Welliver string find_handler_for_path(string file) { // TODO: maybe some caching would be worthwhile here. maybe. 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; }
3524712015-05-26Martin Nilsson 
fba2e22014-12-05Bill Welliver  return 0; }
b3926d2008-06-05Martin Stjernholm 
35f51c2008-06-28Martin Nilsson protected mapping(string:string) environment;
b3926d2008-06-05Martin Stjernholm  #ifdef __NT__
35f51c2008-06-28Martin Nilsson protected void set_lc_env (mapping(string:string) env)
b3926d2008-06-05Martin Stjernholm { environment = ([]); foreach (env; string var; string val) environment[lower_case (var)] = val; } #endif
59f9822018-02-08Henrik Grubbström (Grubba) //! @namespace predef::
b3926d2008-06-05Martin Stjernholm //! @decl mapping(string:string) getenv (void|int force_update)
43293b2002-12-30Henrik Grubbström (Grubba) //!
0866bf2013-06-16Henrik Grubbström (Grubba) //! Queries the environment variables. //! //! @param force_update //! A cached copy of the real environment is kept to make this //! function quicker. If the optional flag @[force_update] is nonzero //! then the real environment is queried and the cache is updated from //! it. That can be necessary if the environment changes through other //! means than @[putenv], typically from a C-level library.
43293b2002-12-30Henrik Grubbström (Grubba) //!
0866bf2013-06-16Henrik Grubbström (Grubba) //! @returns //! Returns the whole environment as a mapping. Destructive //! operations on the mapping will not affect the internal //! environment representation.
b3926d2008-06-05Martin Stjernholm //! //! Variable names and values cannot be wide strings nor contain //! @expr{'\0'@} characters. Variable names also cannot contain //! @expr{'='@} characters.
43293b2002-12-30Henrik Grubbström (Grubba) //! //! @note
b3926d2008-06-05Martin Stjernholm //! On NT the environment variable name is case insensitive.
5128432008-06-02Martin Stjernholm //!
b3926d2008-06-05Martin Stjernholm //! @seealso //! @[putenv()]
0866bf2013-06-16Henrik Grubbström (Grubba) mapping(string:string) getenv (void|int force_update)
b3926d2008-06-05Martin Stjernholm {
0866bf2013-06-16Henrik Grubbström (Grubba)  mapping(string:string) res;
b3926d2008-06-05Martin Stjernholm 
0866bf2013-06-16Henrik Grubbström (Grubba)  if (force_update) { res = Builtin._getenv();
b3926d2008-06-05Martin Stjernholm #ifdef __NT__
0866bf2013-06-16Henrik Grubbström (Grubba)  set_lc_env (res); #else environment = res + ([]);
b3926d2008-06-05Martin Stjernholm #endif
0866bf2013-06-16Henrik Grubbström (Grubba)  } else { #ifdef __NT__ // Can't use the cached environment since variable names have been // lowercased there. res = Builtin._getenv(); if (!environment) set_lc_env (res); #else if (!environment) environment = Builtin._getenv(); res = environment + ([]); #endif
b3926d2008-06-05Martin Stjernholm  }
0866bf2013-06-16Henrik Grubbström (Grubba)  return res; }
fc398b2001-05-31Fredrik Hübinette (Hubbe) 
0866bf2013-06-16Henrik Grubbström (Grubba) //! @decl string getenv (string varname, void|int force_update) //! //! Query the value of a specific environment variable. //! //! @param varname //! Environment variable to query. //! //! @param force_update //! A cached copy of the real environment is kept to make this //! function quicker. If the optional flag @[force_update] is nonzero //! then the real environment is queried and the cache is updated from //! it. That can be necessary if the environment changes through other //! means than @[putenv], typically from a C-level library. //! //! @returns //! Returns the value of the environment variable @[varname] //! if it exists, and @expr{0@} (zero) otherwise. //! //! Variable names and values cannot be wide strings nor contain //! @expr{'\0'@} characters. Variable names also cannot contain //! @expr{'='@} characters. //! //! @note //! On NT the environment variable name is case insensitive. //! //! @seealso //! @[putenv()] variant string getenv (string varname, void|int force_update) { if (!environment || force_update) {
b3926d2008-06-05Martin Stjernholm #ifdef __NT__
0866bf2013-06-16Henrik Grubbström (Grubba)  set_lc_env (Builtin._getenv());
b3926d2008-06-05Martin Stjernholm #else
0866bf2013-06-16Henrik Grubbström (Grubba)  environment = Builtin._getenv();
b3926d2008-06-05Martin Stjernholm #endif
0866bf2013-06-16Henrik Grubbström (Grubba)  }
b3926d2008-06-05Martin Stjernholm  #ifdef __NT__
0866bf2013-06-16Henrik Grubbström (Grubba)  varname = lower_case(varname);
b3926d2008-06-05Martin Stjernholm #endif
0866bf2013-06-16Henrik Grubbström (Grubba)  return environment[varname];
b3926d2008-06-05Martin Stjernholm } void putenv (string varname, void|string value) //! Sets the environment variable @[varname] to @[value].
8f45692001-01-14Henrik Grubbström (Grubba) //!
b3926d2008-06-05Martin Stjernholm //! If @[value] is omitted or zero, the environment variable
1ff0cb2008-06-10Martin Stjernholm //! @[varname] is removed.
8f45692001-01-14Henrik Grubbström (Grubba) //!
b3926d2008-06-05Martin Stjernholm //! @[varname] and @[value] cannot be wide strings nor contain //! @expr{'\0'@} characters. @[varname] also cannot contain //! @expr{'='@} characters.
8f45692001-01-14Henrik Grubbström (Grubba) //!
b3926d2008-06-05Martin Stjernholm //! @note //! On NT the environment variable name is case insensitive. //! //! @seealso //! @[getenv()]
a71f832001-11-13Tomas Nilsson //!
ca2b071998-03-28Henrik Grubbström (Grubba) {
b3926d2008-06-05Martin Stjernholm  Builtin._putenv (varname, value); if (environment) {
a71f832001-11-13Tomas Nilsson #ifdef __NT__
b3926d2008-06-05Martin Stjernholm  varname = lower_case (varname);
a71f832001-11-13Tomas Nilsson #endif
b3926d2008-06-05Martin Stjernholm  if (value) environment[varname] = value; else m_delete (environment, varname); }
df2c632000-08-02Henrik Grubbström (Grubba) }
fc398b2001-05-31Fredrik Hübinette (Hubbe)  //! Compile the Pike code contained in the file @[filename] into a program. //! //! This function will compile the file @[filename] to a Pike program that can //! later be instantiated. It is the same as doing
e5ef062003-04-01Martin Nilsson //! @expr{@[compile_string](@[Stdio.read_file](@[filename]), @[filename])@}.
fc398b2001-05-31Fredrik Hübinette (Hubbe) //! //! @seealso //! @[compile()], @[compile_string()], @[cpp()] //! program compile_file(string filename, object|void handler, void|program p, void|object o) { AUTORELOAD_CHECK_FILE(filename);
d04f8d2015-10-14Henrik Grubbström (Grubba)  string code = cpp(master_read_file(filename), filename, 1, handler, compat_major, compat_minor); if (!code) { error("Required feature missing.\n"); } return compile(code,
fc398b2001-05-31Fredrik Hübinette (Hubbe)  handler, compat_major, compat_minor, p, o); }
c57eda2001-08-29Martin Nilsson //! Replaces "\" with "/" if runing on MS Windows. It is
c2d49b2002-02-14Martin Nilsson //! adviced to use @[System.normalize_path] instead.
c57eda2001-08-29Martin Nilsson string normalize_path( string path )
4c3f7d2000-04-13Per Hedbor { #ifndef __NT__
c57eda2001-08-29Martin Nilsson  return path;
4c3f7d2000-04-13Per Hedbor #else
c57eda2001-08-29Martin Nilsson  return replace(path,"\\","/");
4c3f7d2000-04-13Per Hedbor #endif }
ca2b071998-03-28Henrik Grubbström (Grubba) 
59f9822018-02-08Henrik Grubbström (Grubba) //! @endnamespace
43293b2002-12-30Henrik Grubbström (Grubba) //! Mapping containing the cache of currently compiled files. //! //! This mapping currently has the following structure: //! @mapping //! @member program filename //! @endmapping
39979e2004-09-06Martin Stjernholm //! The filename path separator is / on both NT and UNIX.
43293b2002-12-30Henrik Grubbström (Grubba) //! //! @note
39979e2004-09-06Martin Stjernholm //! Special cases: The current master program is available under the //! name @expr{"/master"@}, and the program containing the @[main] //! function under @expr{"/main"@}.
e617062004-01-08Martin Nilsson mapping(string:program|NoValue) programs=(["/master":this_program]);
b73c652007-06-13Martin Bähr mapping(program:object) documentation = ([]); mapping(program:string) source_cache;
57b52d2003-05-31Martin Stjernholm  mapping (program:object|NoValue) objects=([
e617062004-01-08Martin Nilsson  this_program : this,
83da8e2008-05-14Henrik Grubbström (Grubba)  object_program(_static_modules): _static_modules,
57b52d2003-05-31Martin Stjernholm ]); mapping(string:object|NoValue) fc=([]); // Note: It's assumed that the mappings above never decrease in size
fb847c2004-06-17Martin Stjernholm // unless the reverse mappings above also are updated. no_value should // otherwise be used for entries that should be considered removed.
57b52d2003-05-31Martin Stjernholm  // The reverse mapping for objects isn't only for speed; search() // doesn't work reliably there since it calls `==.
35f51c2008-06-28Martin Nilsson protected mapping(program:string) rev_programs = ([]); protected mapping(object:program) rev_objects = ([]); protected mapping(mixed:string) rev_fc = ([]);
57b52d2003-05-31Martin Stjernholm  string programs_reverse_lookup (program prog) //! Returns the path for @[prog] in @[programs], if it got any. {
97f8142003-09-18Henrik Grubbström (Grubba)  // When running with trace, this function can get called // before __INIT has completed.
b2e9232016-09-19Henrik Grubbström (Grubba)  // NB: We need to be reasonably thread safe, as the compiler // may be running in another thread.
97f8142003-09-18Henrik Grubbström (Grubba)  if (!rev_programs) return UNDEFINED;
57b52d2003-05-31Martin Stjernholm  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)
1d918a2007-12-27Martin Nilsson //! Returns the program for @[obj], if known to the master.
57b52d2003-05-31Martin Stjernholm {
b2e9232016-09-19Henrik Grubbström (Grubba)  // NB: We need to be reasonably thread safe, as the compiler // may be running in another thread.
57b52d2003-05-31Martin Stjernholm  if (sizeof (rev_objects) < sizeof (objects)) { foreach (objects; program prog; object|NoValue obj) if (obj == no_value)
ca1e632005-11-14Martin Nilsson  m_delete (rev_objects, obj);
57b52d2003-05-31Martin Stjernholm  else rev_objects[obj] = prog; } return rev_objects[obj]; } string fc_reverse_lookup (object obj) //! Returns the path for @[obj] in @[fc], if it got any. { 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]; }
ca2b071998-03-28Henrik Grubbström (Grubba) 
6d926c1999-11-26Henrik Grubbström (Grubba) array(string) query_precompiled_names(string fname)
e15f7f2009-04-25Martin Stjernholm //! Returns identifiers (e.g. file names) of potentially precompiled //! files in priority order.
6d926c1999-11-26Henrik Grubbström (Grubba) {
8a49852002-03-10Martin Stjernholm #ifdef PRECOMPILED_SEARCH_MORE // Search for precompiled files in all module directories, not just // in the one where the source file is. This is useful when running // pike directly from the build directory. fname = fakeroot (fname); // FIXME: Not sure if this works correctly with the fakeroot and // module relocation stuff. foreach (pike_module_path, string path) if (has_prefix (fname, path)) return map (pike_module_path, `+, "/", fname[sizeof (path)..], ".o"); #endif
6d926c1999-11-26Henrik Grubbström (Grubba)  return ({ fname + ".o" }); }
e15f7f2009-04-25Martin Stjernholm int get_precompiled_mtime (string id) //! Given an identifier returned by query_precompiled_names, returns //! the mtime of the precompiled entry. Returns -1 if there is no //! entry. { Stat s = master_file_stat (fakeroot (id)); return s && s->isreg ? s->mtime : -1; } string read_precompiled (string id) //! Given an identifier returned by query_precompiled_names, returns //! the precompiled entry. Can assume the entry exists. { return master_read_file (id); }
35f51c2008-06-28Martin Nilsson protected class CompileCallbackError
677d262003-11-14Martin Stjernholm {
729acf2008-05-30Martin Stjernholm  inherit _static_modules.Builtin.GenericError;
677d262003-11-14Martin Stjernholm  constant is_generic_error = 1; constant is_compile_callback_error = 1;
729acf2008-05-30Martin Stjernholm  constant is_cpp_or_compilation_error = 1;
677d262003-11-14Martin Stjernholm }
35f51c2008-06-28Martin Nilsson protected void compile_cb_error (string msg, mixed ... args)
677d262003-11-14Martin Stjernholm // Use this to throw errors that should be converted to plain compile // error messages, without backtraces being reported by // compile_exception. { if (sizeof (args)) msg = sprintf (msg, @args);
35320b2004-10-30Martin Stjernholm  throw (CompileCallbackError (msg, backtrace()[..<1]));
677d262003-11-14Martin Stjernholm }
35f51c2008-06-28Martin Nilsson protected void compile_cb_rethrow (object|array err)
677d262003-11-14Martin Stjernholm // Use this to rethrow errors that should be converted to plain // compile error messages, without backtraces being reported by // compile_exception. { array bt; if (array|object e = catch (bt = get_backtrace (err))) handle_error (e);
86e66a2010-05-06Henrik Grubbström (Grubba)  throw (CompileCallbackError (call_describe_error (err), bt));
677d262003-11-14Martin Stjernholm }
35f51c2008-06-28Martin Nilsson protected void call_compile_warning (object handler, string file,
14cf192008-08-14Martin Stjernholm  string msg, mixed ... args)
677d262003-11-14Martin Stjernholm { if (sizeof (args)) msg = sprintf (msg, @args);
8ff89d2016-07-04Martin Nilsson  msg = trim (msg);
3e7cad2013-11-03Martin Nilsson  if (handler?->compile_warning)
677d262003-11-14Martin Stjernholm  handler->compile_warning (file, 0, msg);
ad356c2009-12-28Martin Stjernholm  else if (master()->compile_warning) master()->compile_warning (file, 0, msg);
677d262003-11-14Martin Stjernholm  else compile_warning (file, 0, msg); }
6330192000-02-10Fredrik Hübinette (Hubbe) #if constant(_static_modules.Builtin.mutex) #define THREADED #endif
61fdd72006-01-21Henrik Grubbström (Grubba) #ifdef __NT__ #define FIX_CASE(X) lower_case(X) #else #define FIX_CASE(X) (X) #endif /* __NT__ */
35f51c2008-06-28Martin Nilsson protected string base_from_filename(string fname)
61fdd72006-01-21Henrik Grubbström (Grubba) { string low_name = FIX_CASE(fname); if (has_prefix(low_name, ".#")) return 0; if (has_suffix(low_name, ".pike") || has_suffix(low_name, ".pmod")) {
8a531a2006-11-04Martin Nilsson  return fname[..<5];
61fdd72006-01-21Henrik Grubbström (Grubba)  } if (has_suffix(low_name, ".so")) {
8a531a2006-11-04Martin Nilsson  return fname[..<3];
61fdd72006-01-21Henrik Grubbström (Grubba)  } return 0; }
35f51c2008-06-28Martin Nilsson protected int prio_from_filename(string fname)
61fdd72006-01-21Henrik Grubbström (Grubba) { 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; // FIXME: Warn here? return 0; }
a5af872018-02-06Martin Nilsson 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; }
3524712015-05-26Martin Nilsson //! Find the files in which @[mod] is defined, as they may be hidden away in
0266592007-06-13Martin Bähr //! joinnodes and dirnodes //! //! @param mod //! The module we are looking for. //! //! @returns //! An array of strings with filenames. //! (one for each file in a joinnode, or just one otherwise)
1a84e52007-06-26Henrik Grubbström (Grubba) array(string) module_defined(object|program mod)
0266592007-06-13Martin Bähr { array files = ({});
1a84e52007-06-26Henrik Grubbström (Grubba)  if (programp(mod))
7d016d2008-03-26Henrik Grubbström (Grubba)  return ({ Builtin.program_defined([program]mod) });
9ef8fe2007-06-23Martin Bähr  array mods;
a5af872018-02-06Martin Nilsson  if (is_joinnode(mod))
3524712015-05-26Martin Nilsson  mods = mod->joined_modules;
0266592007-06-13Martin Bähr  else mods = ({ mod }); foreach (mods;; object mod)
6f46aa2007-06-12Martin Bähr  {
a5af872018-02-06Martin Nilsson  if (is_dirnode(mod))
7d016d2008-03-26Henrik Grubbström (Grubba)  files += ({ Builtin.program_defined(object_program(mod->module)) });
6f46aa2007-06-12Martin Bähr  else
7d016d2008-03-26Henrik Grubbström (Grubba)  files += ({ Builtin.program_defined(object_program(mod)) });
6f46aa2007-06-12Martin Bähr  }
0266592007-06-13Martin Bähr  return files;
c475882007-06-11Martin Bähr }
b73c652007-06-13Martin Bähr //! Enable caching of sources from compile_string() void enable_source_cache() {
64ec5b2007-06-13Martin Bähr  if (!source_cache) source_cache = ([]);
b73c652007-06-13Martin Bähr }
c475882007-06-11Martin Bähr //! Show documentation for the item @[obj] //! //! @param obj //! The object for which the documentation should be shown //! //! @returns //! an AutoDoc object object show_doc(program|object|function obj)
3524712015-05-26Martin Nilsson { object doc_extractor = main_resolv("Tools.AutoDoc.PikeExtractor.extractClass");
c475882007-06-11Martin Bähr  string child; program prog;
0266592007-06-13Martin Bähr 
c475882007-06-11Martin Bähr  if (programp(obj)) prog = obj; if (functionp(obj)) { prog = function_program(obj);
6f46aa2007-06-12Martin Bähr  child = ((describe_function(obj)||"")/"->")[-1];
c475882007-06-11Martin Bähr  } if (objectp(obj)) {
a5af872018-02-06Martin Nilsson  if (is_joinnode(obj))
c475882007-06-11Martin Bähr  obj = obj->joined_modules[0]; // FIXME: check for multiples
a5af872018-02-06Martin Nilsson  if (is_dirnode(obj))
c475882007-06-11Martin Bähr  prog = object_program(obj->module);
19d9422007-06-19Martin Bähr  else prog = object_program(obj);
c475882007-06-11Martin Bähr  }
0266592007-06-13Martin Bähr 
19d9422007-06-19Martin Bähr  if (prog && !documentation[prog] && doc_extractor)
c475882007-06-11Martin Bähr  {
b73c652007-06-13Martin Bähr  string source;
19d9422007-06-19Martin Bähr  if (source_cache && source_cache[prog])
b73c652007-06-13Martin Bähr  source = source_cache[prog];
19d9422007-06-19Martin Bähr  else
9ef8fe2007-06-23Martin Bähr  {
3524712015-05-26Martin Nilsson  array sourceref = array_sscanf(Builtin.program_defined(prog),
9ef8fe2007-06-23Martin Bähr  "%s%[:]%[0-9]"); source = master_read_file(sourceref[0]); if (sizeof(sourceref[1]) && sizeof(sourceref[2])) { if (programp(prog)) child = ((describe_program(prog)||"")/".")[-1]; } }
19d9422007-06-19Martin Bähr 
b73c652007-06-13Martin Bähr  if (source) { catch { documentation[prog] = doc_extractor(source, sprintf("%O", prog)); }; //FIXME: handle this error somehow }
c475882007-06-11Martin Bähr  }
0266592007-06-13Martin Bähr 
b73c652007-06-13Martin Bähr  if (documentation[prog])
3524712015-05-26Martin Nilsson  {
c475882007-06-11Martin Bähr  if (child)
9ef8fe2007-06-23Martin Bähr  return documentation[prog]->findObject(child)||documentation[prog]->findChild(child);
c475882007-06-11Martin Bähr  else
b73c652007-06-13Martin Bähr  return documentation[prog];
c475882007-06-11Martin Bähr  } }
86e66a2010-05-06Henrik Grubbström (Grubba) // Make it possible to customize the backtrace formatting. 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 /* object|array */ err) { return (all_constants()["describe_error"]||describe_error)(err); }
c475882007-06-11Martin Bähr 
35f51c2008-06-28Martin Nilsson protected program low_findprog(string pname,
14cf192008-08-14Martin Stjernholm  string ext, object|void handler, void|int mkobj)
ca2b071998-03-28Henrik Grubbström (Grubba) { program ret;
61a4242000-08-27Mirar (Pontus Hagland)  Stat s;
ca2b071998-03-28Henrik Grubbström (Grubba)  string fname=pname+ext;
bec57d1999-09-06Fredrik Hübinette (Hubbe) 
68b7a22003-09-19Henrik Grubbström (Grubba)  resolv_debug("low_findprog(%O, %O, %O, %O)\n", pname, ext, handler, mkobj);
4839dd2001-09-02Marcus Comstedt #ifdef PIKE_MODULE_RELOC fname = unrelocate_module(fname); #endif
41ee482000-02-28Fredrik Hübinette (Hubbe) #ifdef __NT__
aedfbc2004-01-12Martin Nilsson  // Ugly kluge to work better with cygwin32 "/X:/" paths.
41ee482000-02-28Fredrik Hübinette (Hubbe)  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
68065f2003-05-28Johan Sundström  if( (s=master_file_stat(fakeroot(fname))) && s->isreg )
ca2b071998-03-28Henrik Grubbström (Grubba)  {
1a03e72005-11-09Henrik Grubbström (Grubba) #ifdef PIKE_AUTORELOAD if(!autoreload_on || load_time[fname] >= s->mtime) #endif {
65340d2014-08-15Martin Nilsson  if(!undefinedp (ret=programs[fname]) && ret != no_value) {
1a03e72005-11-09Henrik Grubbström (Grubba)  resolv_debug ("low_findprog %s: returning cached (no autoreload)\n", fname); return ret; } }
bec57d1999-09-06Fredrik Hübinette (Hubbe)  AUTORELOAD_BEGIN();
14fc641999-11-26Henrik Grubbström (Grubba) 
6e2ebb1999-12-28Martin Stjernholm #ifdef PIKE_AUTORELOAD
1a03e72005-11-09Henrik Grubbström (Grubba)  if (load_time[fname] >= s->mtime)
65340d2014-08-15Martin Nilsson  if (!undefinedp (ret=programs[fname]) && ret != no_value) {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("low_findprog %s: returning cached (autoreload)\n", fname);
401fa02002-12-02Martin Stjernholm  return ret; }
6e2ebb1999-12-28Martin Stjernholm #endif
14fc641999-11-26Henrik Grubbström (Grubba) 
b2e9232016-09-19Henrik Grubbström (Grubba)  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; }
ca2b071998-03-28Henrik Grubbström (Grubba)  switch(ext) { case "": case ".pike":
6d926c1999-11-26Henrik Grubbström (Grubba)  foreach(query_precompiled_names(fname), string oname) {
e15f7f2009-04-25Martin Stjernholm  int o_mtime = get_precompiled_mtime (oname); if (o_mtime >= 0) { if (o_mtime >= s->mtime) {
6d926c1999-11-26Henrik Grubbström (Grubba)  mixed err=catch {
87ce122008-05-29Henrik Grubbström (Grubba)  object|program decoded;
e15f7f2009-04-25Martin Stjernholm  AUTORELOAD_CHECK_PRECOMPILED_FILE (oname);
3d21a62003-03-27Martin Stjernholm  resolv_debug ("low_findprog %s: decoding dumped\n", fname); INC_RESOLV_MSG_DEPTH();
e15f7f2009-04-25Martin Stjernholm  decoded = decode_value(read_precompiled (oname),
3e7cad2013-11-03Martin Nilsson  (handler?->get_codec ||
87ce122008-05-29Henrik Grubbström (Grubba)  get_codec)(fname, mkobj, handler));
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("low_findprog %s: dump decode ok\n", fname);
3e7cad2013-11-03Martin Nilsson  if (decoded?->this_program_does_not_exist) {
9d0e942005-04-15Henrik Grubbström (Grubba)  resolv_debug ("low_findprog %s: program claims not to exist\n", fname);
d9786a2018-11-30William Welliver  return PROGRAM_LOADED(programs, fname, 0);
9d0e942005-04-15Henrik Grubbström (Grubba)  } else {
87ce122008-05-29Henrik Grubbström (Grubba)  if (objectp(decoded)) { resolv_debug("low_findprog %s: decoded object %O\n", fname, decoded); objects[ret = object_program(decoded)] = decoded; } else { ret = decoded; }
9d0e942005-04-15Henrik Grubbström (Grubba)  resolv_debug("low_findprog %s: returning %O\n", fname, ret);
d9786a2018-11-30William Welliver  return PROGRAM_LOADED(programs, fname, ret);
9d0e942005-04-15Henrik Grubbström (Grubba)  }
6d926c1999-11-26Henrik Grubbström (Grubba)  };
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("low_findprog %s: dump decode failed\n", fname);
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, fname, no_value);
677d262003-11-14Martin Stjernholm  call_compile_warning (handler, oname,
86e66a2010-05-06Henrik Grubbström (Grubba)  "Decode failed: " + call_describe_error(err));
3abf3f2008-05-26Henrik Grubbström (Grubba)  // handle_error(err);
e115cb1999-12-09Henrik Grubbström (Grubba)  } else if (out_of_date_warning) {
677d262003-11-14Martin Stjernholm  call_compile_warning (handler, oname, "Compiled file is out of date");
10e16f1999-11-04Henrik Grubbström (Grubba)  }
b085961998-05-19Fredrik Hübinette (Hubbe)  }
471ed91998-04-24Fredrik Hübinette (Hubbe)  }
eba0232004-01-13Martin Nilsson 
3d21a62003-03-27Martin Stjernholm  resolv_debug ("low_findprog %s: compiling, mkobj: %O\n", fname, mkobj); INC_RESOLV_MSG_DEPTH();
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, fname, ret=__empty_program(0, fname));
c2e10c2003-11-18Martin Stjernholm  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;
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, fname, ret=0); // Negative cache.
c2e10c2003-11-18Martin Stjernholm  compile_cb_rethrow (err); }
aa68b12001-03-19Fredrik Hübinette (Hubbe)  if ( mixed e=catch {
c2e10c2003-11-18Martin Stjernholm  ret=compile_string(src, fname, handler, ret, mkobj? (objects[ret]=__null_program()) : 0); } )
ca2b071998-03-28Henrik Grubbström (Grubba)  {
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("low_findprog %s: compilation failed\n", fname);
57b52d2003-05-31Martin Stjernholm  objects[ret] = no_value;
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, fname, ret=0); // Negative cache.
0df7702016-09-16Henrik Grubbström (Grubba)  destruct(compiler_lock);
c46d682000-01-05Martin Stjernholm  throw(e);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
0df7702016-09-16Henrik Grubbström (Grubba)  destruct(compiler_lock);
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("low_findprog %s: compilation ok\n", fname);
ca2b071998-03-28Henrik Grubbström (Grubba)  break;
20b5222004-03-22Martin Stjernholm 
ca2b071998-03-28Henrik Grubbström (Grubba) #if constant(load_module) case ".so":
caa3221998-04-15Henrik Grubbström (Grubba)  if (fname == "") {
20b5222004-03-22Martin Stjernholm  werror( "low_findprog(%O, %O) => load_module(\"\")\n"
86e66a2010-05-06Henrik Grubbström (Grubba)  "%s\n", pname, ext, call_describe_backtrace(backtrace()) );
caa3221998-04-15Henrik Grubbström (Grubba)  }
26f3da2000-07-11Fredrik Hübinette (Hubbe) 
c2e10c2003-11-18Martin Stjernholm  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;
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, fname, ret=0); // Negative cache.
d58c972004-04-18Martin Stjernholm  if (objectp (err) && err->is_module_load_error)
20b5222004-03-22Martin Stjernholm  // Do not treat errors from dlopen(3) as exceptions since in // a dist we can have .so files that are dynamically linked // against libraries that don't exist on the system, and in // that case we should just treat the module as nonexisting. // // What we really want is to do this only for errors that // are due to nonexisting files, but the error reporting // from dlerror(3) doesn't allow us to tell those from other // errors. call_compile_warning (handler, fname,
d58c972004-04-18Martin Stjernholm  "Failed to load library: %s\n", err->reason);
20b5222004-03-22Martin Stjernholm  else compile_cb_rethrow (err);
c2e10c2003-11-18Martin Stjernholm  }
20b5222004-03-22Martin Stjernholm  else resolv_debug ("low_findprog %s: loaded binary\n", fname);
ca2b071998-03-28Henrik Grubbström (Grubba) #endif /* load_module */ }
bec57d1999-09-06Fredrik Hübinette (Hubbe)  AUTORELOAD_FINISH(ret,programs,fname);
6e2ebb1999-12-28Martin Stjernholm 
3e7cad2013-11-03Martin Nilsson  if (ret?->this_program_does_not_exist) {
0453bf2004-03-22Martin Stjernholm  resolv_debug ("low_findprog %s: program says it doesn't exist\n", fname);
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, fname, ret=0); return ret;
0453bf2004-03-22Martin Stjernholm  } else {
9565132014-02-14Martin Nilsson  if(!ret)
0237982014-02-15Martin Nilsson  resolv_debug("low_findprog %s: dependencies failed.\n", fname);
9565132014-02-14Martin Nilsson  else resolv_debug("low_findprog %s: returning %O\n", fname, ret);
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, fname, ret); return ret;
0453bf2004-03-22Martin Stjernholm  }
ca2b071998-03-28Henrik Grubbström (Grubba)  }
0453bf2004-03-22Martin Stjernholm 
3d21a62003-03-27Martin Stjernholm  resolv_debug ("low_findprog %s: file not found\n", fname);
6e2ebb1999-12-28Martin Stjernholm  return 0;
ca2b071998-03-28Henrik Grubbström (Grubba) }
eaa4da2001-10-04Fredrik Hübinette (Hubbe) //
a002d32002-03-01Martin Stjernholm // This function is called by the compiler when a delayed compilation // error occurs in the given program. It should remove all references // to the program so that it can be freed.
eaa4da2001-10-04Fredrik Hübinette (Hubbe) // void unregister(program p) {
87ce122008-05-29Henrik Grubbström (Grubba)  // werror("Unregistering %O...\n", p);
b2e9232016-09-19Henrik Grubbström (Grubba)  object compiler_lock = DefaultCompilerEnvironment->lock();
fb847c2004-06-17Martin Stjernholm  if(string fname=rev_programs[p] || search(programs,p)) {
3593292003-09-08Henrik Grubbström (Grubba)  resolv_debug("unregister %s\n", fname);
fb847c2004-06-17Martin Stjernholm  if (m_delete (rev_programs, p)) m_delete (programs, fname); else
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, fname, no_value);
fb847c2004-06-17Martin Stjernholm 
548e832011-03-13Martin Stjernholm  string name = program_path_to_name (fname);
567f922016-09-12Martin Nilsson  mixed n = has_value (name, '.') ?
548e832011-03-13Martin Stjernholm  resolv ((name / ".")[..<1] * ".") : get_root_module();
a5af872018-02-06Martin Nilsson  if (is_dirnode(n) || is_joinnode(n))
548e832011-03-13Martin Stjernholm  n->delete_value (p);
a002d32002-03-01Martin Stjernholm  fname = dirname (fname);
57b52d2003-05-31Martin Stjernholm  if ( fname!="" && objectp (n = fc[fname]) )
a5af872018-02-06Martin Nilsson  if (is_dirnode(n)) // Won't find joinnodes in fc.
1997b32005-07-13Henrik Grubbström (Grubba)  n->delete_value (p);
a002d32002-03-01Martin Stjernholm  }
fb847c2004-06-17Martin Stjernholm 
87ce122008-05-29Henrik Grubbström (Grubba)  object o = m_delete(objects, p);
fb847c2004-06-17Martin Stjernholm  if (objectp (o)) {
87ce122008-05-29Henrik Grubbström (Grubba)  m_delete(rev_objects, o);
fb847c2004-06-17Martin Stjernholm  }
c6cf602001-12-13Martin Stjernholm  foreach (fc; string name; mixed mod) if (objectp(mod) && object_program(mod) == p)
fb847c2004-06-17Martin Stjernholm  if (m_delete (rev_fc, mod)) m_delete (fc, name); else fc[name] = no_value;
14cf192008-08-14Martin Stjernholm 
548e832011-03-13Martin Stjernholm  // FIXME: What about compat handlers?
eaa4da2001-10-04Fredrik Hübinette (Hubbe) }
35f51c2008-06-28Martin Nilsson protected program findprog(string pname,
14cf192008-08-14Martin Stjernholm  string ext, object|void handler, void|int mkobj)
ca2b071998-03-28Henrik Grubbström (Grubba) { switch(ext) { case ".pike": case ".so":
aa68b12001-03-19Fredrik Hübinette (Hubbe)  return low_findprog(pname,ext,handler, mkobj);
ca2b071998-03-28Henrik Grubbström (Grubba)  default: pname+=ext; return
aa68b12001-03-19Fredrik Hübinette (Hubbe)  low_findprog(pname,"", handler, mkobj) || low_findprog(pname,".pike", handler, mkobj) || low_findprog(pname,".so", handler, mkobj);
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
aa68b12001-03-19Fredrik Hübinette (Hubbe) program low_cast_to_program(string pname, string current_file, object|void handler, void|int mkobj)
ca2b071998-03-28Henrik Grubbström (Grubba) { string ext; string nname;
7d016d2008-03-26Henrik Grubbström (Grubba)  //werror("low_cast_to_program(%O, %O, %O, %O)\n", // pname, current_file, handler, mkobj);
34241f2001-05-24Henrik Grubbström (Grubba) 
15af9c2003-12-19Marcus Comstedt  if(sscanf(reverse(BASENAME(pname)),"%s.%s",ext, nname))
ca2b071998-03-28Henrik Grubbström (Grubba)  { ext="."+reverse(ext);
35320b2004-10-30Martin Stjernholm  pname=pname[..<sizeof(ext)];
2f520e2002-04-28Martin Nilsson  } else {
ca2b071998-03-28Henrik Grubbström (Grubba)  ext=""; }
2f520e2002-04-28Martin Nilsson 
b2e9232016-09-19Henrik Grubbström (Grubba)  // NB: No need to lock the compiler here; findprog() will // lock and reprobe on miss in the programs mapping.
471ed91998-04-24Fredrik Hübinette (Hubbe)  if(IS_ABSOLUTE_PATH(pname))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
57b52d2003-05-31Martin Stjernholm  program|NoValue prog = programs[pname];
65340d2014-08-15Martin Nilsson  if ((!undefinedp(prog)) && (prog != no_value))
3524712015-05-26Martin Nilsson  {
c475882007-06-11Martin Bähr  return prog; }
61b41f2003-12-18Marcus Comstedt  pname=combine_path("",pname);
aa68b12001-03-19Fredrik Hübinette (Hubbe)  return findprog(pname,ext,handler,mkobj);
2f520e2002-04-28Martin Nilsson  } else {
ca2b071998-03-28Henrik Grubbström (Grubba)  string cwd; if(current_file) {
2f520e2002-04-28Martin Nilsson  cwd=dirname(current_file); } else {
ca2b071998-03-28Henrik Grubbström (Grubba)  cwd=getcwd(); }
aa68b12001-03-19Fredrik Hübinette (Hubbe)  if(program ret=findprog(combine_path(cwd,pname),ext,handler,mkobj))
ca2b071998-03-28Henrik Grubbström (Grubba)  return ret; foreach(pike_program_path, string path)
aa68b12001-03-19Fredrik Hübinette (Hubbe)  if(program ret=findprog(combine_path(path,pname),ext,handler,mkobj))
ca2b071998-03-28Henrik Grubbström (Grubba)  return ret; return 0; } }
aa68b12001-03-19Fredrik Hübinette (Hubbe) 
97e5c72001-07-28Martin Nilsson //! This function is called when the driver wants to cast a string //! to a program, this might be because of an explicit cast, an inherit //! or a implict cast. In the future it might receive more arguments, //! to aid the master finding the right program.
aa68b12001-03-19Fredrik Hübinette (Hubbe) program cast_to_program(string pname,
3524712015-05-26Martin Nilsson  string current_file,
aa68b12001-03-19Fredrik Hübinette (Hubbe)  object|void handler) {
3d21a62003-03-27Martin Stjernholm  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);
677d262003-11-14Martin Stjernholm  if (programp (ret)) return ret; error("Cast %O to program failed%s.\n", pname, (current_file && current_file!="-") ? sprintf(" in %O",current_file) : "");
aa68b12001-03-19Fredrik Hübinette (Hubbe) }
4f8b1f2013-06-28Henrik Grubbström (Grubba) protected string narrowify_string(string s) { if (Builtin.string_width(s) <= 8) return s; // Perform Unicode escaping. 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); }) * ""; }
97e5c72001-07-28Martin Nilsson //! This function is called when an error occurs that is not caught //! with catch().
aa84102003-12-06Martin Nilsson void handle_error(array|object trace)
ca2b071998-03-28Henrik Grubbström (Grubba) {
9d0e942005-04-15Henrik Grubbström (Grubba)  // NB: Use predef::trace() to modify trace level here. // predef::trace(2);
62e87b1998-04-14Fredrik Hübinette (Hubbe)  if(mixed x=catch {
86e66a2010-05-06Henrik Grubbström (Grubba)  werror(call_describe_backtrace(trace));
d28a712001-07-02Henrik Grubbström (Grubba)  }) {
9f71092000-11-20Martin Stjernholm  // One reason for this might be too little stack space, which // easily can occur for "out of stack" errors. It should help to // tune up the STACK_MARGIN values in interpret.c then.
62e87b1998-04-14Fredrik Hübinette (Hubbe)  werror("Error in handle_error in master object:\n");
9f71092000-11-20Martin Stjernholm  if(catch {
9d0e942005-04-15Henrik Grubbström (Grubba)  // NB: Splited werror calls to retain some information // even if/when werror throws.
d28a712001-07-02Henrik Grubbström (Grubba)  catch { if (catch {
da24482002-05-24Martin Nilsson  string msg = [string]x[0]; array bt = [array]x[1];
4f8b1f2013-06-28Henrik Grubbström (Grubba)  werror("%s", narrowify_string(msg)); werror(narrowify_string(sprintf("%O\n", bt)));
d28a712001-07-02Henrik Grubbström (Grubba)  }) {
4f8b1f2013-06-28Henrik Grubbström (Grubba)  werror(narrowify_string(sprintf("%O\n", x)));
d28a712001-07-02Henrik Grubbström (Grubba)  } };
4f8b1f2013-06-28Henrik Grubbström (Grubba)  werror(narrowify_string(sprintf("Original error:\n" "%O\n", trace)));
aa73fc1999-10-21Fredrik Hübinette (Hubbe)  }) { werror("sprintf() failed to write error.\n"); }
62e87b1998-04-14Fredrik Hübinette (Hubbe)  }
9d0e942005-04-15Henrik Grubbström (Grubba)  // predef::trace(0);
ca2b071998-03-28Henrik Grubbström (Grubba) }
6155402018-06-01Henrik Grubbström (Grubba) //! This function is called in runtime check_types mode (@tt{-rt@}), //! when encountering a soft cast to an attributed type. //! //! @param value //! Value that is about to receive the attribute. //! //! @param attribute //! Type attribute to validate. //! //! @returns //! Returns one of: //! @int //! @value 1 //! If the attribute is valid for the value. //! @value 0 //! If the attribute is not valid for the value. //! @value UNDEFINED //! If the attribute is unsupported. //! @endint //! //! The default master implements validation of the @expr{"utf8"@} //! attribute. 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; }
c5cc2d1998-04-29Henrik Grubbström (Grubba) /* This array contains the names of the functions * that a replacing master-object may want to override. */ constant master_efuns = ({
4f64a52002-05-22Martin Nilsson  "error",
c5cc2d1998-04-29Henrik Grubbström (Grubba)  "basename", "dirname", "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",
a66ff22000-01-11Martin Stjernholm  "describe_error",
677d262003-11-14Martin Stjernholm  "get_backtrace",
4c3f7d2000-04-13Per Hedbor  "normalize_path",
fb2dc02005-03-14Per Hedbor  "true", "false",
c5cc2d1998-04-29Henrik Grubbström (Grubba)  "getenv", "putenv", #ifdef GETCWD_CACHE "cd", "getcwd", #endif });
901ce22008-06-29Marcus Agehall //! Prefix for Pike-related C header files.
28c5382002-09-09Marcus Comstedt string include_prefix;
e54fbc2006-04-22Henrik Grubbström (Grubba) //! Prefix for autodoc files. string doc_prefix;
116cf52008-06-29Marcus Agehall //! Flags suitable for use when compiling Pike C modules string cflags; //! Flags suitable for use when linking Pike C modules
901ce22008-06-29Marcus Agehall string ldflags; // Not yet used
7a90f12003-01-26Martin Nilsson 
59f9822018-02-08Henrik Grubbström (Grubba) //! @namespace predef:: //! //! This is the default namespace and contains lots of global symbols.
97a1522017-03-17Henrik Grubbström (Grubba) //! Boolean datatype. enum bool { false=0, true=1 };
e378192003-01-20Martin Nilsson 
7a90f12003-01-26Martin Nilsson //! @decl int write(string fmt, mixed ... args)
e378192003-01-20Martin Nilsson //! Writes a string on stdout. Works just like @[Stdio.File.write] //! on @[Stdio.stdout].
d4140e2004-07-04Stephen R. van den Berg //! @decl int werror(string fmt, mixed ... args) //! Writes a string on stderr. Works just like @[Stdio.File.write] //! on @[Stdio.stderr].
97a1522017-03-17Henrik Grubbström (Grubba) //! @decl array random(mapping m) //! @decl float random(float max) //! @decl int random(int max) //! @decl mixed random(object o) //! @decl mixed random(array|multiset x) //! //! Get a random value generated by the default @[RandomSystem]. //! //! @seealso //! @[RandomSystem()->random()], @[random_string()] //! @decl string random_string(int len) //! //! Get a string of random characters @expr{0..255@} with the length @[len] //! from the default @[RandomSystem]. //! //! @seealso //! @[RandomSystem()->random_string()], @[random()]
76dc182018-02-09Martin Nilsson //! @decl int cp(string from, string to) //! //! Copies the file @[from] to the new position @[to]. This is an //! alias for @[Stdio.cp].
ca2b071998-03-28Henrik Grubbström (Grubba) /* Note that create is called before add_precompiled_program */
35f51c2008-06-28Martin Nilsson protected void create()
ca2b071998-03-28Henrik Grubbström (Grubba) {
0de46d2018-08-06Henrik Grubbström (Grubba)  add_constant("CompilerEnvironment", CompilerEnvironment); add_constant("DefaultCompilerEnvironment", DefaultCompilerEnvironment); add_constant("cpp", cpp);
9066122002-11-28Martin Nilsson  foreach(master_efuns, string e)
65340d2014-08-15Martin Nilsson  if (has_index(this, e))
e617062004-01-08Martin Nilsson  add_constant(e, this[e]);
9066122002-11-28Martin Nilsson  else error("Function %O is missing from master.pike.\n", e);
c5cc2d1998-04-29Henrik Grubbström (Grubba) 
43fe472016-01-04Per Hedbor 
52a0b12016-05-08Henrik Grubbström (Grubba) // This gives the type int(0..1), which is more close to reality
43fe472016-01-04Per Hedbor // than the enum type (aka int(1..1)) // // doing the add_constant on the typeof directly gives int(1..1) // instead, since the same "optimization" of the type is done in that // case.
52a0b12016-05-08Henrik Grubbström (Grubba)  add_constant("bool", typeof([int(0..1)](mixed)0));
43fe472016-01-04Per Hedbor 
1554cc2007-09-03Henrik Grubbström (Grubba)  add_constant("__dirnode", dirnode); add_constant("__joinnode", joinnode);
7c386d2018-12-08Marcus Comstedt  werror = locale_werror;
d4140e2004-07-04Stephen R. van den Berg  add_constant("write", write); add_constant("werror", werror);
b85b132004-12-26Per Hedbor  // To make it possible to overload get_dir and file_stat later on. // It's not possible to replace efuns with normal functions in .o-files
fba2e22014-12-05Bill Welliver  add_constant("get_dir", high_master_get_dir );
b85b132004-12-26Per Hedbor  add_constant("file_stat", lambda( string f, int|void d ) { return file_stat(f,d);} );
ca2b071998-03-28Henrik Grubbström (Grubba) 
2064412016-01-17Martin Nilsson  object rnd = Builtin.RandomSystem(); add_constant("random", rnd->random); add_constant("random_string", rnd->random_string);
677d262003-11-14Martin Stjernholm #define CO(X) add_constant(#X,Builtin.__backend->X)
87f9082001-03-12Fredrik Hübinette (Hubbe)  CO(call_out); CO(_do_call_outs); CO(find_call_out); CO(remove_call_out); CO(call_out_info);
5667ee2009-03-05Henrik Grubbström (Grubba) #if "#share_prefix#"[0]!='#'
2d8c832003-08-11Henrik Grubbström (Grubba)  // add path for architecture-independant files
5667ee2009-03-05Henrik Grubbström (Grubba)  add_include_path("#share_prefix#/include"); add_module_path("#share_prefix#/modules");
e37a3e1999-10-09Fredrik Hübinette (Hubbe) #endif
5667ee2009-03-05Henrik Grubbström (Grubba) #if "#lib_prefix#"[0]!='#'
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  // add path for architecture-dependant files
5667ee2009-03-05Henrik Grubbström (Grubba)  add_include_path("#lib_prefix#/include"); add_module_path("#lib_prefix#/modules");
e37a3e1999-10-09Fredrik Hübinette (Hubbe) #endif
28c5382002-09-09Marcus Comstedt 
5667ee2009-03-05Henrik Grubbström (Grubba) #if "#cflags# "[0]!='#' cflags = "#cflags#";
901ce22008-06-29Marcus Agehall #endif
5667ee2009-03-05Henrik Grubbström (Grubba) #if "#ldflags# "[0]!='#' ldflags = "#ldflags#";
901ce22008-06-29Marcus Agehall #endif
5667ee2009-03-05Henrik Grubbström (Grubba) #if "#include_prefix#"[0]!='#' include_prefix = "#include_prefix#";
907cf82008-06-29Marcus Agehall  cflags = (cflags || "") + " -I" + dirname(include_prefix);
e54fbc2006-04-22Henrik Grubbström (Grubba) #endif
901ce22008-06-29Marcus Agehall 
5667ee2009-03-05Henrik Grubbström (Grubba) #if "#doc_prefix#"[0]!='#' doc_prefix = "#doc_prefix#";
28c5382002-09-09Marcus Comstedt #endif
110ff82007-01-24H. William Welliver III  #if constant(__embedded_resource_directory) // for use with embedded interpreters // add path for architecture-dependant files add_include_path(__embedded_resource_directory + "/lib/include"); add_module_path(__embedded_resource_directory + "/lib/modules");
98ed482007-07-31H. William Welliver III  add_module_path(__embedded_resource_directory + "/" + replace(uname()->machine, " ", "_") + "/modules");
110ff82007-01-24H. William Welliver III #endif
0418252003-10-30H. William Welliver III  system_module_path=pike_module_path;
ca2b071998-03-28Henrik Grubbström (Grubba) }
59f9822018-02-08Henrik Grubbström (Grubba) //! @endnamespace
97e5c72001-07-28Martin Nilsson //! This function is called whenever a inherit is called for. //! It is supposed to return the program to inherit. //! The first argument is the argument given to inherit, and the second //! is the file name of the program currently compiling. Note that the //! file name can be changed with #line, or set by compile_string, so //! it can not be 100% trusted to be a filename. //! previous_object(), can be virtually anything in this function, as it //! is called from the compiler.
10e16f1999-11-04Henrik Grubbström (Grubba) program handle_inherit(string pname, string current_file, object|void handler)
ca2b071998-03-28Henrik Grubbström (Grubba) {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("handle_inherit(%O, %O)\n", pname, current_file); INC_RESOLV_MSG_DEPTH();
677d262003-11-14Martin Stjernholm  program ret = cast_to_program(pname, current_file, handler);
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("handle_inherit(%O, %O) => %O\n", pname, current_file, ret); return ret;
ca2b071998-03-28Henrik Grubbström (Grubba) }
34241f2001-05-24Henrik Grubbström (Grubba) object low_cast_to_object(string oname, string current_file, object|void current_handler)
ca2b071998-03-28Henrik Grubbström (Grubba) { program p; object o;
34241f2001-05-24Henrik Grubbström (Grubba)  p = low_cast_to_program(oname, current_file, current_handler, 1);
ca2b071998-03-28Henrik Grubbström (Grubba)  if(!p) return 0;
b2e9232016-09-19Henrik Grubbström (Grubba)  if(!objectp(o = objects[p])) { object compiler_lock = DefaultCompilerEnvironment->lock(); // NB: p might be a function in a fake_object... if(!objectp(o = objects[p])) o = objects[p] = p(); destruct(compiler_lock); }
ca2b071998-03-28Henrik Grubbström (Grubba)  return o; }
97e5c72001-07-28Martin Nilsson //! This function is called when the drivers wants to cast a string //! to an object because of an implict or explicit cast. This function //! may also receive more arguments in the future.
aa84102003-12-06Martin Nilsson object cast_to_object(string oname, string current_file, object|void current_handler)
ca2b071998-03-28Henrik Grubbström (Grubba) {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("cast_to_object(%O, %O)\n", oname, current_file); INC_RESOLV_MSG_DEPTH();
aa84102003-12-06Martin Nilsson  object o = low_cast_to_object(oname, current_file, current_handler);
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("cast_to_object(%O, %O) => %O\n", oname, current_file, o);
401fa02002-12-02Martin Stjernholm  if (objectp (o)) return o;
677d262003-11-14Martin Stjernholm  error("Cast %O to object failed%s.\n", oname, (current_file && current_file!="-") ? sprintf(" in %O",current_file) : "");
ca2b071998-03-28Henrik Grubbström (Grubba) }
97f8142003-09-18Henrik Grubbström (Grubba) // Marker used for negative caching in module caches. // FIXME: Won't this cause problems when inheriting "/master"?
35f51c2008-06-28Martin Nilsson protected class ZERO_TYPE {};
97f8142003-09-18Henrik Grubbström (Grubba) 
35f51c2008-06-28Martin Nilsson protected object Unicode;
7d016d2008-03-26Henrik Grubbström (Grubba) 
97f8142003-09-18Henrik Grubbström (Grubba) //! Module node representing a single directory. //! //! @seealso //! @[joinnode]
1a03d12011-02-27Martin Nilsson class dirnode (string dirname, object|void compilation_handler, string|void name)
ca2b071998-03-28Henrik Grubbström (Grubba) {
1997b32005-07-13Henrik Grubbström (Grubba)  constant is_resolv_dirnode = 1;
401fa02002-12-02Martin Stjernholm  // objectp() is intentionally not used on the module object, to // allow a module to deny its own existence with `!.
97f8142003-09-18Henrik Grubbström (Grubba)  mixed module;
098c8a2000-03-30Henrik Grubbström (Grubba)  mapping(string:mixed) cache=([]);
3fc67f2016-07-07Martin Nilsson  // Maps a base name like "Bar" to an ordered array of file paths, // e.g. ({ "/lib/Foo.pmod/Bar.pmod", "/lib/Foo.pmod/Bar.so" }).
5feacf2016-07-08Martin Nilsson  protected mapping(string:array(string)) file_paths = ([]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
97f8142003-09-18Henrik Grubbström (Grubba) #ifdef __NT__ #define FIX_CASE(X) lower_case(X) #else #define FIX_CASE(X) (X) #endif /* __NT__ */
35f51c2008-06-28Martin Nilsson  protected string base_from_filename(string fname)
97f8142003-09-18Henrik Grubbström (Grubba)  {
4885f12003-09-19Henrik Grubbström (Grubba)  string low_name = FIX_CASE(fname);
58eb132008-03-20Henrik Grubbström (Grubba)  catch { // FIXME: Warn on failure? low_name = utf8_to_string(low_name);
236a4a2008-03-27Henrik Grubbström (Grubba)  if (Builtin.string_width(low_name) > 8) {
7d016d2008-03-26Henrik Grubbström (Grubba)  // We might need to normalize the string (cf MacOS X). // Load the Unicode module if it hasn't already been loaded. if (!Unicode) { Unicode = resolv("Unicode"); } low_name = Unicode.normalize(low_name, "NFC"); }
58eb132008-03-20Henrik Grubbström (Grubba)  };
4885f12003-09-19Henrik Grubbström (Grubba)  if (has_prefix(low_name, ".#")) return 0; if (has_suffix(low_name, ".pike") || has_suffix(low_name, ".pmod")) {
35320b2004-10-30Martin Stjernholm  return fname[..<5];
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  }
4885f12003-09-19Henrik Grubbström (Grubba)  if (has_suffix(low_name, ".so")) {
35320b2004-10-30Martin Stjernholm  return fname[..<3];
97f8142003-09-18Henrik Grubbström (Grubba)  } return 0; }
35f51c2008-06-28Martin Nilsson  protected int prio_from_filename(string fname)
97f8142003-09-18Henrik Grubbström (Grubba)  { 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;
3fc67f2016-07-07Martin Nilsson  return 0; // We will not reach this.
97f8142003-09-18Henrik Grubbström (Grubba)  }
1a03d12011-02-27Martin Nilsson  protected void create()
97f8142003-09-18Henrik Grubbström (Grubba)  {
20d6932014-12-09Henrik Grubbström (Grubba)  if (!dirname) { error("Attempt to create a dirnode without a directory.\n" "Have you inherited a dirnode?\n"); }
1a03d12011-02-27Martin Nilsson  resolv_debug ("dirnode(%O,%O) created with name %O\n", dirname, compilation_handler, name);
e617062004-01-08Martin Nilsson  fc[dirname]=this;
1a03d12011-02-27Martin Nilsson  if (!sizeof(dirname)) return;
3fc67f2016-07-07Martin Nilsson  array(string) files = sort(master_get_dir(dirname)||({}));
97f8142003-09-18Henrik Grubbström (Grubba)  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",
1a03d12011-02-27Martin Nilsson  dirname, compilation_handler, sizeof(bases));
97f8142003-09-18Henrik Grubbström (Grubba)  if (!sizeof(files)) return; foreach(files; int no; string fname) { fname = combine_path(dirname, fname); string base = bases[no]; if (base == "module") { // We need a module_checker.
3fc67f2016-07-07Martin Nilsson  module = module_checker();
97f8142003-09-18Henrik Grubbström (Grubba)  } array(string) paths = file_paths[base]; if (!paths) { // New entry. file_paths[base] = ({ fname }); continue; } // Multiple files. Order according to prio_from_filename(). // Insert sort. Worst case is 3 filenames. 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..];
e378192003-01-20Martin Nilsson  } }
3fc67f2016-07-07Martin Nilsson  protected class module_checker
14bb592000-05-06Fredrik Hübinette (Hubbe)  {
47ba5a2013-06-03Martin Nilsson  protected int `!()
14bb592000-05-06Fredrik Hübinette (Hubbe)  {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("dirnode(%O)->module_checker()->`!()\n",dirname);
80f7142003-02-27Henrik Grubbström (Grubba) 
3524712015-05-26Martin Nilsson  if (mixed err = catch {
97f8142003-09-18Henrik Grubbström (Grubba)  // Look up module. if (module = cache["module"] || low_ind("module", 1)) {
80f7142003-02-27Henrik Grubbström (Grubba)  /* This allows for `[] to have side effects first time * it is called. (Specifically, the Calendar module uses
97f8142003-09-18Henrik Grubbström (Grubba)  * this).
80f7142003-02-27Henrik Grubbström (Grubba)  */ cache=([]); _cache_full=0; }
97f8142003-09-18Henrik Grubbström (Grubba)  resolv_debug("dirnode(%O)->module_checker()->`!() => %s\n", dirname, !module ? "doesn't exist" : "exists");
3d21a62003-03-27Martin Stjernholm  return !module;
80f7142003-02-27Henrik Grubbström (Grubba)  }) {
86e66a2010-05-06Henrik Grubbström (Grubba)  //werror ("findmodule error: " + call_describe_backtrace (err));
4ce9832003-06-05Martin Stjernholm 
80f7142003-02-27Henrik Grubbström (Grubba)  // findmodule() failed. This can occur due to circularities // between encode_value()'ed programs. // The error will then typically be: // "Cannot call functions in unfinished objects." // Pretend not to exist for now...
97f8142003-09-18Henrik Grubbström (Grubba)  resolv_debug("dirnode(%O)->module_checker()->`!() => failure, doesn't exist\n", dirname);
80f7142003-02-27Henrik Grubbström (Grubba)  return 1;
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  }
14bb592000-05-06Fredrik Hübinette (Hubbe)  }
52c5792000-05-23Fredrik Hübinette (Hubbe) 
47ba5a2013-06-03Martin Nilsson  protected mixed `[](string index)
cd99712001-11-09Martin Stjernholm  {
3fc67f2016-07-07Martin Nilsson  resolv_debug ("dirnode(%O)->module_checker()[%O] => %O\n",
3e7cad2013-11-03Martin Nilsson  dirname, index, module[?index]); return module[?index];
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  }
47ba5a2013-06-03Martin Nilsson  protected array(string) _indices() { if(module) return indices(module); } protected array _values() { if(module) return values(module); }
ca2b071998-03-28Henrik Grubbström (Grubba)  }
35f51c2008-06-28Martin Nilsson  protected mixed low_ind(string index, int(0..1)|void set_module)
97f8142003-09-18Henrik Grubbström (Grubba)  { array(string) paths;
fea47d2011-04-10Marcus Comstedt  INC_RESOLV_MSG_DEPTH();
97f8142003-09-18Henrik Grubbström (Grubba)  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) {
0488452008-02-07Martin Stjernholm  if (dirnode n = fc[fname]) { // Avoid duplicate dirnodes for the same dirs. This can // happen if the master is replaced, e.g. with master_76 // in 7.6/modules/__default.pmod. 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);
9dcabf2009-04-25Martin Stjernholm  return fc[fname] = dirnode(fname, compilation_handler, name && (name == "predef::" ? index : name + "." + index));
97f8142003-09-18Henrik Grubbström (Grubba)  } resolv_debug("dirnode(%O)->ind(%O) casting (object)%O\n", dirname, index, fname); // FIXME: cast_to_program() and cast_to_object() // have lots of overhead to guess the proper // filename. This overhead isn't needed in // our cases, so we could make do with // low_findprog() and the caches. mixed ret;
87ce122008-05-29Henrik Grubbström (Grubba)  if (ret = catch { if (objectp(ret = low_cast_to_object(fname, 0, compilation_handler))) { // This assignment is needed for eg the Calendar module. 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",
86e66a2010-05-06Henrik Grubbström (Grubba)  dirname, index, call_describe_backtrace(ret));
97f8142003-09-18Henrik Grubbström (Grubba)  } } else { resolv_debug("dirnode(%O)->ind(%O) casting (program)%O\n", dirname, index, fname);
fd0fd72004-04-17Marcus Comstedt  program|object ret;
677d262003-11-14Martin Stjernholm  if (ret = low_cast_to_program(fname, 0, compilation_handler)) {
97f8142003-09-18Henrik Grubbström (Grubba)  DEC_RESOLV_MSG_DEPTH(); resolv_debug("dirnode(%O)->ind(%O) => found subprogram %O:%O\n", dirname, index, fname, ret);
fd0fd72004-04-17Marcus Comstedt #if constant(load_module) if (has_suffix(fname, ".so")) { // This is compatible with 7.4 behaviour.
8c201a2004-04-17Marcus Comstedt  if (!ret->_module_value) { object o; // NB: p might be a function in a fake_object...
b2e9232016-09-19Henrik Grubbström (Grubba)  if(!objectp(o = objects[ret])) { object compiler_lock = DefaultCompilerEnvironment->lock(); if(!objectp(o = objects[ret])) o = objects[ret] = ret(); destruct(compiler_lock); }
8c201a2004-04-17Marcus Comstedt  ret = o; }
fd0fd72004-04-17Marcus Comstedt  if(mixed tmp=ret->_module_value) ret=tmp; } #endif
97f8142003-09-18Henrik Grubbström (Grubba)  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; }
35f51c2008-06-28Martin Nilsson  protected mixed ind(string index)
ca2b071998-03-28Henrik Grubbström (Grubba)  {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("dirnode(%O)->ind(%O)\n", dirname, index); INC_RESOLV_MSG_DEPTH();
97f8142003-09-18Henrik Grubbström (Grubba)  if (_cache_full) { DEC_RESOLV_MSG_DEPTH(); resolv_debug("dirnode(%O)->ind(%O) => cache_full %O\n", dirname, index, cache[index]); return cache[index]; }
3d21a62003-03-27Martin Stjernholm  if(module)
e118831999-12-22Per Hedbor  {
cd99712001-11-09Martin Stjernholm  mixed o;
65340d2014-08-15Martin Nilsson  if(!undefinedp(o=module[index]))
aa68b12001-03-19Fredrik Hübinette (Hubbe)  {
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("dirnode(%O)->ind(%O) => found %O\n", dirname, index, o);
aa68b12001-03-19Fredrik Hübinette (Hubbe)  return o; }
97f8142003-09-18Henrik Grubbström (Grubba)  resolv_debug ("dirnode(%O)->ind(%O) => not found in module\n", dirname, index);
a2faf61999-12-01Martin Stjernholm  }
4ce9832003-06-05Martin Stjernholm  else resolv_debug ("dirnode(%O)->ind(%O) => no module\n", dirname, index);
ca2b071998-03-28Henrik Grubbström (Grubba) 
fea47d2011-04-10Marcus Comstedt  DEC_RESOLV_MSG_DEPTH();
97f8142003-09-18Henrik Grubbström (Grubba)  return low_ind(index);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
3abcaf2016-07-08Martin Nilsson  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); }
5feacf2016-07-08Martin Nilsson  protected mixed `->=(string index, mixed value) { return `[]=(index, value); }
47ba5a2013-06-03Martin Nilsson  protected mixed `[](string index)
ca2b071998-03-28Henrik Grubbström (Grubba)  { mixed ret;
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE
e378192003-01-20Martin Nilsson  werror("%*nDirnode(%O) cache[%O] ?????\n", sizeof(backtrace()),dirname,index);
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #endif
65340d2014-08-15Martin Nilsson  if(!undefinedp(ret=cache[index]))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE
3d21a62003-03-27Martin Stjernholm  werror("%*nDirnode(%O) cache[%O] => %O%s\n",
ab9d672003-03-08Henrik Grubbström (Grubba)  sizeof(backtrace()),dirname,index, ret, (ret != ZERO_TYPE)?"":" (zero_type)");
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #endif
cd99712001-11-09Martin Stjernholm  if (ret != ZERO_TYPE) return ret;
ab9d672003-03-08Henrik Grubbström (Grubba) #ifdef MODULE_TRACE werror("%*nDirnode(%O) ZERO_TYPE!\n", sizeof(backtrace()),dirname); #endif
ca2b071998-03-28Henrik Grubbström (Grubba)  return UNDEFINED; }
1997b32005-07-13Henrik Grubbström (Grubba)  ret=ind(index);
dd7d452002-12-09Martin Stjernholm  // We might have gotten placeholder objects in the first pass // which must not be cached to the second.
ab9d672003-03-08Henrik Grubbström (Grubba)  if(ret == predef::__placeholder_object) { #ifdef MODULE_TRACE werror("%*nDirnode(%O) PLACE_HOLDER.\n", sizeof(backtrace()),dirname); #endif return ret; }
dd7d452002-12-09Martin Stjernholm 
65340d2014-08-15Martin Nilsson  cache[index] = undefinedp(ret) ? ZERO_TYPE : ret;
cd99712001-11-09Martin Stjernholm  return ret;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
3e4b811998-10-16Henrik Grubbström (Grubba) 
5feacf2016-07-08Martin Nilsson  protected mixed `->(string index) {
370a782016-07-08Martin Nilsson  if( (< "dirname", "name", "is_resolv_dirnode",
50afc22016-07-11Martin Nilsson  "module", "delete_value" >)[index] )
5feacf2016-07-08Martin Nilsson  return ::`->(index); return `[](index); } protected mixed safe_index(string index)
97f8142003-09-18Henrik Grubbström (Grubba)  { mixed err;
3abf3f2008-05-26Henrik Grubbström (Grubba)  resolv_debug ("dirnode(%O): %O...\n", dirname, index);
97f8142003-09-18Henrik Grubbström (Grubba)  if (err = catch { return `[](index); }) {
677d262003-11-14Martin Stjernholm  call_compile_warning (compilation_handler, dirname+"."+fname,
86e66a2010-05-06Henrik Grubbström (Grubba)  "Compilation failed: " + call_describe_error(err));
97f8142003-09-18Henrik Grubbström (Grubba)  } return UNDEFINED; }
35f51c2008-06-28Martin Nilsson  protected int(0..1) _cache_full;
5feacf2016-07-08Martin Nilsson  protected void fill_cache()
3e4b811998-10-16Henrik Grubbström (Grubba)  { if (_cache_full) { return; }
3abf3f2008-05-26Henrik Grubbström (Grubba)  resolv_debug ("dirnode(%O) => Filling cache...\n", dirname);
97f8142003-09-18Henrik Grubbström (Grubba)  // NOTE: We rely on side effects in `[]() and safe_index() // to fill the cache.
677d262003-11-14Martin Stjernholm  // Why shouldn't thrown errors be propagated here? /mast
3e4b811998-10-16Henrik Grubbström (Grubba)  if (module) {
3abf3f2008-05-26Henrik Grubbström (Grubba)  resolv_debug("dirnode(%O): module: %O, indices:%{%O, %}\n", dirname, module, indices(module));
97f8142003-09-18Henrik Grubbström (Grubba)  map(indices(module), safe_index);
3e4b811998-10-16Henrik Grubbström (Grubba)  }
97f8142003-09-18Henrik Grubbström (Grubba)  map(indices(file_paths), safe_index);
3abf3f2008-05-26Henrik Grubbström (Grubba)  _cache_full = (object_program(module) != __null_program); resolv_debug ("dirnode(%O) => Cache %s.\n", dirname, _cache_full?"full":"partially filled");
3e4b811998-10-16Henrik Grubbström (Grubba)  }
e378192003-01-20Martin Nilsson 
4fcd4f2014-06-10Henrik Grubbström (Grubba)  protected array(string) _indices()
3e4b811998-10-16Henrik Grubbström (Grubba)  { fill_cache();
eb801d2003-06-05Martin Stjernholm  // Note: Cannot index cache at all here to filter out the // ZERO_TYPE values since that can change the order in the // mapping, and _indices() has to return the elements in the same // order as a nearby _values() call. return filter (indices (cache), map (values (cache), `!=, ZERO_TYPE));
3e4b811998-10-16Henrik Grubbström (Grubba)  }
e378192003-01-20Martin Nilsson 
4fcd4f2014-06-10Henrik Grubbström (Grubba)  protected array(mixed) _values()
3e4b811998-10-16Henrik Grubbström (Grubba)  { fill_cache();
cd99712001-11-09Martin Stjernholm  return values(cache) - ({ZERO_TYPE});
3e4b811998-10-16Henrik Grubbström (Grubba)  }
52c5792000-05-23Fredrik Hübinette (Hubbe) 
a002d32002-03-01Martin Stjernholm  void delete_value (mixed val) {
97f8142003-09-18Henrik Grubbström (Grubba)  if (string name = search (cache, val)) {
a002d32002-03-01Martin Stjernholm  m_delete (cache, name);
97f8142003-09-18Henrik Grubbström (Grubba)  _cache_full = 0; }
a002d32002-03-01Martin Stjernholm  }
35f51c2008-06-28Martin Nilsson  protected int(0..) _sizeof() {
e378192003-01-20Martin Nilsson  return sizeof(_values()); }
35f51c2008-06-28Martin Nilsson  protected string _sprintf(int as)
e378192003-01-20Martin Nilsson  {
9dcabf2009-04-25Martin Stjernholm  return as=='O' && (name || sprintf("master()->dirnode(%O:%O)", dirname, module && module));
e378192003-01-20Martin Nilsson  } }
ca2b071998-03-28Henrik Grubbström (Grubba) 
97f8142003-09-18Henrik Grubbström (Grubba) //! Module node holding possibly multiple directories, //! and optionally falling back to another level. //! //! @seealso //! @[dirnode]
1a03d12011-02-27Martin Nilsson class joinnode (array(object|mapping) joined_modules, object|void compilation_handler, joinnode|mapping(mixed:int(0..0))|void fallback_module, string|void name)
94257b1998-10-16Henrik Grubbström (Grubba) {
1997b32005-07-13Henrik Grubbström (Grubba)  constant is_resolv_joinnode = 1;
9dcabf2009-04-25Martin Stjernholm 
098c8a2000-03-30Henrik Grubbström (Grubba)  mapping(string:mixed) cache=([]);
94257b1998-10-16Henrik Grubbström (Grubba) 
1a03d12011-02-27Martin Nilsson  protected string _sprintf(int as)
97f8142003-09-18Henrik Grubbström (Grubba)  {
9dcabf2009-04-25Martin Stjernholm  if (as != 'O') return 0; if (name) {
567f922016-09-12Martin Nilsson  if (has_value (name, '|'))
9dcabf2009-04-25Martin Stjernholm  return "joinnode(" + name + ")"; else return name; // Let's be brief. } else return sprintf("master()->joinnode(%O)", joined_modules);
97f8142003-09-18Henrik Grubbström (Grubba)  }
52c5792000-05-23Fredrik Hübinette (Hubbe) 
1a03d12011-02-27Martin Nilsson  protected void create()
94257b1998-10-16Henrik Grubbström (Grubba)  {
eb6f0e2011-02-28Henrik Grubbström (Grubba)  if( !fallback_module ) { // NOTE: Uses the empty mapping as the default fallback // for simplified code.
1a03d12011-02-27Martin Nilsson  fallback_module = ([]);
eb6f0e2011-02-28Henrik Grubbström (Grubba)  }
9dcabf2009-04-25Martin Stjernholm 
20d6932014-12-09Henrik Grubbström (Grubba)  if (!joined_modules) { error("Attempt to create a joinnode without joined modules.\n" "Have you inherited a joinnode?\n"); }
1a03d12011-02-27Martin Nilsson  if (!name) {
9dcabf2009-04-25Martin Stjernholm  mapping(string:int(1..1)) names = ([]);
1a03d12011-02-27Martin Nilsson  foreach (joined_modules, object|mapping m) { if (objectp (m) && stringp (m->name))
9dcabf2009-04-25Martin Stjernholm  names[m->name] = 1; } if (sizeof (names))
1a03d12011-02-27Martin Nilsson  name = sort (indices (names)) * "|";
9dcabf2009-04-25Martin Stjernholm  } resolv_debug ("joinnode(%O) created with name %O\n", joined_modules, name);
94257b1998-10-16Henrik Grubbström (Grubba)  }
97f8142003-09-18Henrik Grubbström (Grubba)  void add_path(string path) { path = combine_path(getcwd(), path); dirnode node = fc[path] ||
9dcabf2009-04-25Martin Stjernholm  (fc[path] = dirnode(path, compilation_handler,
567f922016-09-12Martin Nilsson  name && !has_value (name, '|') && name));
97f8142003-09-18Henrik Grubbström (Grubba)  if (sizeof(joined_modules) && joined_modules[0] == node) return; joined_modules = ({ node }) + (joined_modules - ({ node }));
db6eae2009-07-17Henrik Grubbström (Grubba)  cache = ([]);
97f8142003-09-18Henrik Grubbström (Grubba)  } void rem_path(string path) { path = combine_path(getcwd(), path); joined_modules = filter(joined_modules, lambda(dirnode node) {
a5af872018-02-06Martin Nilsson  return !is_dirnode(node) ||
97f8142003-09-18Henrik Grubbström (Grubba)  (node->dirname != path); });
db6eae2009-07-17Henrik Grubbström (Grubba)  cache = ([]);
97f8142003-09-18Henrik Grubbström (Grubba)  }
35f51c2008-06-28Martin Nilsson  protected mixed ind(string index)
94257b1998-10-16Henrik Grubbström (Grubba)  {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("joinnode(%O)->ind(%O)\n", joined_modules, index); INC_RESOLV_MSG_DEPTH();
94257b1998-10-16Henrik Grubbström (Grubba)  array(mixed) res = ({});
3524712015-05-26Martin Nilsson  foreach(joined_modules, object|mapping o)
ca051c1999-11-23Per Hedbor  {
94257b1998-10-16Henrik Grubbström (Grubba)  mixed ret;
3524712015-05-26Martin Nilsson  if (!undefinedp(ret = o[index]))
ca051c1999-11-23Per Hedbor  {
a5af872018-02-06Martin Nilsson  if (is_dirnode(ret) || is_joinnode(ret))
ca051c1999-11-23Per Hedbor  {
8b307e1998-10-17Henrik Grubbström (Grubba)  // Only join directorynodes (or joinnodes).
97f8142003-09-18Henrik Grubbström (Grubba)  res += ({ ret }); } else {
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("joinnode(%O)->ind(%O) => found %O\n", joined_modules, index, ret);
ca051c1999-11-23Per Hedbor  return (ret);
8b307e1998-10-17Henrik Grubbström (Grubba)  }
94257b1998-10-16Henrik Grubbström (Grubba)  } }
3d21a62003-03-27Martin Stjernholm 
97f8142003-09-18Henrik Grubbström (Grubba)  if (sizeof(res)) {
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH();
97f8142003-09-18Henrik Grubbström (Grubba)  resolv_debug("joinnode(%O)->ind(%O) => new joinnode, fallback: %O\n", joined_modules, index, fallback_module[index]);
9dcabf2009-04-25Martin Stjernholm  return joinnode(res, compilation_handler, fallback_module[index],
567f922016-09-12Martin Nilsson  name && !has_value (name, '|') &&
9dcabf2009-04-25Martin Stjernholm  (name == "predef::" ? index : name + "." + index));
3d21a62003-03-27Martin Stjernholm  } DEC_RESOLV_MSG_DEPTH();
97f8142003-09-18Henrik Grubbström (Grubba)  resolv_debug ("joinnode(%O)->ind(%O) => not found. Trying fallback %O\n", joined_modules, index, fallback_module); return fallback_module[index];
94257b1998-10-16Henrik Grubbström (Grubba)  }
3abcaf2016-07-08Martin Nilsson  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); }
5feacf2016-07-08Martin Nilsson  protected mixed `->=(string index, mixed value) {
bb04912016-07-08Martin Nilsson  if( index=="fallback_module" ) return fallback_module=value;
5feacf2016-07-08Martin Nilsson  return `[]=(index, value); }
47ba5a2013-06-03Martin Nilsson  protected mixed `[](string index)
94257b1998-10-16Henrik Grubbström (Grubba)  {
098c8a2000-03-30Henrik Grubbström (Grubba)  mixed ret;
65340d2014-08-15Martin Nilsson  if (!undefinedp(ret = cache[index])) {
94257b1998-10-16Henrik Grubbström (Grubba)  if (ret != ZERO_TYPE) { return ret; } return UNDEFINED; }
1997b32005-07-13Henrik Grubbström (Grubba)  ret = ind(index);
dd7d452002-12-09Martin Stjernholm  // We might have gotten placeholder objects in the first pass // which must not be cached to the second. if(ret == predef::__placeholder_object) return ret;
65340d2014-08-15Martin Nilsson  if (undefinedp(ret)) {
94257b1998-10-16Henrik Grubbström (Grubba)  cache[index] = ZERO_TYPE; } else { cache[index] = ret; } return ret; }
eb801d2003-06-05Martin Stjernholm 
5feacf2016-07-08Martin Nilsson  protected mixed `->(string index) {
bb04912016-07-08Martin Nilsson  if( (< "joined_modules", "fallback_module", "name", "is_resolv_joinnode",
50afc22016-07-11Martin Nilsson  "add_path", "rem_path", "delete_value", "_encode",
370a782016-07-08Martin Nilsson  "_decode" >)[index] )
5feacf2016-07-08Martin Nilsson  return ::`->(index); return `[](index); }
35f51c2008-06-28Martin Nilsson  protected int _cache_full;
eb801d2003-06-05Martin Stjernholm 
5feacf2016-07-08Martin Nilsson  protected void fill_cache()
3e4b811998-10-16Henrik Grubbström (Grubba)  { if (_cache_full) { return; }
c084262000-02-04Henrik Grubbström (Grubba)  foreach(joined_modules, object|mapping|program o) {
3e4b811998-10-16Henrik Grubbström (Grubba)  foreach(indices(o), string index) {
65340d2014-08-15Martin Nilsson  if (!has_index(cache, index)) {
3e4b811998-10-16Henrik Grubbström (Grubba)  `[](index); } } }
a165032003-09-19Henrik Grubbström (Grubba)  foreach(indices(fallback_module), string index) { `[](index); }
3e4b811998-10-16Henrik Grubbström (Grubba)  _cache_full = 1; }
eb801d2003-06-05Martin Stjernholm 
47ba5a2013-06-03Martin Nilsson  protected array(string) _indices()
3e4b811998-10-16Henrik Grubbström (Grubba)  { fill_cache();
eb801d2003-06-05Martin Stjernholm  // Note: Cannot index cache at all here to filter out the // ZERO_TYPE values since that can change the order in the // mapping, and _indices() has to return the elements in the same // order as a nearby _values() call. return filter (indices (cache), map (values (cache), `!=, ZERO_TYPE));
3e4b811998-10-16Henrik Grubbström (Grubba)  }
eb801d2003-06-05Martin Stjernholm 
47ba5a2013-06-03Martin Nilsson  protected array(mixed) _values()
3e4b811998-10-16Henrik Grubbström (Grubba)  { fill_cache();
cd99712001-11-09Martin Stjernholm  return values(cache) - ({ZERO_TYPE});
3e4b811998-10-16Henrik Grubbström (Grubba)  }
a002d32002-03-01Martin Stjernholm 
c782bd2016-07-08Martin Nilsson  protected int(0..) _sizeof() { return sizeof(_values()); }
a002d32002-03-01Martin Stjernholm  void delete_value (mixed val) { if (string name = search (cache, val)) m_delete (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--; }
a5af872018-02-06Martin Nilsson  else if (is_dirnode(o) || is_joinnode(o))
1997b32005-07-13Henrik Grubbström (Grubba)  o->delete_value (val);
a002d32002-03-01Martin Stjernholm  else if (string name = mappingp (o) && search (o, val)) m_delete (o, name); } }
94257b1998-10-16Henrik Grubbström (Grubba) 
47ba5a2013-06-03Martin Nilsson  protected int `== (mixed other)
4ce9832003-06-05Martin Stjernholm  {
8b7c242018-02-06Henrik Grubbström (Grubba)  // NB: Index the program instead of the object to avoid issues // with modules overloading lfun::`->() with stuff that has // side-effects (here's looking at you Calendar.Events).
a5af872018-02-06Martin Nilsson  return is_joinnode(other) &&
1997b32005-07-13Henrik Grubbström (Grubba)  equal (mkmultiset (joined_modules), mkmultiset (other->joined_modules));
4ce9832003-06-05Martin Stjernholm  }
57b52d2003-05-31Martin Stjernholm  array(object) _encode() { return joined_modules; } void _decode (array(object) joined_modules) {
8e06a32014-09-30Martin Nilsson  this::joined_modules = joined_modules;
57b52d2003-05-31Martin Stjernholm  }
14cf192008-08-14Martin Stjernholm }
ca2b071998-03-28Henrik Grubbström (Grubba) 
97f8142003-09-18Henrik Grubbström (Grubba) joinnode handle_import(string path, string|void current_file,
14cf192008-08-14Martin Stjernholm  object|void current_handler)
97f8142003-09-18Henrik Grubbström (Grubba) { if(current_file) {
15af9c2003-12-19Marcus Comstedt  path = combine_path_with_cwd(dirname(current_file), path);
97f8142003-09-18Henrik Grubbström (Grubba)  } else { path = combine_path_with_cwd(path); } // FIXME: Need caching!!! #if 0 // FIXME: This caching strategy could be improved, // since it ignores module_nodes from the // ordinary module tree. 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 */
325b8f2018-11-04Mateusz Krawczuk  auto path_stat = file_stat(path); if (!path_stat) compile_cb_error("Failed to stat file: %O\n", path); joinnode node; if (path_stat->isreg) { node = low_cast_to_object(path, current_file, current_handler); }
9d30492018-11-04Mateusz Krawczuk  else if (path_stat->isdir) {
325b8f2018-11-04Mateusz Krawczuk  node = joinnode(({}), current_handler);
97f8142003-09-18Henrik Grubbström (Grubba) #ifdef PIKE_MODULE_RELOC
325b8f2018-11-04Mateusz Krawczuk  // If we have PIKE_MODULE_RELOC enabled, // we might need to map to multiple directories. if(path == "/${PIKE_MODULE_PATH}" || has_prefix(path, "/${PIKE_MODULE_PATH}/")) { string tmp = path[21..]; foreach(pike_module_path, string prefix) { node->add_path(sizeof(tmp)? combine_path(prefix, tmp) : prefix); } } else
97f8142003-09-18Henrik Grubbström (Grubba) #endif /* PIKE_MODULE_RELOC */
325b8f2018-11-04Mateusz Krawczuk  node->add_path(path); }
97f8142003-09-18Henrik Grubbström (Grubba)  return node; }
9dcabf2009-04-25Martin Stjernholm program|object findmodule(string fullname, object|void handler, void|string name)
ca2b071998-03-28Henrik Grubbström (Grubba) {
3593292003-09-08Henrik Grubbström (Grubba)  program|object o;
57b52d2003-05-31Martin Stjernholm 
3d21a62003-03-27Martin Stjernholm  resolv_debug ("findmodule(%O)\n", fullname);
65340d2014-08-15Martin Nilsson  if(!undefinedp(o=fc[fullname]) && o != no_value)
ca2b071998-03-28Henrik Grubbström (Grubba)  {
3593292003-09-08Henrik Grubbström (Grubba)  if (objectp(o) || programp(o) || o != 0) {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("findmodule(%O) => found %O (cached)\n", fullname, o); return o; } resolv_debug ("findmodule(%O) => not found (cached)\n", fullname); return UNDEFINED;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
89b7162007-11-15Martin Stjernholm  if(Stat stat=master_file_stat(fakeroot(fullname)))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
68065f2003-05-28Johan Sundström  if(stat->isdir) {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("findmodule(%O) => new dirnode\n", fullname);
9dcabf2009-04-25Martin Stjernholm  return fc[fullname] = dirnode(fullname, handler, name);
89b7162007-11-15Martin Stjernholm  } #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;
3d21a62003-03-27Martin Stjernholm  }
89b7162007-11-15Martin Stjernholm #endif
ca2b071998-03-28Henrik Grubbström (Grubba)  }
3d21a62003-03-27Martin Stjernholm  INC_RESOLV_MSG_DEPTH();
89b7162007-11-15Martin Stjernholm  if(objectp (o = low_cast_to_object(fullname, "/.", handler))) {
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("findmodule(%O) => got object %O\n", fullname, o);
ca2b071998-03-28Henrik Grubbström (Grubba)  return fc[fullname]=o;
3d21a62003-03-27Martin Stjernholm  }
eba0232004-01-13Martin Nilsson 
677d262003-11-14Martin Stjernholm  if (programp (o = low_cast_to_program(fullname, "/.", handler))) {
3593292003-09-08Henrik Grubbström (Grubba)  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("findmodule(%O) => got .pike program %O\n", fullname, o); return fc[fullname] = o; }
3d21a62003-03-27Martin Stjernholm  DEC_RESOLV_MSG_DEPTH(); resolv_debug ("findmodule(%O) => not found\n", fullname);
401fa02002-12-02Martin Stjernholm  return fc[fullname] = 0;
ca2b071998-03-28Henrik Grubbström (Grubba) }
97f8142003-09-18Henrik Grubbström (Grubba) #if 0
10e16f1999-11-04Henrik Grubbström (Grubba) mixed handle_import(string what, string|void current_file, object|void handler)
ca2b071998-03-28Henrik Grubbström (Grubba) {
afa1292000-02-19Martin Nilsson  string path;
ca2b071998-03-28Henrik Grubbström (Grubba)  if(current_file) {
15af9c2003-12-19Marcus Comstedt  path = combine_path_with_cwd(dirname(current_file), what);
57b1af2001-12-13Henrik Grubbström (Grubba)  } else { path = combine_path_with_cwd(what);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
57b52d2003-05-31Martin Stjernholm  #if 0 // If we can't cache the dirnode when we got a handler, then // findmodule has to be broken too. Good caching is necessary for // module dumping. /mast
34241f2001-05-24Henrik Grubbström (Grubba)  if (handler) {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("handle_import(%O, %O, %O) => new dirnode with handler\n", what, current_file, handler);
34241f2001-05-24Henrik Grubbström (Grubba)  return dirnode(path, handler); }
57b52d2003-05-31Martin Stjernholm #endif if(objectp (fc[path])) {
3d21a62003-03-27Martin Stjernholm  resolv_debug ("handle_import(%O, %O) => found %O (cached)\n",
fba2e22014-12-05Bill Welliver  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"); }
3d21a62003-03-27Martin Stjernholm  what, current_file, fc[path]); return fc[path]; } resolv_debug ("handle_import(%O, %O) => new dirnode\n", what, current_file);
2d8c832003-08-11Henrik Grubbström (Grubba) #ifdef PIKE_MODULE_RELOC
3524712015-05-26Martin Nilsson  // If we have PIKE_MODULE_RELOC enabled,
2d8c832003-08-11Henrik Grubbström (Grubba)  // we might need to map to a join node. // FIXME: Ought to use the non-relocate_module() fakeroot(). 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);
fba2e22014-12-05Bill Welliver  // do we have a mounted zip?
3524712015-05-26Martin Nilsson  if(fs_map[tmp])
fba2e22014-12-05Bill Welliver  tmp = combine_path(tmp, "modules");
2d8c832003-08-11Henrik Grubbström (Grubba)  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);
cc2c071998-04-19Fredrik Hübinette (Hubbe) }
97f8142003-09-18Henrik Grubbström (Grubba) #endif /* 0 */
a20af62000-09-26Fredrik Hübinette (Hubbe)  multiset no_resolv = (<>);
b07e962001-07-27Martin Nilsson 
21c85e2008-06-01Henrik Grubbström (Grubba) //! Resolver of symbols not located in the program being compiled.
a20af62000-09-26Fredrik Hübinette (Hubbe) class CompatResolver
cc2c071998-04-19Fredrik Hübinette (Hubbe) {
21c85e2008-06-01Henrik Grubbström (Grubba)  //! Join node of the root modules for this resolver.
9dcabf2009-04-25Martin Stjernholm  joinnode root_module = joinnode(({instantiate_static_modules(predef::_static_modules)}), 0, 0, "predef::");
97f8142003-09-18Henrik Grubbström (Grubba)  //! Lookup from handler module to corresponding root_module. mapping(object:joinnode) handler_root_modules = ([]);
94dc1b2003-10-30H. William Welliver III  //! The pike system module path, not including any set by the user.
0418252003-10-30H. William Welliver III  array(string) system_module_path=({}); //! The complete module search path
a20af62000-09-26Fredrik Hübinette (Hubbe)  array(string) pike_module_path=({});
0418252003-10-30H. William Welliver III  //! The complete include search path
97f8142003-09-18Henrik Grubbström (Grubba)  array(string) pike_include_path=({});
0418252003-10-30H. William Welliver III  //! The complete program search path
a20af62000-09-26Fredrik Hübinette (Hubbe)  array(string) pike_program_path=({});
0418252003-10-30H. William Welliver III 
da494f2003-11-12Henrik Grubbström (Grubba)  mapping(string:string) predefines = master()->initial_predefines;
a20af62000-09-26Fredrik Hübinette (Hubbe)  string ver;
97f8142003-09-18Henrik Grubbström (Grubba)  //! If we fail to resolv, try the fallback.
3593292003-09-08Henrik Grubbström (Grubba)  //! //! Typical configuration:
21c85e2008-06-01Henrik Grubbström (Grubba)  //! @pre{0.6->7.0->7.2-> ... ->master@}
97f8142003-09-18Henrik Grubbström (Grubba)  CompatResolver fallback_resolver;
3593292003-09-08Henrik Grubbström (Grubba) 
4619bd2002-07-29Martin Nilsson  //! The CompatResolver is initialized with a value that can be
6df5a52001-11-07Martin Nilsson  //! casted into a "%d.%d" string, e.g. a version object.
97f8142003-09-18Henrik Grubbström (Grubba)  //! //! It can also optionally be initialized with a fallback resolver.
35f51c2008-06-28Martin Nilsson  protected void create(mixed version, CompatResolver|void fallback_resolver)
97f8142003-09-18Henrik Grubbström (Grubba)  { resolv_debug("CompatResolver(%O, %O)\n", version, fallback_resolver); ver=(string)version; #if 0 if (version) {
1997b32005-07-13Henrik Grubbström (Grubba)  root_module->symbol = ver + "::";
97f8142003-09-18Henrik Grubbström (Grubba)  } #endif if (CompatResolver::fallback_resolver = fallback_resolver) {
1997b32005-07-13Henrik Grubbström (Grubba)  root_module->fallback_module = fallback_resolver->root_module;
a20af62000-09-26Fredrik Hübinette (Hubbe)  }
97f8142003-09-18Henrik Grubbström (Grubba)  predefines = initial_predefines; }
a20af62000-09-26Fredrik Hübinette (Hubbe) 
8f45692001-01-14Henrik Grubbström (Grubba)  //! Add a directory to search for include files. //! //! This is the same as the command line option @tt{-I@}. //! //! @note //! Note that the added directory will only be searched when using //! < > to quote the included file. //! //! @seealso //! @[remove_include_path()] //!
a20af62000-09-26Fredrik Hübinette (Hubbe)  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; }
8f45692001-01-14Henrik Grubbström (Grubba)  //! Remove a directory to search for include files. //! //! This function performs the reverse operation of @[add_include_path()]. //! //! @seealso //! @[add_include_path()] //!
a20af62000-09-26Fredrik Hübinette (Hubbe)  void remove_include_path(string tmp) { tmp=normalize_path(combine_path_with_cwd(tmp)); pike_include_path-=({tmp}); }
eba0232004-01-13Martin Nilsson 
8f45692001-01-14Henrik Grubbström (Grubba)  //! Add a directory to search for modules. //! //! This is the same as the command line option @tt{-M@}. //! //! @seealso //! @[remove_module_path()] //!
fba2e22014-12-05Bill Welliver  //! @param path
3524712015-05-26Martin Nilsson  //! a string containing a path to search for Pike modules. May be a //! directory, or a path to a ZIP archive. If a ZIP archive path is
fba2e22014-12-05Bill Welliver  //! provided, modules will be loaded from a directory, "modules" within //! the ZIP archive (see the subpath argument). //! //! @param subpath
3524712015-05-26Martin Nilsson  //! if path is a ZIP archive, this argument will determine the path within //! the archive to be searched.
fba2e22014-12-05Bill Welliver  //! void add_module_path(string path, string|void subpath)
a20af62000-09-26Fredrik Hübinette (Hubbe)  {
fba2e22014-12-05Bill Welliver  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 }));
a20af62000-09-26Fredrik Hübinette (Hubbe)  }
eba0232004-01-13Martin Nilsson 
8f45692001-01-14Henrik Grubbström (Grubba)  //! Remove a directory to search for modules. //! //! This function performs the reverse operation of @[add_module_path()]. //! //! @seealso //! @[add_module_path()] //!
a20af62000-09-26Fredrik Hübinette (Hubbe)  void remove_module_path(string tmp) { tmp=normalize_path(combine_path_with_cwd(tmp));
1997b32005-07-13Henrik Grubbström (Grubba)  root_module->rem_path(tmp);
97f8142003-09-18Henrik Grubbström (Grubba)  pike_module_path -= ({ tmp });
a20af62000-09-26Fredrik Hübinette (Hubbe)  }
eba0232004-01-13Martin Nilsson 
8f45692001-01-14Henrik Grubbström (Grubba)  //! Add a directory to search for programs. //! //! This is the same as the command line option @tt{-P@}. //! //! @seealso //! @[remove_program_path()] //!
a20af62000-09-26Fredrik Hübinette (Hubbe)  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; }
eba0232004-01-13Martin Nilsson 
8f45692001-01-14Henrik Grubbström (Grubba)  //! Remove a directory to search for programs. //! //! This function performs the reverse operation of @[add_program_path()]. //! //! @seealso //! @[add_program_path()] //!
a20af62000-09-26Fredrik Hübinette (Hubbe)  void remove_program_path(string tmp) { tmp=normalize_path(combine_path_with_cwd(tmp)); pike_program_path-=({tmp}); }
374c902001-12-20Martin Stjernholm  //! Add a define (without arguments) which will be implicitly //! defined in @[cpp] calls.
080e3a2011-11-04Per Hedbor  void add_predefine (string name, mixed value)
374c902001-12-20Martin Stjernholm  { predefines[name] = value; } //! Remove a define from the set that are implicitly defined in //! @[cpp] calls. void remove_predefine (string name) { m_delete (predefines, name); }
db77fa2002-12-14Martin Nilsson  //! Returns a mapping with the current predefines.
374c902001-12-20Martin Stjernholm  mapping get_predefines() { return predefines; }
fd0fd72004-04-17Marcus Comstedt  //! Instantiate static modules in the same way that dynamic modules //! are instantiated.
35f51c2008-06-28Martin Nilsson  protected mapping(string:mixed) instantiate_static_modules(object|mapping static_modules)
fd0fd72004-04-17Marcus Comstedt  {
4b7c4c2004-04-17Marcus Comstedt  mapping(string:mixed) res = ([]), joins = ([]);
fd0fd72004-04-17Marcus Comstedt  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;
4b7c4c2004-04-17Marcus Comstedt  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])
9dcabf2009-04-25Martin Stjernholm  res[n] = joinnode(({res[n], v}), 0, 0, n);
4b7c4c2004-04-17Marcus Comstedt  else res[n] = v;
fd0fd72004-04-17Marcus Comstedt  } return res; }
a7e9b92017-12-06Henrik Grubbström (Grubba)  //! Return the default module for the @[CompatResolver].
6df5a52001-11-07Martin Nilsson  //!
a7e9b92017-12-06Henrik Grubbström (Grubba)  //! This is the mapping that corresponds to the @[predef::] //! name space for the compatibility level, and is the //! value returned by @[all_constants()] for the same.
a20af62000-09-26Fredrik Hübinette (Hubbe)  mapping get_default_module()
e842282016-07-11Martin Nilsson  { resolv_debug ("%O->get_default_module()\n", this); /* This is an ugly kluge to avoid an infinite recursion. The * infinite recursion occurs because this function is called for * every file when the compat_major/minor is set. This kluge * could cause problems with threads if the compiler was * threaded. -Hubbe */ int saved_compat_minor=compat_minor; int saved_compat_major=compat_major; compat_minor=-1; compat_major=-1; mixed x; mixed err =catch {
acd1632001-12-17Henrik Grubbström (Grubba)  if(resolv("__default") && (x=resolv("__default.all_constants"))) x=x();
a20af62000-09-26Fredrik Hübinette (Hubbe)  };
e842282016-07-11Martin Nilsson  compat_major=saved_compat_major; compat_minor=saved_compat_minor; if(err) throw(err); return x; }
a20af62000-09-26Fredrik Hübinette (Hubbe) 
97f8142003-09-18Henrik Grubbström (Grubba)  // _static_modules -- default for global:: // current_handler->get_default_module()->_static_modules
3215c92003-05-15Henrik Grubbström (Grubba) 
97f8142003-09-18Henrik Grubbström (Grubba)  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;
34241f2001-05-24Henrik Grubbström (Grubba) 
97f8142003-09-18Henrik Grubbström (Grubba)  // Check for _static_modules. 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"] || ([]);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
94257b1998-10-16Henrik Grubbström (Grubba)  }
97f8142003-09-18Henrik Grubbström (Grubba) 
50afc22016-07-11Martin Nilsson  node = joinnode(({ // Kluge to get _static_modules to work at top level. ([ "_static_modules" : static_modules ]), instantiate_static_modules(static_modules), // Copy relevant stuff from the root module.
a5af872018-02-06Martin Nilsson  @filter(root_module->joined_modules, is_dirnode) }),
97f8142003-09-18Henrik Grubbström (Grubba)  current_handler,
9dcabf2009-04-25Martin Stjernholm  root_module->fallback_module, "predef::");
97f8142003-09-18Henrik Grubbström (Grubba)  return node; }
a7e9b92017-12-06Henrik Grubbström (Grubba)  //! Look up @[identifier] in the root module.
97f8142003-09-18Henrik Grubbström (Grubba)  mixed resolv_base(string identifier, string|void current_file,
26e3592018-07-06Henrik Grubbström (Grubba)  object|void current_handler, object|void current_compat_handler)
97f8142003-09-18Henrik Grubbström (Grubba)  { // werror("Resolv_base(%O)\n",identifier); return get_root_module(current_handler)[identifier]; }
6df5a52001-11-07Martin Nilsson 
100c3e2003-12-01Martin Nilsson  //! Same as @[resolv], but throws an error instead of returning //! @[UNDEFINED] if the resolv failed. mixed resolv_or_error(string identifier, string|void current_file, void|object current_handler) { mixed res = resolv(identifier, current_file, current_handler);
65340d2014-08-15Martin Nilsson  if(undefinedp(res)) error("Could not resolve %s.\n", identifier);
100c3e2003-12-01Martin Nilsson  return res; }
a7e9b92017-12-06Henrik Grubbström (Grubba)  //! Resolve the @[identifier] expression.
6df5a52001-11-07Martin Nilsson  //!
a7e9b92017-12-06Henrik Grubbström (Grubba)  //! @returns //! Returns the value of the @[identifier] if it exists, //! and @[UNDEFINED] otherwise.
34241f2001-05-24Henrik Grubbström (Grubba)  mixed resolv(string identifier, string|void current_file,
26e3592018-07-06Henrik Grubbström (Grubba)  object|void current_handler, object|void current_compat_handler)
97f8142003-09-18Henrik Grubbström (Grubba)  { resolv_debug("resolv(%O, %O)\n",identifier, current_file); INC_RESOLV_MSG_DEPTH();
a20af62000-09-26Fredrik Hübinette (Hubbe) 
97f8142003-09-18Henrik Grubbström (Grubba)  // FIXME: Support having the cache in the handler? if( no_resolv[ identifier ] ) { DEC_RESOLV_MSG_DEPTH(); resolv_debug("resolv(%O, %O) => excluded\n",identifier, current_file); return UNDEFINED; }
26ece22001-06-18Henrik Grubbström (Grubba) 
97f8142003-09-18Henrik Grubbström (Grubba)  if (current_file && !stringp(current_file)) {
26e3592018-07-06Henrik Grubbström (Grubba)  error("resolv(%O, %O, %O, %O): current_file is not a string!\n", identifier, current_file, current_handler, current_compat_handler);
97f8142003-09-18Henrik Grubbström (Grubba)  }
eaa4da2001-10-04Fredrik Hübinette (Hubbe) 
15cb2e2008-02-28Henrik Grubbström (Grubba)  array(string) tmp = identifier/"::"; mixed ret; if (sizeof(tmp) > 1) { string scope = tmp[0];
9eee962008-05-20Henrik Grubbström (Grubba)  tmp = tmp[1]/".";
15cb2e2008-02-28Henrik Grubbström (Grubba)  switch(scope) { case "predef": ret = all_constants(); break; default: if (sscanf(scope, "%d.%d%*s", int major, int minor) == 3) { // Versioned identifier. ret = get_compilation_handler(major, minor); if (ret) {
9eee962008-05-20Henrik Grubbström (Grubba)  mixed mod = ret->get_default_module();
9c628b2014-11-04Martin Nilsson  if (mod && !undefinedp(mod = mod[tmp[0]])) {
9eee962008-05-20Henrik Grubbström (Grubba)  ret = mod;
15cb2e2008-02-28Henrik Grubbström (Grubba)  } else {
9eee962008-05-20Henrik Grubbström (Grubba)  ret = ret->resolv(tmp[0]);
15cb2e2008-02-28Henrik Grubbström (Grubba)  }
9eee962008-05-20Henrik Grubbström (Grubba)  tmp = tmp[1..];
15cb2e2008-02-28Henrik Grubbström (Grubba)  break; } } error("resolv(%O, %O, %O): Unsupported scope: %O!\n", identifier, current_file, current_handler, scope); } } else { tmp = identifier/".";
26e3592018-07-06Henrik Grubbström (Grubba)  ret = resolv_base(tmp[0], current_file, current_handler, current_compat_handler);
15cb2e2008-02-28Henrik Grubbström (Grubba)  tmp = tmp[1..]; } foreach(tmp,string index) {
7749332004-12-27Henrik Grubbström (Grubba)  resolv_debug("indexing %O with %O...\n", ret, index);
7d25782016-10-20Henrik Grubbström (Grubba)  // NB: Running indices() on directory nodes will force them to load // all their content, which is probably NOT what you want... // resolv_debug("indices(%O): %O\n", ret, indices(ret));
65340d2014-08-15Martin Nilsson  if (undefinedp(ret)) break;
97f8142003-09-18Henrik Grubbström (Grubba)  ret = ret[index]; } DEC_RESOLV_MSG_DEPTH();
3c6f582002-05-24Martin Stjernholm #ifdef RESOLV_DEBUG
65340d2014-08-15Martin Nilsson  if (undefinedp (ret))
97f8142003-09-18Henrik Grubbström (Grubba)  resolv_debug("resolv(%O, %O) => not found\n",identifier, current_file); else resolv_debug("resolv(%O, %O) => found %O\n",identifier, current_file, ret);
3c6f582002-05-24Martin Stjernholm #endif /* RESOLV_DEBUG */
97f8142003-09-18Henrik Grubbström (Grubba)  return ret; }
a20af62000-09-26Fredrik Hübinette (Hubbe) 
b784022008-05-28Henrik Grubbström (Grubba) 
9a61da2004-04-20Martin Nilsson  //! This function is called whenever an #include directive is //! encountered. It receives the argument for #include and should
5d533f2018-03-06Henrik Grubbström (Grubba)  //! return the file name of the file to include. //! //! @seealso //! @[read_include()]
a20af62000-09-26Fredrik Hübinette (Hubbe)  string handle_include(string f, string current_file, int local_include)
97f8142003-09-18Henrik Grubbström (Grubba)  { if(local_include)
a20af62000-09-26Fredrik Hübinette (Hubbe)  {
0ee5c62004-01-12Martin Nilsson  if(IS_ABSOLUTE_PATH(f)) return combine_path(f);
15af9c2003-12-19Marcus Comstedt  return combine_path_with_cwd(dirname(current_file), f);
97f8142003-09-18Henrik Grubbström (Grubba)  } else { foreach(pike_include_path, string path)
a20af62000-09-26Fredrik Hübinette (Hubbe)  {
97f8142003-09-18Henrik Grubbström (Grubba)  path=combine_path(path,f); if(master_file_stat(fakeroot(path))) return path;
a20af62000-09-26Fredrik Hübinette (Hubbe)  }
97f8142003-09-18Henrik Grubbström (Grubba)  if (fallback_resolver) { return fallback_resolver->handle_include(f, current_file,
3593292003-09-08Henrik Grubbström (Grubba)  local_include);
a20af62000-09-26Fredrik Hübinette (Hubbe)  } }
97f8142003-09-18Henrik Grubbström (Grubba)  // Failed. return 0; }
6df5a52001-11-07Martin Nilsson 
5d533f2018-03-06Henrik Grubbström (Grubba)  //! Read the file specified by @[handle_include()].
6df5a52001-11-07Martin Nilsson  //!
5d533f2018-03-06Henrik Grubbström (Grubba)  //! @seealso //! @[handle_include()]
a20af62000-09-26Fredrik Hübinette (Hubbe)  string read_include(string f)
97f8142003-09-18Henrik Grubbström (Grubba)  {
c2e10c2003-11-18Martin Stjernholm  AUTORELOAD_CHECK_FILE(f); if (array|object err = catch { return master_read_file (f); }) compile_cb_rethrow (err);
97f8142003-09-18Henrik Grubbström (Grubba)  }
a20af62000-09-26Fredrik Hübinette (Hubbe) 
47ba5a2013-06-03Martin Nilsson  protected string _sprintf(int t)
97f8142003-09-18Henrik Grubbström (Grubba)  { return t=='O' && sprintf("CompatResolver(%O)",ver); }
7c11f41999-10-04Fredrik Hübinette (Hubbe) }
a20af62000-09-26Fredrik Hübinette (Hubbe) inherit CompatResolver;
59f9822018-02-08Henrik Grubbström (Grubba) //! @namespace predef::
97a1522017-03-17Henrik Grubbström (Grubba) //! @class __dirnode //! @decl inherit MasterObject.dirnode //! @endclass //! @class __joinnode //! @decl inherit MasterObject.joinnode //! @endclass //! @decl void add_include_path(string tmp) //! Add a directory to search for include files. //! //! This is the same as the command line option @tt{-I@}. //! //! @note //! Note that the added directory will only be searched when using //! < > to quote the included file. //! //! @seealso //! @[remove_include_path()] //! //! @decl void remove_include_path(string tmp) //! Remove a directory to search for include files. //! //! This function performs the reverse operation of @[add_include_path()]. //! //! @seealso //! @[add_include_path()] //! //! @decl void add_module_path(string path, string|void subpath) //! Add a directory to search for modules. //! //! This is the same as the command line option @tt{-M@}. //! //! @seealso //! @[remove_module_path()] //! //! @param path //! a string containing a path to search for Pike modules. May be a //! directory, or a path to a ZIP archive. If a ZIP archive path is //! provided, modules will be loaded from a directory, "modules" within //! the ZIP archive (see the subpath argument). //! //! @param subpath //! if path is a ZIP archive, this argument will determine the path within //! the archive to be searched. //! //! @decl void remove_module_path(string tmp) //! Remove a directory to search for modules. //! //! This function performs the reverse operation of @[add_module_path()]. //! //! @seealso //! @[add_module_path()] //! //! @decl void add_program_path(string tmp) //! Add a directory to search for programs. //! //! This is the same as the command line option @tt{-P@}. //! //! @seealso //! @[remove_program_path()] //! //! @decl void remove_program_path(string tmp) //! Remove a directory to search for programs. //! //! This function performs the reverse operation of @[add_program_path()]. //! //! @seealso //! @[add_program_path()] //!
59f9822018-02-08Henrik Grubbström (Grubba) //! @endnamespace
97e5c72001-07-28Martin Nilsson //! These are useful if you want to start other Pike processes //! with the same options as this one was started with.
bfa62b1998-04-30Henrik Grubbström (Grubba) string _pike_file_name;
ac51841998-04-29Henrik Grubbström (Grubba) string _master_file_name;
b1d7d92002-01-07Martin Nilsson // Gets set to 1 if we're in async-mode (script->main() returned <0) private int(0..1) _async=0;
53a32a2000-06-04Francesco Chemolli 
7c386d2018-12-08Marcus Comstedt //! Returns 1 if we're in async-mode, e.g. if the main method has
b1d7d92002-01-07Martin Nilsson //! returned a negative number. int(0..1) asyncp() {
53a32a2000-06-04Francesco Chemolli  return _async; }
45c7262001-04-17Mirar (Pontus Hagland) #if constant(thread_create) // this must be done in __init if someone inherits the master
35f51c2008-06-28Martin Nilsson protected object _backend_thread=this_thread();
97e5c72001-07-28Martin Nilsson  //! The backend_thread() function is useful to determine if you are //! the backend thread - important when doing async/sync protocols. //! This method is only available if thread_create is present.
45c7262001-04-17Mirar (Pontus Hagland) object backend_thread() { return _backend_thread; } #endif
70e2ca2003-01-01Martin Nilsson 
97f8142003-09-18Henrik Grubbström (Grubba) mapping(string:string) initial_predefines = ([]);
35f51c2008-06-28Martin Nilsson protected mixed main_resolv(string sym, CompatResolver|void resolver) {
aed1b52005-11-21Martin Nilsson  mixed v = (resolver||this)->resolv(sym); if(!v)
da22f12006-06-08Martin Stjernholm  error("Could not resolve %s. "
aed1b52005-11-21Martin Nilsson  "(Perhaps the installed pike tree has been moved.)\n", sym); return v; };
d9786a2018-11-30William Welliver // TODO: this seems like a backward approach. The debugger should register its completer on startup. // callback for completing breakpoint registration for programs which weren't loaded // at the time of the breakpoint's creation. function deferred_breakpoint_completer; mixed program_loaded(string fn, mixed c) {if(deferred_breakpoint_completer) deferred_breakpoint_completer(fn, c); return c;}
0c1e0c2018-11-29William Welliver void load_debugger(int wait_seconds) {
d9786a2018-11-30William Welliver  want_load_announcements = 1;
00f4802018-11-15William Welliver  set_debugger(1); // load the debugger support function d;
6a83ba2018-11-15William Welliver 
00f4802018-11-15William Welliver  mixed err = catch {
6a83ba2018-11-15William Welliver  function f = main_resolv("Debug.debug", get_compilation_handler(compat_major, compat_minor)); }; if(err) { werror("Debugging is only available when Pike is compiled with RTL debug.\n"); exit(1); }
d9786a2018-11-30William Welliver  err = catch { deferred_breakpoint_completer = main_resolv("Debug.Debugger.deferred_breakpoint_completer", get_compilation_handler(compat_major, compat_minor)); }; if(err) { werror("Unable to load the deferred breakpoint completer\n"); werror(describe_backtrace(err)); exit(1); }
6a83ba2018-11-15William Welliver  err = catch {
00f4802018-11-15William Welliver  d = main_resolv("Debug.Debugger.debug_server",
6a83ba2018-11-15William Welliver  get_compilation_handler(compat_major, compat_minor));
00f4802018-11-15William Welliver  }; if(!d){ werror("Unable to load debugger.\n"); throw(d); } debugger = d();
0c1e0c2018-11-29William Welliver  debugger->load_breakpoint(wait_seconds);
00f4802018-11-15William Welliver }
97e5c72001-07-28Martin Nilsson //! This function is called when all the driver is done with all setup //! of modules, efuns, tables etc. etc. and is ready to start executing
b3926d2008-06-05Martin Stjernholm //! _real_ programs. It receives the arguments not meant for the driver.
d712e32013-11-30Henrik Grubbström (Grubba) void _main(array(string(0..255)) orig_argv)
ca2b071998-03-28Henrik Grubbström (Grubba) {
afa1292000-02-19Martin Nilsson  array(string) argv=copy_value(orig_argv);
5048622003-04-10Martin Nilsson  int debug,trace,run_tool;
ca2b071998-03-28Henrik Grubbström (Grubba)  object tmp;
c05dc42002-09-05Marcus Comstedt  string postparseaction=0;
ca2b071998-03-28Henrik Grubbström (Grubba) 
97f8142003-09-18Henrik Grubbström (Grubba)  predefines = initial_predefines =
7d016d2008-03-26Henrik Grubbström (Grubba)  Builtin._take_over_initial_predefines();
bfa62b1998-04-30Henrik Grubbström (Grubba)  _pike_file_name = orig_argv[0];
91ac562011-09-07Martin Stjernholm  _master_file_name = __FILE__;
45c7262001-04-17Mirar (Pontus Hagland) #if constant(thread_create) _backend_thread = this_thread(); #endif
bfa62b1998-04-30Henrik Grubbström (Grubba) 
e90a8b1999-06-01Mirar (Pontus Hagland) #ifndef NOT_INSTALLED
5048622003-04-10Martin Nilsson  {
929cf72003-08-19Martin Nilsson  array parts = (getenv("PIKE_INCLUDE_PATH")||"")/PATH_SEPARATOR-({""});
5048622003-04-10Martin Nilsson  int i = sizeof(parts); while(i) add_include_path(parts[--i]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
929cf72003-08-19Martin Nilsson  parts = (getenv("PIKE_PROGRAM_PATH")||"")/PATH_SEPARATOR-({""});
5048622003-04-10Martin Nilsson  i = sizeof(parts); while(i) add_program_path(parts[--i]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
929cf72003-08-19Martin Nilsson  parts = (getenv("PIKE_MODULE_PATH")||"")/PATH_SEPARATOR-({""});
5048622003-04-10Martin Nilsson  i = sizeof(parts); while(i) add_module_path(parts[--i]); }
e90a8b1999-06-01Mirar (Pontus Hagland) #endif
da2ddc2002-08-11Martin Nilsson  // Some configure scripts depends on this format.
4619bd2002-07-29Martin Nilsson  string format_paths() {
25c0a82002-08-11Per Hedbor  return ("master.pike...: " + (_master_file_name || __FILE__) + "\n" "Module path...: " + pike_module_path*"\n"
020d002002-08-15Per Hedbor  " " + "\n"
25c0a82002-08-11Per Hedbor  "Include path..: " + pike_include_path*"\n"
020d002002-08-15Per Hedbor  " " + "\n"
25c0a82002-08-11Per Hedbor  "Program path..: " + pike_program_path*"\n"
020d002002-08-15Per Hedbor  " " + "\n");
4619bd2002-07-29Martin Nilsson  };
b3926d2008-06-05Martin Stjernholm  Version cur_compat_ver;
0c1e0c2018-11-29William Welliver  int have_debugger = 0; int debugger_wait = 5; // 5 seconds by default
ca2b071998-03-28Henrik Grubbström (Grubba)  if(sizeof(argv)>1 && sizeof(argv[1]) && argv[1][0]=='-') {
5048622003-04-10Martin Nilsson  array q;
27a23d2003-01-27Martin Nilsson  tmp = main_resolv( "Getopt" );
8c03142002-11-15Martin Nilsson  int NO_ARG = tmp->NO_ARG; int MAY_HAVE_ARG = tmp->MAY_HAVE_ARG; int HAS_ARG = tmp->HAS_ARG;
a7a45a1998-05-11Henrik Grubbström (Grubba) 
ca2b071998-03-28Henrik Grubbström (Grubba)  q=tmp->find_all_options(argv,({
8c03142002-11-15Martin Nilsson  ({"compat_version", HAS_ARG, ({"-V", "--compat"}), 0, 0}), ({"version", NO_ARG, ({"-v", "--version"}), 0, 0}),
64ff312003-04-03Martin Nilsson  ({"dumpversion", NO_ARG, ({"--dumpversion"}), 0, 0}),
d62eab2003-09-18Martin Nilsson  ({"help", MAY_HAVE_ARG, ({"-h", "--help"}), 0, 0}),
8c03142002-11-15Martin Nilsson  ({"features", NO_ARG, ({"--features"}), 0, 0}), ({"info", NO_ARG, ({"--info"}), 0, 0}), ({"execute", HAS_ARG, ({"-e", "--execute"}), 0, 0}), ({"debug_without", HAS_ARG, ({"--debug-without"}), 0, 0}), ({"preprocess", HAS_ARG, ({"-E", "--preprocess"}), 0, 0}), ({"modpath", HAS_ARG, ({"-M", "--module-path"}), 0, 0}), ({"ipath", HAS_ARG, ({"-I", "--include-path"}), 0, 0}), ({"ppath", HAS_ARG, ({"-P", "--program-path"}), 0, 0}),
9e83d32008-06-29Martin Nilsson  ({"showpaths", MAY_HAVE_ARG, ({"--show-paths"}), 0, 0}),
8c03142002-11-15Martin Nilsson  ({"warnings", NO_ARG, ({"-w", "--warnings"}), 0, 0}), ({"nowarnings", NO_ARG, ({"-W", "--woff", "--no-warnings"}), 0, 0}), ({"autoreload", NO_ARG, ({"--autoreload"}), 0, 0}), ({"master", HAS_ARG, ({"-m"}), 0, 0}), ({"compiler_trace", NO_ARG, ({"--compiler-trace"}), 0, 0}), ({"assembler_debug",MAY_HAVE_ARG, ({"--assembler-debug"}), 0, 0}), ({"optimizer_debug",MAY_HAVE_ARG, ({"--optimizer-debug"}), 0, 0}),
00f4802018-11-15William Welliver  ({"debugger", MAY_HAVE_ARG, ({"--debugger"}), 0, 1}),
0c1e0c2018-11-29William Welliver  ({"debugger_wait", HAS_ARG, ({"--debugger-wait"}), 0, 1}),
8c03142002-11-15Martin Nilsson  ({"debug", MAY_HAVE_ARG, ({"--debug"}), 0, 1}), ({"trace", MAY_HAVE_ARG, ({"--trace"}), 0, 1}), ({"ignore", MAY_HAVE_ARG, ({"-Dqdatplr"}), 0, 1}), ({"ignore", HAS_ARG, ({"-s"}), 0, 0}), ({"run_tool", NO_ARG, ({"-x"}), 0, 0}),
b73de52004-11-05Martin Nilsson  ({"show_cpp_warn", NO_ARG, ({"--show-all-cpp-warnings","--picky-cpp"}), 0, 0}),
c5cc2d1998-04-29Henrik Grubbström (Grubba)  }), 1);
eba0232004-01-13Martin Nilsson 
ca2b071998-03-28Henrik Grubbström (Grubba)  /* Parse -M and -I backwards */
5048622003-04-10Martin Nilsson  for(int i=sizeof(q)-1; i>=0; i--)
ca2b071998-03-28Henrik Grubbström (Grubba)  { switch(q[i][0]) {
a20af62000-09-26Fredrik Hübinette (Hubbe)  case "compat_version": sscanf(q[i][1],"%d.%d",compat_major,compat_minor); break;
8c03142002-11-15Martin Nilsson 
bec57d1999-09-06Fredrik Hübinette (Hubbe) #ifdef PIKE_AUTORELOAD case "autoreload": autoreload_on++;
631e282003-05-28Johan Sundström  break;
bec57d1999-09-06Fredrik Hübinette (Hubbe) #endif
8c03142002-11-15Martin Nilsson 
3d14462000-09-24Per Hedbor  case "debug_without":
1a67ea2003-07-22Martin Nilsson  // FIXME: Disable loading of dumped modules?
3d14462000-09-24Per Hedbor  foreach( q[i][1]/",", string feature ) { switch( feature ) { case "ttf": no_resolv[ "_Image_TTF" ] = 1; break; case "zlib": no_resolv[ "Gz" ] = 1; break; case "unisys": no_resolv[ "_Image_GIF" ] = 1; no_resolv[ "_Image_TIFF" ] = 1; break; case "threads": // not really 100% correct, but good enough for most things. no_resolv[ "Thread" ] = 1;
f595e92003-01-01Martin Nilsson  add_constant( "thread_create" );
3d14462000-09-24Per Hedbor  break; default: no_resolv[ feature ] = 1; break; } } break;
8c03142002-11-15Martin Nilsson 
c5cc2d1998-04-29Henrik Grubbström (Grubba)  case "debug":
0c1e0c2018-11-29William Welliver  debug+=(int)q[i][1]; break;
00f4802018-11-15William Welliver  case "debugger":
0c1e0c2018-11-29William Welliver  have_debugger = 1; break; case "debugger_wait": debugger_wait = (int)q[i][1]; break;
c5cc2d1998-04-29Henrik Grubbström (Grubba)  case "trace":
0c1e0c2018-11-29William Welliver  trace+=(int)q[i][1]; break;
862fb41998-04-05Fredrik Hübinette (Hubbe) 
ca2b071998-03-28Henrik Grubbström (Grubba)  case "modpath": add_module_path(q[i][1]); break;
eba0232004-01-13Martin Nilsson 
ca2b071998-03-28Henrik Grubbström (Grubba)  case "ipath": add_include_path(q[i][1]); break;
eba0232004-01-13Martin Nilsson 
ca2b071998-03-28Henrik Grubbström (Grubba)  case "ppath": add_program_path(q[i][1]); break;
c5cc2d1998-04-29Henrik Grubbström (Grubba)  case "warnings":
ca2b071998-03-28Henrik Grubbström (Grubba)  want_warnings++; break;
ac51841998-04-29Henrik Grubbström (Grubba) 
b714e12002-09-05Marcus Comstedt  case "nowarnings":
098c8a2000-03-30Henrik Grubbström (Grubba)  want_warnings--; break;
ac51841998-04-29Henrik Grubbström (Grubba)  case "master": _master_file_name = q[i][1]; break;
66dca02002-09-05Marcus Comstedt  case "run_tool":
c05dc42002-09-05Marcus Comstedt  run_tool = 1;
66dca02002-09-05Marcus Comstedt  break;
f6da7b2004-06-27Martin Nilsson  case "show_cpp_warn": show_if_constant_errors = 1; break;
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
0c1e0c2018-11-29William Welliver  if(have_debugger) { load_debugger(debugger_wait); set_debugger(1); }
b3926d2008-06-05Martin Stjernholm  cur_compat_ver = Version (compat_major, compat_minor);
0d34dc2014-08-10Martin Nilsson  if (cur_compat_ver < lowestcompat) { werror("This Pike only supports compatibility down to %s.\n", (string)lowestcompat); cur_compat_ver = lowestcompat; compat_major = lowestcompat->major; compat_minor = lowestcompat->minor; }
b3926d2008-06-05Martin Stjernholm  if (compat_major != -1) { object compat_master = get_compat_master (compat_major, compat_minor); }
afa1292000-02-19Martin Nilsson  foreach(q, array opts)
ca2b071998-03-28Henrik Grubbström (Grubba)  { switch(opts[0]) {
64ff312003-04-03Martin Nilsson  case "dumpversion": write("%d.%d.%d\n", __REAL_MAJOR__, __REAL_MINOR__, __REAL_BUILD__);
9e83d32008-06-29Martin Nilsson  exit(0);
64ff312003-04-03Martin Nilsson 
ca2b071998-03-28Henrik Grubbström (Grubba)  case "version":
7c386d2018-12-08Marcus Comstedt  exit(0, version() + " Copyright © 1994-2018 Linköping University\n"
b47fb62009-11-13Per Hedbor  "Pike comes with ABSOLUTELY NO WARRANTY; This is free software and you are\n" "welcome to redistribute it under certain conditions; read the files\n"
7c386d2018-12-08Marcus Comstedt  "COPYING and COPYRIGHT in the Pike distribution for more details.\n");
eba0232004-01-13Martin Nilsson 
ca2b071998-03-28Henrik Grubbström (Grubba)  case "help":
9e83d32008-06-29Martin Nilsson  exit( 0, main_resolv("Tools.MasterHelp")->do_help(opts[1]) );
eba0232004-01-13Martin Nilsson 
94c8552001-01-19Mirar (Pontus Hagland)  case "features":
a6b6df2001-01-19Mirar (Pontus Hagland)  postparseaction="features"; break; case "info": postparseaction="info";
94c8552001-01-19Mirar (Pontus Hagland)  break;
2ea8261998-05-12Martin Stjernholm  case "showpaths":
9e83d32008-06-29Martin Nilsson  if( stringp(opts[1]) ) { switch(opts[1]) { case "master": write( (_master_file_name || __FILE__)+"\n" ); break; case "module": write( (pike_module_path * ":")+"\n" ); break; case "include": write( (pike_include_path * ":")+"\n" ); break; case "program": write( (pike_program_path * ":")+"\n" ); break; default: exit(1, "Unknown path type %s\n", opts[1]); } exit(0); } exit(0, format_paths());
eba0232004-01-13Martin Nilsson 
ca2b071998-03-28Henrik Grubbström (Grubba)  case "execute":
3bc9eb2004-02-27Martin Nilsson  main_resolv( "Gmp.bignum" );
2064412016-01-17Martin Nilsson  argv = tmp->get_args(argv,1);
3215c92003-05-15Henrik Grubbström (Grubba) 
f9a0962003-03-20Martin Stjernholm  program prog;
729acf2008-05-30Martin Stjernholm  mixed compile_err = catch {;
8732142014-10-05Martin Nilsson  if (intp (opts[1]))
729acf2008-05-30Martin Stjernholm  prog = compile_string ("mixed run() {}"); else { string code = opts[1]; while(sscanf(code, "%sCHAR(%1s)%s", code, string c, string rest)==3) code += c[0] + rest;
8732142014-10-05Martin Nilsson  prog = compile_string(
b3926d2008-06-05Martin Stjernholm  "#define NOT(X) !(X)\n" "mixed run(int argc, array(string) argv){" + code + ";}");
729acf2008-05-30Martin Stjernholm  } };
be62e62008-05-30Henrik Grubbström (Grubba)  if (compile_err) { if (compile_err->is_cpp_or_compilation_error) { // Don't clutter the output with the backtrace for // compilation errors.
86e66a2010-05-06Henrik Grubbström (Grubba)  exit (20, call_describe_error (compile_err));
be62e62008-05-30Henrik Grubbström (Grubba)  } else throw (compile_err);
d385d72004-05-01Martin Nilsson  }
f9a0962003-03-20Martin Stjernholm  #if constant(_debug) if(debug) _debug(debug); #endif
97f8142003-09-18Henrik Grubbström (Grubba)  if(trace) trace = predef::trace(trace);
00f4802018-11-15William Welliver 
f9a0962003-03-20Martin Stjernholm  mixed ret; mixed err = catch { // One reason for this catch is to get a new call to // eval_instruction in interpret.c so that the debug and // trace levels set above take effect in the bytecode // evaluator.
8732142014-10-05Martin Nilsson  ret = prog()->run(sizeof(argv),argv);
f9a0962003-03-20Martin Stjernholm  };
97f8142003-09-18Henrik Grubbström (Grubba)  predef::trace(trace);
f9a0962003-03-20Martin Stjernholm  if (err) { handle_error (err); ret = 10; }
70e2ca2003-01-01Martin Nilsson  if(stringp(ret)) { write(ret); if(ret[-1]!='\n') write("\n"); }
2ac59e2002-12-29Martin Nilsson  if(!intp(ret) || ret<0) ret=0; exit(ret);
fcf7281998-04-28Fredrik Hübinette (Hubbe) 
c5cc2d1998-04-29Henrik Grubbström (Grubba)  case "preprocess":
3bc9eb2004-02-27Martin Nilsson  main_resolv( "Gmp.bignum" );
70e2ca2003-01-01Martin Nilsson  write(cpp(master_read_file(opts[1]),opts[1]));
c5cc2d1998-04-29Henrik Grubbström (Grubba)  exit(0);
639ada2016-08-07Henrik Grubbström (Grubba)  case "compiler_trace": function(int:void) compiler_trace = main_resolv("Debug.compiler_trace"); if (compiler_trace) { compiler_trace(1); } break; case "assembler_debug": function(int:void) assembler_debug = main_resolv("Debug.assembler_debug"); if (assembler_debug) { assembler_debug((int)opts[1]); } break; case "optimizer_debug": function(int:void) optimizer_debug = main_resolv("Debug.optimizer_debug"); if (optimizer_debug) { optimizer_debug((int)opts[1]); } break;
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
caa3221998-04-15Henrik Grubbström (Grubba)  argv = tmp->get_args(argv,1);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
b3926d2008-06-05Martin Stjernholm  else cur_compat_ver = Version (compat_major, compat_minor);
ca2b071998-03-28Henrik Grubbström (Grubba) 
a6b6df2001-01-19Mirar (Pontus Hagland)  switch (postparseaction)
94c8552001-01-19Mirar (Pontus Hagland)  {
a6b6df2001-01-19Mirar (Pontus Hagland)  case "features":
3bc9eb2004-02-27Martin Nilsson  write( main_resolv( "Tools.Install.features" )()*"\n"+"\n" );
70e2ca2003-01-01Martin Nilsson  exit(0);
a6b6df2001-01-19Mirar (Pontus Hagland)  case "info":
70e2ca2003-01-01Martin Nilsson  write("Software......Pike\n" "Version......."+version()+"\n"
3032b42011-03-06Henrik Grubbström (Grubba)  "WWW...........http://pike.lysator.liu.se/\n"
70e2ca2003-01-01Martin Nilsson  "\n" "pike binary..."+_pike_file_name+"\n"+ format_paths() + "\n" "Features......"+
3bc9eb2004-02-27Martin Nilsson  main_resolv( "Tools.Install.features" )()*"\n "+
70e2ca2003-01-01Martin Nilsson  "\n");
a6b6df2001-01-19Mirar (Pontus Hagland)  exit(0);
94c8552001-01-19Mirar (Pontus Hagland)  }
3bc9eb2004-02-27Martin Nilsson  main_resolv( "Gmp.bignum" );
9339fc2000-01-09Fredrik Hübinette (Hubbe) 
c05dc42002-09-05Marcus Comstedt  if(sizeof(argv)==1)
ca2b071998-03-28Henrik Grubbström (Grubba)  {
db77fa2002-12-14Martin Nilsson  if(run_tool) { werror("Pike -x specificed without tool name.\n" "Available tools:\n"); mapping t = ([]); int i;
f306b12005-04-15Henrik Grubbström (Grubba)  object ts = main_resolv("Tools.Standalone", get_compilation_handler(compat_major, compat_minor));
6e2cfd2003-10-08Martin Stjernholm  foreach (indices(ts), string s) { mixed val = ts[s]; if (programp (val)) { object o = val();
22ac452008-06-28Per Hedbor  if(!o->main || !o->description) continue; t[s] = o->description;
6e2cfd2003-10-08Martin Stjernholm  i = max(i, sizeof(s)); }
db77fa2002-12-14Martin Nilsson  } foreach(sort(indices(t)), string s) werror(" %-"+i+"s %s\n", s, t[s]); exit(1); }
f306b12005-04-15Henrik Grubbström (Grubba)  main_resolv("Tools.Hilfe", get_compilation_handler(compat_major, compat_minor))->StdinHilfe();
caa3221998-04-15Henrik Grubbström (Grubba)  exit(0);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
4619bd2002-07-29Martin Nilsson  else argv=argv[1..];
ca2b071998-03-28Henrik Grubbström (Grubba) 
586d1c2000-09-04Fredrik Hübinette (Hubbe)  program prog;
34fb3d1998-10-31Henrik Grubbström (Grubba) 
66dca02002-09-05Marcus Comstedt  if(run_tool) { mixed err = catch {
f306b12005-04-15Henrik Grubbström (Grubba)  prog = main_resolv("Tools.Standalone." + argv[0], get_compilation_handler(compat_major, compat_minor));
66dca02002-09-05Marcus Comstedt  }; if (err)
d8674e2007-12-28Martin Nilsson  exit(1, "Pike: Failed to load tool %s:\n" "%s\n", argv[0],
86e66a2010-05-06Henrik Grubbström (Grubba)  stringp(err[0])?err[0]:call_describe_backtrace(err));
66dca02002-09-05Marcus Comstedt 
57b52d2003-05-31Martin Stjernholm  argv[0] = search(programs, prog) || argv[0];
66dca02002-09-05Marcus Comstedt  } else { argv[0]=combine_path_with_cwd(argv[0]); mixed err = catch { prog=(program)argv[0]; };
f6da7b2004-06-27Martin Nilsson  if (err) {
d8674e2007-12-28Martin Nilsson  string fn = argv[0]; if( !file_stat(fn) ) { if( file_stat(fn+".pike") ) fn += ".pike"; else
9f220b2008-05-12Henrik Grubbström (Grubba)  exit(1, "Could not find file %O.\n", fn);
d8674e2007-12-28Martin Nilsson  } if( !file_stat(fn)->isreg ) exit(1, "File %O is not a regular file.\n", fn); if( !master_read_file(fn) )
8490d22016-11-05Martin Nilsson  exit(1, "File %O is not readable. %s.\n", fn, strerror(errno()));
729acf2008-05-30Martin Stjernholm  if (objectp (err) && err->is_cpp_or_compilation_error) exit(1, "Pike: Failed to compile script.\n"); else exit(1, "Pike: Failed to compile script:\n"
86e66a2010-05-06Henrik Grubbström (Grubba)  "%s", call_describe_backtrace(err));
f6da7b2004-06-27Martin Nilsson  }
39979e2004-09-06Martin Stjernholm  // Don't list the program with its real path in the programs // mapping, so that reverse lookups (typically by the codec) // always find the canonical "/main" instead.
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, argv[0], no_value);
66dca02002-09-05Marcus Comstedt  }
34fb3d1998-10-31Henrik Grubbström (Grubba) 
d9786a2018-11-30William Welliver  PROGRAM_LOADED(programs, "/main", prog);
39979e2004-09-06Martin Stjernholm 
d8674e2007-12-28Martin Nilsson  // FIXME: Can this occur at all?
586d1c2000-09-04Fredrik Hübinette (Hubbe)  if(!prog)
3bc9eb2004-02-27Martin Nilsson  error("Pike: Couldn't find script to execute\n(%O)\n", argv[0]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
862fb41998-04-05Fredrik Hübinette (Hubbe) #if constant(_debug) if(debug) _debug(debug); #endif
97f8142003-09-18Henrik Grubbström (Grubba)  if(trace) trace = predef::trace(trace);
5048622003-04-10Martin Nilsson  mixed ret;
f9a0962003-03-20Martin Stjernholm  mixed err = catch { // The main reason for this catch is actually to get a new call // to eval_instruction in interpret.c so that the debug and // trace levels set above take effect in the bytecode evaluator.
808d712009-12-28Martin Stjernholm  // Note that it won't work if there's another catch surrounding // this one.
41d0af2003-04-10Martin Nilsson  object script;
8732142014-10-05Martin Nilsson  script=prog(argv);
f9a0962003-03-20Martin Stjernholm  if(!script->main)
3bc9eb2004-02-27Martin Nilsson  error("Error: %s has no main().\n", argv[0]);
8732142014-10-05Martin Nilsson  if (cur_compat_ver <= Version (8, 0))
d712e32013-11-30Henrik Grubbström (Grubba)  ret = script->main(sizeof(argv),argv);
b3926d2008-06-05Martin Stjernholm  else
fc76bf2013-11-30Martin Nilsson  {
d712e32013-11-30Henrik Grubbström (Grubba)  mixed first_arg = __get_first_arg_type(_typeof(script->main)); // NB: first_arg may be zero eg in case main() ignores all args. if( first_arg && (typeof(argv) <= first_arg) ) { // argv accepted as first argument.
fc76bf2013-11-30Martin Nilsson  ret=script->main(argv);
d712e32013-11-30Henrik Grubbström (Grubba)  } else
fc76bf2013-11-30Martin Nilsson  ret=script->main(sizeof(argv),argv); }
f9a0962003-03-20Martin Stjernholm  };
ead42e2004-07-04Martin Stjernholm  // Disable tracing.
b440ab2004-02-08Henrik Grubbström (Grubba)  trace = predef::trace(trace);
f9a0962003-03-20Martin Stjernholm  if (err) { handle_error (err);
5048622003-04-10Martin Nilsson  ret = 10;
f9a0962003-03-20Martin Stjernholm  }
9e83d32008-06-29Martin Nilsson  if(!intp(ret)) exit(10, "Error: Non-integer value %O returned from main.\n", ret);
5048622003-04-10Martin Nilsson  if(ret >=0) exit([int]ret);
53a32a2000-06-04Francesco Chemolli  _async=1;
eba0232004-01-13Martin Nilsson 
b440ab2004-02-08Henrik Grubbström (Grubba)  // Reenable tracing. trace = predef::trace(trace);
87f9082001-03-12Fredrik Hübinette (Hubbe)  while(1) {
3524712015-05-26Martin Nilsson  mixed err=catch
87f9082001-03-12Fredrik Hübinette (Hubbe)  { while(1)
677d262003-11-14Martin Stjernholm  Builtin.__backend(3600.0);
87f9082001-03-12Fredrik Hübinette (Hubbe)  }; master()->handle_error(err); }
ca2b071998-03-28Henrik Grubbström (Grubba) }
01d3c91999-11-04Henrik Grubbström (Grubba) #if constant(thread_local) object inhibit_compile_errors = thread_local();
c63b2d2013-01-23Henrik Grubbström (Grubba) //! Set the compile error, warning and exception behaviour. //! //! @param behaviour //! The desired behaviour. One of: //! @mixed //! @type int(0..0) //! Output compilation errors and warnings to @tt{stderr@}. //! This is the default behaviour. //! @type int(1..1) //! Inhibit output of compilator diagnostics. //! @type function(string, int, string:void) //! Function to call for compilation errors. Compilation //! warnings and exceptions are inhibited. //! //! The function will be called with the same arguments //! as those passed to @[compile_error()]. //! @type CompilationHandler //! Compilation handler to use for diagnostics. //! @endmixed //! //! @note //! Note that the behaviour is thread local, and is not copied //! to new threads when they are created. //! //! @seealso //! @[get_inhibit_compile_errors()] void set_inhibit_compile_errors(mixed behaviour)
01d3c91999-11-04Henrik Grubbström (Grubba) {
c63b2d2013-01-23Henrik Grubbström (Grubba)  inhibit_compile_errors->set(behaviour);
01d3c91999-11-04Henrik Grubbström (Grubba) }
71d9951999-11-29Henrik Grubbström (Grubba) 
c63b2d2013-01-23Henrik Grubbström (Grubba) //! Get the current compile error, warning and exception behaviour. //! //! See @[set_inhibit_compile_errors()] for details. //! //! @seealso //! @[set_inhibit_compile_errors()]
71d9951999-11-29Henrik Grubbström (Grubba) mixed get_inhibit_compile_errors() {
c2eb4a1999-11-29David Hedbor  return inhibit_compile_errors->get();
71d9951999-11-29Henrik Grubbström (Grubba) }
01d3c91999-11-04Henrik Grubbström (Grubba) #else /* !constant(thread_local) */
ca2b071998-03-28Henrik Grubbström (Grubba) mixed inhibit_compile_errors; void set_inhibit_compile_errors(mixed f) { inhibit_compile_errors=f; }
71d9951999-11-29Henrik Grubbström (Grubba)  mixed get_inhibit_compile_errors() {
c2eb4a1999-11-29David Hedbor  return inhibit_compile_errors;
71d9951999-11-29Henrik Grubbström (Grubba) }
01d3c91999-11-04Henrik Grubbström (Grubba) #endif /* constant(thread_local) */
ca2b071998-03-28Henrik Grubbström (Grubba) 
35f51c2008-06-28Martin Nilsson protected private function(string:string) _trim_file_name_cb=0;
ca2b071998-03-28Henrik Grubbström (Grubba) string trim_file_name(string s) {
4839dd2001-09-02Marcus Comstedt #ifdef PIKE_MODULE_RELOC s = relocate_module(s); #endif
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  if(getenv("LONG_PIKE_ERRORS")) return s;
471ed91998-04-24Fredrik Hübinette (Hubbe)  if(getenv("SHORT_PIKE_ERRORS")) return BASENAME(s);
0024f92001-06-06Mirar (Pontus Hagland)  if (_trim_file_name_cb) return _trim_file_name_cb(s);
df2c632000-08-02Henrik Grubbström (Grubba)  /* getcwd() can fail, but since this is called from handle_error(), * we don't want to fail, so we don't care about that. */ catch { string cwd=getcwd(); if (sizeof(cwd) && (cwd[-1] != '/')) { cwd += "/"; }
28351b2003-05-31Martin Stjernholm  if(has_prefix (s, cwd)) return s[sizeof(cwd)..];
df2c632000-08-02Henrik Grubbström (Grubba)  };
ca2b071998-03-28Henrik Grubbström (Grubba)  return s; }
0024f92001-06-06Mirar (Pontus Hagland) function(string:string) set_trim_file_name_callback(function(string:string) s) { function(string:string) f=_trim_file_name_cb; _trim_file_name_cb=s; return f; }
97e5c72001-07-28Martin Nilsson 
677d262003-11-14Martin Stjernholm //! This function is called whenever a compile error occurs. @[line] //! is zero for errors that aren't associated with any specific line. //! @[err] is not newline terminated.
c63b2d2013-01-23Henrik Grubbström (Grubba) //! //! @seealso //! @[compile_warning()], @[compile_exception()], //! @[get_inhibit_compile_errors()], @[set_inhibit_compile_errors()],
ca2b071998-03-28Henrik Grubbström (Grubba) void compile_error(string file,int line,string err) {
01d3c91999-11-04Henrik Grubbström (Grubba)  mixed val;
3112422000-03-27Per Hedbor  if(! (val = get_inhibit_compile_errors() ))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
2f520e2002-04-28Martin Nilsson  werror( "%s:%s:%s\n",trim_file_name(file),
4f8b1f2013-06-28Henrik Grubbström (Grubba)  line?(string)line:"-",narrowify_string(err) );
ca2b071998-03-28Henrik Grubbström (Grubba)  }
01d3c91999-11-04Henrik Grubbström (Grubba)  else if(objectp(val) || programp(val) || functionp(val))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
01d3c91999-11-04Henrik Grubbström (Grubba)  if (objectp(val) && val->compile_error) { val->compile_error(file, line, err);
71f4fe2008-05-01Martin Nilsson  } else if (callablep(val)) {
3112422000-03-27Per Hedbor  val(file, line, err);
01d3c91999-11-04Henrik Grubbström (Grubba)  }
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
97e5c72001-07-28Martin Nilsson 
677d262003-11-14Martin Stjernholm //! This function is called whenever a compile warning occurs. @[line] //! is zero for warnings that aren't associated with any specific //! line. @[err] is not newline terminated.
c63b2d2013-01-23Henrik Grubbström (Grubba) //! //! @seealso //! @[compile_error()], @[compile_exception()], //! @[get_inhibit_compile_errors()], @[set_inhibit_compile_errors()],
ca2b071998-03-28Henrik Grubbström (Grubba) void compile_warning(string file,int line,string err) {
01d3c91999-11-04Henrik Grubbström (Grubba)  mixed val;
3112422000-03-27Per Hedbor  if(!(val = get_inhibit_compile_errors() ))
ca2b071998-03-28Henrik Grubbström (Grubba)  { if(want_warnings)
2f520e2002-04-28Martin Nilsson  werror( "%s:%s: Warning: %s\n",trim_file_name(file),
4f8b1f2013-06-28Henrik Grubbström (Grubba)  line?(string)line:"-",narrowify_string(err) );
2f520e2002-04-28Martin Nilsson  } else if (objectp(val) && val->compile_warning) {
23184f2003-04-30Martin Nilsson  ([function(string,int,string:void)]([object]val) ->compile_warning)(file, line, err);
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
97e5c72001-07-28Martin Nilsson 
152a622010-02-22Stephen R. van den Berg //! This function is called when an exception is caught during
8594c82001-08-15Martin Stjernholm //! compilation. Its message is also reported to @[compile_error] if //! this function returns zero.
c63b2d2013-01-23Henrik Grubbström (Grubba) //! //! @seealso //! @[compile_error()], @[compile_warning()], //! @[get_inhibit_compile_errors()], @[set_inhibit_compile_errors()],
8594c82001-08-15Martin Stjernholm int compile_exception (array|object trace) {
729acf2008-05-30Martin Stjernholm  if (objectp (trace) && ([object]trace)->is_cpp_or_compilation_error) // Errors thrown by cpp(), compile() or a compile callback should // be reported as a normal compile error, so let the caller do // just that.
677d262003-11-14Martin Stjernholm  return 0;
8594c82001-08-15Martin Stjernholm  if (mixed val = get_inhibit_compile_errors()) {
23184f2003-04-30Martin Nilsson  if (objectp(val) && ([object]val)->compile_exception) return ([function(object:int)]([object]val) ->compile_exception)([object]trace);
8594c82001-08-15Martin Stjernholm  } else { handle_error (trace); return 1; } return 0; }
97e5c72001-07-28Martin Nilsson //! Called for every runtime warning. The first argument identifies //! where the warning comes from, the second identifies the specific //! message, and the rest depends on that. See code below for currently //! implemented warnings.
8f23062000-06-09Martin Stjernholm void runtime_warning (string where, string what, mixed... args) { if (want_warnings) switch (where + "." + what) { case "gc.bad_cycle": // args[0] is an array containing the objects in the cycle
c071bc2017-11-05Henrik Grubbström (Grubba)  // which aren't destructed and have _destruct() functions.
3c6f582002-05-24Martin Stjernholm #if 0 // Ignore this warning for now since we do not yet have a weak // modifier, so it can't be avoided in a reasonable way.
c071bc2017-11-05Henrik Grubbström (Grubba)  werror ("GC warning: Garbing cycle where _destruct() will be called "
8f23062000-06-09Martin Stjernholm  "in arbitrary order:\n%{ %s\n%}",
d3a3322002-11-23Marcus Comstedt  sprintf("%O", args[0][*]));
3c6f582002-05-24Martin Stjernholm #endif
8f23062000-06-09Martin Stjernholm  break; default: werror ("%s warning: %s %O\n", capitalize (where), what, args); } }
ca2b071998-03-28Henrik Grubbström (Grubba) 
35f51c2008-06-28Martin Nilsson protected object Charset;
97e5c72001-07-28Martin Nilsson  //! This function is called by cpp() when it wants to do //! character code conversion.
f4f08d1999-02-26Henrik Grubbström (Grubba) string decode_charset(string data, string charset) {
bd8e1a2006-01-19Henrik Grubbström (Grubba)  if (!Charset) {
0b8d2f2013-06-17Martin Nilsson  Charset = [object]resolv("Charset");
bd8e1a2006-01-19Henrik Grubbström (Grubba)  if (!Charset)
0b8d2f2013-06-17Martin Nilsson  compile_cb_error("Cannot handle charset - no Charset module found.");
f4f08d1999-02-26Henrik Grubbström (Grubba)  }
677d262003-11-14Martin Stjernholm  if (mixed err = catch {
bd8e1a2006-01-19Henrik Grubbström (Grubba)  object decoder = ([function(string:object)]Charset.decoder)(charset);
677d262003-11-14Martin Stjernholm  return ([function(void:string)]([function(string:object)]decoder-> feed)(data)->drain)(); }) compile_cb_rethrow (err);
f4f08d1999-02-26Henrik Grubbström (Grubba) }
bf24c92018-05-19Arne Goedeke //! Class used by @[describe_backtrace()] to describe values in backtraces.
da0a822000-08-29Martin Stjernholm class Describer
ca2b071998-03-28Henrik Grubbström (Grubba) {
da0a822000-08-29Martin Stjernholm  int clipped=0; int canclip=0; mapping(mixed:int|string) ident = ([]); int identcount = 0; void identify_parts (mixed stuff) {
9f71092000-11-20Martin Stjernholm  // Use an array as stack here instead of recursing directly; we // might be pressed for stack space if the backtrace being // described is a stack overflow. array identify_stack = ({stuff}); while (sizeof (identify_stack)) { stuff = identify_stack[-1];
35320b2004-10-30Martin Stjernholm  identify_stack = identify_stack[..<1];
54f7af2006-12-07Henrik Grubbström (Grubba)  if (!intp(ident[stuff])) continue; // Already identified.
26ece22001-06-18Henrik Grubbström (Grubba)  if (objectp (stuff) || functionp (stuff) || programp (stuff)) ident[stuff]++; else if (arrayp (stuff)) {
9f71092000-11-20Martin Stjernholm  if (!ident[stuff]++) identify_stack += stuff; } else if (multisetp (stuff)) { if (!ident[stuff]++)
23184f2003-04-30Martin Nilsson  identify_stack += indices([multiset]stuff);
9f71092000-11-20Martin Stjernholm  } else if (mappingp (stuff)) { if (!ident[stuff]++)
23184f2003-04-30Martin Nilsson  identify_stack += indices([mapping]stuff) + values([mapping]stuff);
9f71092000-11-20Martin Stjernholm  }
da0a822000-08-29Martin Stjernholm  } }
2602b82000-08-29Martin Stjernholm  string describe_string (string m, int maxlen) { canclip++; if(sizeof(m) < maxlen) {
9449362008-09-25Martin Stjernholm  string t = sprintf("%q", m);
eba0232004-01-13Martin Nilsson  if (sizeof(t) < (maxlen + 2))
2602b82000-08-29Martin Stjernholm  return t; t = 0; } clipped++;
e4c3762016-08-19Henrik Grubbström (Grubba)  if(maxlen>10) { int h = (3*maxlen)/4; return sprintf("%q+[%d]+%q", m[..h-5], sizeof(m)-(maxlen-8), m[sizeof(m) - (maxlen - (h + 4))..]); }
eba0232004-01-13Martin Nilsson  return "string["+sizeof(m)+"]";
2602b82000-08-29Martin Stjernholm  } string describe_array (array m, int maxlen) { if(!sizeof(m)) return "({})"; else { if(maxlen<5) { clipped++; return "array["+sizeof(m)+"]"; } else { canclip++; return "({" + describe_comma_list(m,maxlen-2) +"})"; } } } string describe_mapping (mapping m, int maxlen) { if(!sizeof(m)) return "([])"; else return "mapping["+sizeof(m)+"]"; } string describe_multiset (multiset m, int maxlen) { if(!sizeof(m)) return "(<>)"; else return "multiset["+sizeof(m)+"]"; }
da0a822000-08-29Martin Stjernholm  string describe (mixed m, int maxlen)
ca2b071998-03-28Henrik Grubbström (Grubba)  {
e617062004-01-08Martin Nilsson  catch { if (stringp (ident[m])) return [string]ident[m]; else if (intp (ident[m]) && ident[m] > 1) ident[m] = "@" + identcount++; };
da0a822000-08-29Martin Stjernholm 
0a064e2002-11-24Henrik Grubbström (Grubba)  string res; if (catch (res=sprintf("%t",m))) res = "object"; // Object with a broken _sprintf(), probably. switch(res) { case "int":
65340d2014-08-15Martin Nilsson  if (!m && undefinedp (m) == 1)
08ca0a2004-12-08Martin Stjernholm  return "UNDEFINED";
0a064e2002-11-24Henrik Grubbström (Grubba)  case "float": return (string)m; case "string":
23184f2003-04-30Martin Nilsson  return describe_string ([string]m, maxlen);
0a064e2002-11-24Henrik Grubbström (Grubba)  case "array":
23184f2003-04-30Martin Nilsson  res = describe_array ([array]m, maxlen);
0a064e2002-11-24Henrik Grubbström (Grubba)  break; case "mapping":
23184f2003-04-30Martin Nilsson  res = describe_mapping ([mapping]m, maxlen);
0a064e2002-11-24Henrik Grubbström (Grubba)  break; case "multiset":
23184f2003-04-30Martin Nilsson  res = describe_multiset ([multiset]m, maxlen);
0a064e2002-11-24Henrik Grubbström (Grubba)  break; case "function":
23184f2003-04-30Martin Nilsson  if (string tmp=describe_function(