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 //
3e57bd2003-02-27Marcus Comstedt // $Id: master.pike.in,v 1.258 2003/02/27 14:52:30 marcus Exp $
c896b41998-04-29Henrik Grubbström (Grubba) 
a580e12000-09-27Fredrik Hübinette (Hubbe) #pike __REAL_VERSION__
2f520e2002-04-28Martin Nilsson 
77e4f22002-07-09Martin Nilsson // Some programs destroys character pairs beginning with the currency // symbol when running in chinese locale.
47b4322002-06-28Martin Nilsson #if "¤/" != "\244/" #error "master.pike.in is corrupted." #endif
2f520e2002-04-28Martin Nilsson // --- Some configurable parameters
bec57d1999-09-06Fredrik Hübinette (Hubbe) #define PIKE_AUTORELOAD
2f520e2002-04-28Martin Nilsson #define GETCWD_CACHE #define FILE_STAT_CACHE
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 */ // --- 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;
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) 
2f520e2002-04-28Martin Nilsson //! int compat_major=-1;
4839dd2001-09-02Marcus Comstedt 
2f520e2002-04-28Martin Nilsson //! int compat_minor=-1; // --- Functions begin here. #define Stat _static_modules.files.Stat #define capitalize(X) (upper_case((X)[..0])+(X)[1..])
70e2ca2003-01-01Martin Nilsson #define write(X) _static_modules.files()->_stdout->write(X)
c896b41998-04-29Henrik Grubbström (Grubba) 
4f64a52002-05-22Martin Nilsson //! @appears error
01f7f32002-05-22Johan Sundström //! Throws an error. A more readable version of the code
da78302002-05-22Martin Nilsson //! @tt{throw( ({ sprintf(f, @@args), backtrace() }) )@}.
4f64a52002-05-22Martin Nilsson void error(string f, mixed ... args) {
da24482002-05-24Martin Nilsson  array b = backtrace();
4f64a52002-05-22Martin Nilsson  if (sizeof(args)) f = sprintf(f, @args); throw( ({ f, b[..sizeof(b)-2] }) ); }
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 foreach(PIKE_FAKEROOT_OMIT/":", string x) 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) { if(s[..1]=="/$" && (s+"/")[..20] == "/${PIKE_MODULE_PATH}/") { string tmp = s[21..]; foreach(pike_module_path, string path) { string s2 = fakeroot(sizeof(tmp)? combine_path(path, tmp) : path); if(master_file_stat(s2)) return s2; } } return fakeroot(s); } string unrelocate_module(string s) { if(s[..1]=="/$" && (s+"/")[..20] == "/${PIKE_MODULE_PATH}/") return s; foreach(pike_module_path, string path) if(s == path) return "/${PIKE_MODULE_PATH}"; else { string s2 = combine_path(path, ""); if(s[..sizeof(s2)-1] == s2) return "/${PIKE_MODULE_PATH}/"+s[sizeof(s2)..]; } return s; } #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) 
b07e962001-07-27Martin Nilsson //! @appears is_absolute_path
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) { #ifdef __NT__ 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 #define IS_ABSOLUTE_PATH(X) ((X)[0]=='/')
ca2b071998-03-28Henrik Grubbström (Grubba) #endif return p[0]=='/'; }
4619bd2002-07-29Martin Nilsson #ifdef __NT__ #define EXPLODE_PATH(X) (replace((X),"\\","/")/"/") #else #define EXPLODE_PATH(X) ((X)/"/") #endif
b07e962001-07-27Martin Nilsson //! @appears explode_path
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 //! not work on some operating systems. //!
bbf4702000-04-10Henrik Grubbström (Grubba) array(string) explode_path(string p)
ca2b071998-03-28Henrik Grubbström (Grubba) {
4619bd2002-07-29Martin Nilsson  return EXPLODE_PATH(p);
ca2b071998-03-28Henrik Grubbström (Grubba) }
b07e962001-07-27Martin Nilsson //! @appears dirname
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> //! <r><c>dirname("/a/b")</c><c>"/a/"</c></r> //! <r><c>dirname("/a/")</c><c>"/a/"</c></r> //! <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 "";
afa1292000-02-19Martin Nilsson  array(string) tmp=EXPLODE_PATH(x);
bd22082002-07-29Martin Nilsson  if(x[0]=='/' && sizeof(tmp)<3) return "/";
ca2b071998-03-28Henrik Grubbström (Grubba)  return tmp[..sizeof(tmp)-2]*"/"; }
b07e962001-07-27Martin Nilsson //! @appears basename
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])
ca2b071998-03-28Henrik Grubbström (Grubba) 
bec57d1999-09-06Fredrik Hübinette (Hubbe) #ifdef PIKE_AUTORELOAD int autoreload_on; int newest; #define AUTORELOAD_CHECK_FILE(X) \
da24482002-05-24Martin Nilsson  if(autoreload_on) if(Stat s=master_file_stat(X)) if(s->mtime>newest) newest=[int]s->mtime;
bec57d1999-09-06Fredrik Hübinette (Hubbe)  #define AUTORELOAD_BEGIN() \ int ___newest=newest; \ newest=0 #define AUTORELOAD_FINISH(VAR, CACHE, FILE) \ if(autoreload_on) { \ if(CACHE [ FILE ] && newest <= load_time[FILE]) { \ VAR = CACHE [ FILE ]; \ } \ } \ load_time[FILE]=time(); \ if(___newest > newest) newest=___newest; mapping(string:int) load_time=([]); #else #define AUTORELOAD_CHECK_FILE(X) #define AUTORELOAD_BEGIN() #define AUTORELOAD_FINISH(VAR,CACHE,FILE)
2f520e2002-04-28Martin Nilsson #endif // PIKE_AUTORELOAD
a20af62000-09-26Fredrik Hübinette (Hubbe) 
b07e962001-07-27Martin Nilsson //! @appears compile_string
56cd002001-10-28Martin Nilsson //! Compile the Pike code in the string @[source] into a program.
8f45692001-01-14Henrik Grubbström (Grubba) //! If @[filename] is not specified, it will default to @tt{"-"@}. //! //! Functionally equal to @code{@[compile](@[cpp](@[source], @[filename]))@}. //! //! @seealso //! @[compile()], @[cpp()], @[compile_file()] //! program compile_string(string source, void|string filename, object|void handler)
ca2b071998-03-28Henrik Grubbström (Grubba) {
d2777c2001-03-26Henrik Grubbström (Grubba)  return compile(cpp(source, filename||"-", 1, handler,
8f45692001-01-14Henrik Grubbström (Grubba)  compat_major, compat_minor),
a20af62000-09-26Fredrik Hübinette (Hubbe)  handler, compat_major, compat_minor);
ca2b071998-03-28Henrik Grubbström (Grubba) }
97e5c72001-07-28Martin Nilsson //!
d8a6fc2000-03-25Fredrik Hübinette (Hubbe) string master_read_file(string file) { object o=_static_modules.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
43293b2002-12-30Henrik Grubbström (Grubba) static 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)  string combine_path_with_cwd(string path) {
471ed91998-04-24Fredrik Hübinette (Hubbe)  return combine_path(IS_ABSOLUTE_PATH(path)?"/":getcwd(),path);
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 = ([]);
61a4242000-08-27Mirar (Pontus Hagland) Stat master_file_stat(string x)
ca2b071998-03-28Henrik Grubbström (Grubba) {
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]; if( zero_type(d) )
ca2b071998-03-28Henrik Grubbström (Grubba)  {
da24482002-05-24Martin Nilsson  array(string) tmp = get_dir(dir); 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
da24482002-05-24Martin Nilsson  d = dir_cache[dir] = aggregate_multiset(@tmp);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
da24482002-05-24Martin Nilsson  else dir_cache[dir]=0;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
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; return predef::file_stat(x); } #else #define master_file_stat file_stat
2f520e2002-04-28Martin Nilsson #endif // FILE_STAT_CACHE
ca2b071998-03-28Henrik Grubbström (Grubba) 
43293b2002-12-30Henrik Grubbström (Grubba) //! Mapping containing the environment variables. //! //! The mapping currently has the following structure: //! @mapping //! @member array(string) index //! Note that the index is @[lower_case()]'d on NT. //! @array //! @elem string varname //! Variable name with case intact. //! @elem string value //! Variable value. //! @endarray //! @endmapping //! //! @note //! This mapping should not be accessed directly; use @[getenv()] //! and @[putenv()] instead. //! //! @note //! This mapping is not compatible with @[Process.create_process()]; //! use the mapping returned from calling @[getenv()] without arguments //! instead. mapping(string:array(string)) environment=([]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
fc398b2001-05-31Fredrik Hübinette (Hubbe) 
8f45692001-01-14Henrik Grubbström (Grubba) //! @decl string getenv(string varname) //! @decl mapping(string:string) getenv()
b07e962001-07-27Martin Nilsson //! @appears getenv
8f45692001-01-14Henrik Grubbström (Grubba) //!
a71f832001-11-13Tomas Nilsson //! When called with no arguments, a mapping with all current environment
df9dcd2003-01-07Martin Nilsson //! variables will be returned. Destructive opreations on the mapping //! will not affect the internal environment representation.
8f45692001-01-14Henrik Grubbström (Grubba) //! //! If the @[varname] argument has been given, the value of the environment //! variable with the name @[varname] will be returned. If no such //! environment variable exists, @tt{0@} (zero) will be returned. //!
a71f832001-11-13Tomas Nilsson //! On NT the environment variable name is case insensitive. //!
944d5b1999-12-05Henrik Grubbström (Grubba) string|mapping(string:string) getenv(string|void s)
ca2b071998-03-28Henrik Grubbström (Grubba) {
da24482002-05-24Martin Nilsson  if(!s) return [mapping(string:string)]aggregate_mapping( @(values(environment)*({}) ) );
a71f832001-11-13Tomas Nilsson #ifdef __NT__ s = lower_case(s); #endif return environment[s] && environment[s][1];
df2c632000-08-02Henrik Grubbström (Grubba) }
fc398b2001-05-31Fredrik Hübinette (Hubbe) 
b07e962001-07-27Martin Nilsson //! @appears compile_file
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 //! @code{@[compile_string](@[Stdio.read_file](@[filename]), @[filename])@}. //! //! @seealso //! @[compile()], @[compile_string()], @[cpp()] //! program compile_file(string filename, object|void handler, void|program p, void|object o) { AUTORELOAD_CHECK_FILE(filename); return compile(cpp(master_read_file(filename), filename, 1, handler, compat_major, compat_minor), handler, compat_major, compat_minor, p, o); }
df2c632000-08-02Henrik Grubbström (Grubba) #if 0 variant mapping(string:string) getenv() { return environment + ([]); } variant string getenv(string s) { return environment[s]; } function(:mapping(string:string))|function(string:string) getenv(s) { if(!s) return environment + ([]); return environment[s]; }
b07e962001-07-27Martin Nilsson // mapping(string:string) getenv() |
df2c632000-08-02Henrik Grubbström (Grubba) string getenv(string s) { if(!s) return environment + ([]);
ca2b071998-03-28Henrik Grubbström (Grubba)  return environment[s]; }
df2c632000-08-02Henrik Grubbström (Grubba) #endif /* 0 */
ca2b071998-03-28Henrik Grubbström (Grubba) 
b07e962001-07-27Martin Nilsson //! @appears putenv
8f45692001-01-14Henrik Grubbström (Grubba) //! Sets the environment variable @[varname] to @[value]. //!
a71f832001-11-13Tomas Nilsson //! On NT the environment variable name is case insensitive. //!
8f45692001-01-14Henrik Grubbström (Grubba) //! @seealso //! @[getenv()] //! void putenv(string varname, string value)
ca2b071998-03-28Henrik Grubbström (Grubba) {
a71f832001-11-13Tomas Nilsson  string index = varname; #ifdef __NT__ index = lower_case(varname); if (environment[index] && environment[index][0]) varname = environment[index][0]; #endif environment[index] = ({ varname, value });
ca2b071998-03-28Henrik Grubbström (Grubba) }
b07e962001-07-27Martin Nilsson //! @appears normalize_path
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) 
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 //! //! @note //! As a special case the current master program is available //! under the name @tt{"/master"@}. mapping(string:program) programs=(["/master":object_program(this_object())]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
6d926c1999-11-26Henrik Grubbström (Grubba) array(string) query_precompiled_names(string fname) { // Filenames of potential precompiled files in priority order.
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" }); }
6330192000-02-10Fredrik Hübinette (Hubbe) #if constant(_static_modules.Builtin.mutex) #define THREADED
da24482002-05-24Martin Nilsson _static_modules.Builtin.mutex compilation_mutex = _static_modules.Builtin()->mutex();
6330192000-02-10Fredrik Hübinette (Hubbe) #endif
aa68b12001-03-19Fredrik Hübinette (Hubbe) static program low_findprog(string pname, 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) 
6330192000-02-10Fredrik Hübinette (Hubbe) #ifdef THREADED
3b11422000-02-13Henrik Grubbström (Grubba)  object key; // FIXME: The catch is needed, since we might be called in // a context when threads are disabled. // (compile() disables threads).
098c8a2000-03-30Henrik Grubbström (Grubba)  mixed err = catch {
3b11422000-02-13Henrik Grubbström (Grubba)  key=compilation_mutex->lock(2); };
098c8a2000-03-30Henrik Grubbström (Grubba)  if (err) {
2f520e2002-04-28Martin Nilsson  werror( "low_findprog: Caught spurious error:\n" "%s\n", describe_backtrace(err) );
098c8a2000-03-30Henrik Grubbström (Grubba)  }
6330192000-02-10Fredrik Hübinette (Hubbe) #endif
4839dd2001-09-02Marcus Comstedt #ifdef PIKE_MODULE_RELOC fname = unrelocate_module(fname); #endif
bec57d1999-09-06Fredrik Hübinette (Hubbe) #ifdef PIKE_AUTORELOAD if(!autoreload_on || load_time[fname]>=time()) #endif {
401fa02002-12-02Martin Stjernholm  if(!zero_type (ret=programs[fname])) { #ifdef RESOLV_DEBUG werror ("low_findprog: %s returning cached (no autoreload)\n", fname); #endif return ret; }
bec57d1999-09-06Fredrik Hübinette (Hubbe)  }
41ee482000-02-28Fredrik Hübinette (Hubbe) #ifdef __NT__ // Ugly kluge to work better with cygwin32 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
26f3da2000-07-11Fredrik Hübinette (Hubbe)  if( (s=master_file_stat(fakeroot(fname))) && s[1]>=0 )
ca2b071998-03-28Henrik Grubbström (Grubba)  {
bec57d1999-09-06Fredrik Hübinette (Hubbe)  AUTORELOAD_BEGIN();
14fc641999-11-26Henrik Grubbström (Grubba) 
6e2ebb1999-12-28Martin Stjernholm #ifdef PIKE_AUTORELOAD
14fc641999-11-26Henrik Grubbström (Grubba)  if (load_time[fname] > s[3])
401fa02002-12-02Martin Stjernholm  if (!zero_type (ret=programs[fname])) { #ifdef RESOLV_DEBUG werror ("low_findprog: %s returning cached (autoreload)\n", fname); #endif return ret; }
6e2ebb1999-12-28Martin Stjernholm #endif
14fc641999-11-26Henrik Grubbström (Grubba) 
ca2b071998-03-28Henrik Grubbström (Grubba)  switch(ext) { case "": case ".pike":
6d926c1999-11-26Henrik Grubbström (Grubba)  foreach(query_precompiled_names(fname), string oname) {
61a4242000-08-27Mirar (Pontus Hagland)  if(Stat s2=master_file_stat(fakeroot(oname)))
6d926c1999-11-26Henrik Grubbström (Grubba)  { if(s2[1]>=0 && s2[3]>=s[3]) { mixed err=catch { AUTORELOAD_CHECK_FILE(oname);
401fa02002-12-02Martin Stjernholm  ret = decode_value(master_read_file(oname),
11f0ae2003-02-27Henrik Grubbström (Grubba)  (handler && handler->get_codec || get_codec)(fname, mkobj));
401fa02002-12-02Martin Stjernholm #ifdef RESOLV_DEBUG werror ("low_findprog: %s returning decoded dump\n", fname); #endif return programs[fname] = ret;
6d926c1999-11-26Henrik Grubbström (Grubba)  };
5d6a562001-11-08Fredrik Hübinette (Hubbe)  m_delete(programs, fname); if (handler && handler->compile_warning) {
6d926c1999-11-26Henrik Grubbström (Grubba)  handler->compile_warning(oname, 0, sprintf("Decode failed:\n"
88a2fa2001-08-16Martin Stjernholm  "\t%s", describe_error(err)));
6d926c1999-11-26Henrik Grubbström (Grubba)  } else { compile_warning(oname, 0, sprintf("Decode failed:\n"
88a2fa2001-08-16Martin Stjernholm  "\t%s", describe_error(err)));
6d926c1999-11-26Henrik Grubbström (Grubba)  }
e115cb1999-12-09Henrik Grubbström (Grubba)  } else if (out_of_date_warning) {
280de72002-03-08Martin Stjernholm  if (handler && handler->compile_warning) {
6d926c1999-11-26Henrik Grubbström (Grubba)  handler->compile_warning(oname, 0, "Compiled file is out of date\n"); } else { compile_warning(oname, 0, "Compiled file is out of date\n"); }
10e16f1999-11-04Henrik Grubbström (Grubba)  }
b085961998-05-19Fredrik Hübinette (Hubbe)  }
471ed91998-04-24Fredrik Hübinette (Hubbe)  }
bec57d1999-09-06Fredrik Hübinette (Hubbe) 
401fa02002-12-02Martin Stjernholm #ifdef RESOLV_DEBUG werror ("low_findprog: %s compiling\n", fname); #endif programs[fname]=ret=__empty_program(0, fname);
aa68b12001-03-19Fredrik Hübinette (Hubbe)  if ( mixed e=catch { ret=compile_file(fname,
34241f2001-05-24Henrik Grubbström (Grubba)  handler,
aa68b12001-03-19Fredrik Hübinette (Hubbe)  ret, mkobj? (objects[ret]=__null_program()) : 0); } )
ca2b071998-03-28Henrik Grubbström (Grubba)  {
aa68b12001-03-19Fredrik Hübinette (Hubbe)  ret=programs[fname]=0;
c46d682000-01-05Martin Stjernholm  throw(e);
ca2b071998-03-28Henrik Grubbström (Grubba)  } break; #if constant(load_module) case ".so":
caa3221998-04-15Henrik Grubbström (Grubba)  if (fname == "") {
2f520e2002-04-28Martin Nilsson  werror( "low_findprog(\"%s\", \"%s\") => load_module(\"\")\n" "%s\n", pname, ext, describe_backtrace(backtrace()) );
caa3221998-04-15Henrik Grubbström (Grubba)  }
26f3da2000-07-11Fredrik Hübinette (Hubbe) 
401fa02002-12-02Martin Stjernholm  ret=load_module(fakeroot(fname)); #ifdef RESOLV_DEBUG werror ("low_findprog: %s loaded binary\n", fname); #endif
ca2b071998-03-28Henrik Grubbström (Grubba) #endif /* load_module */ }
bec57d1999-09-06Fredrik Hübinette (Hubbe)  AUTORELOAD_FINISH(ret,programs,fname);
6e2ebb1999-12-28Martin Stjernholm 
ca2b071998-03-28Henrik Grubbström (Grubba)  return programs[fname]=ret; }
401fa02002-12-02Martin Stjernholm #ifdef RESOLV_DEBUG werror ("low_findprog: %s file not found\n", fname); #endif
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) {
a002d32002-03-01Martin Stjernholm  if(string fname=search(programs,p)) {
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  m_delete(programs, fname);
a002d32002-03-01Martin Stjernholm  // FIXME: The following assumes that programs are always stored // with '/' as path separators, even on NT. Haven't checked if // that always is the case. fname = dirname (fname);
da24482002-05-24Martin Nilsson  object n; if ( fname!="" && (n = fc[fname]) )
a002d32002-03-01Martin Stjernholm  if (n->is_resolv_dirnode || n->is_resolv_joinnode) n->delete_value (p); }
56f7162002-12-08Martin Stjernholm  m_delete(objects, p);
c6cf602001-12-13Martin Stjernholm  foreach (fc; string name; mixed mod) if (objectp(mod) && object_program(mod) == p) m_delete(fc, name);
eaa4da2001-10-04Fredrik Hübinette (Hubbe) }
aa68b12001-03-19Fredrik Hübinette (Hubbe) static program findprog(string pname, 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;
471ed91998-04-24Fredrik Hübinette (Hubbe)  array(string) tmp=EXPLODE_PATH(pname);
ca2b071998-03-28Henrik Grubbström (Grubba) 
34241f2001-05-24Henrik Grubbström (Grubba)  // werror("low_cast_to_program(%O, %O, %O, %O)\n", // pname, current_file, handler, mkobj);
ca2b071998-03-28Henrik Grubbström (Grubba)  if(sscanf(reverse(tmp[-1]),"%s.%s",ext, nname)) { ext="."+reverse(ext); tmp[-1]=reverse(nname); pname=tmp*"/";
2f520e2002-04-28Martin Nilsson  } else {
ca2b071998-03-28Henrik Grubbström (Grubba)  ext=""; }
2f520e2002-04-28Martin Nilsson 
471ed91998-04-24Fredrik Hübinette (Hubbe)  if(IS_ABSOLUTE_PATH(pname))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
941de62001-06-21Marcus Wellhardh  if (programs[pname]) return programs[pname];
ca2b071998-03-28Henrik Grubbström (Grubba)  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, string current_file, object|void handler) { return low_cast_to_program(pname, current_file, handler); }
97e5c72001-07-28Martin Nilsson //! This function is called when an error occurs that is not caught //! with catch().
06d6d31999-12-13Henrik Grubbström (Grubba) void handle_error(array(mixed)|object trace)
ca2b071998-03-28Henrik Grubbström (Grubba) {
62e87b1998-04-14Fredrik Hübinette (Hubbe)  if(mixed x=catch { werror(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 {
d28a712001-07-02Henrik Grubbström (Grubba)  catch { if (catch {
da24482002-05-24Martin Nilsson  string msg = [string]x[0]; array bt = [array]x[1];
d28a712001-07-02Henrik Grubbström (Grubba)  werror("%s%O\n", msg, bt); }) { werror("%O\n", x); } }; werror("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)  }
ca2b071998-03-28Henrik Grubbström (Grubba) }
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",
4c3f7d2000-04-13Per Hedbor  "normalize_path",
c5cc2d1998-04-29Henrik Grubbström (Grubba)  "getenv", "putenv", #ifdef GETCWD_CACHE "cd", "getcwd", #endif });
28c5382002-09-09Marcus Comstedt string include_prefix;
7a90f12003-01-26Martin Nilsson  //! @decl int strlen(string|multiset|array|mapping|object thing)
e378192003-01-20Martin Nilsson //! @appears strlen //! Alias for @[sizeof]. //! @deprecated sizeof
7a90f12003-01-26Martin Nilsson //! @decl int write(string fmt, mixed ... args)
e378192003-01-20Martin Nilsson //! @appears write //! Writes a string on stdout. Works just like @[Stdio.File.write] //! on @[Stdio.stdout].
ca2b071998-03-28Henrik Grubbström (Grubba) /* Note that create is called before add_precompiled_program */ void create() {
c5cc2d1998-04-29Henrik Grubbström (Grubba)  object o = this_object();
ca2b071998-03-28Henrik Grubbström (Grubba) 
9066122002-11-28Martin Nilsson  foreach(master_efuns, string e) if (o[e])
c5cc2d1998-04-29Henrik Grubbström (Grubba)  add_constant(e, o[e]);
9066122002-11-28Martin Nilsson  else error("Function %O is missing from master.pike.\n", e);
c5cc2d1998-04-29Henrik Grubbström (Grubba)  add_constant("strlen", sizeof); add_constant("write", _static_modules.files()->_stdout->write);
ca2b071998-03-28Henrik Grubbström (Grubba) 
87f9082001-03-12Fredrik Hübinette (Hubbe) #define CO(X) add_constant(#X,_static_modules.Builtin.__backend->X) CO(call_out); CO(_do_call_outs); CO(find_call_out); CO(remove_call_out); CO(call_out_info);
e37a3e1999-10-09Fredrik Hübinette (Hubbe) #if "¤share_prefix¤"[0]!='¤' // add path for architecture-dependant files add_include_path("¤share_prefix¤/include"); add_module_path("¤share_prefix¤/modules"); #endif #if "¤lib_prefix¤"[0]!='¤' // add path for architecture-dependant files add_include_path("¤lib_prefix¤/include"); add_module_path("¤lib_prefix¤/modules"); #endif
28c5382002-09-09Marcus Comstedt  #if "¤include_prefix¤"[0]!='¤' include_prefix = "¤include_prefix¤"; #endif
ca2b071998-03-28Henrik Grubbström (Grubba) }
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) {
10e16f1999-11-04Henrik Grubbström (Grubba)  return cast_to_program(pname, current_file, handler);
ca2b071998-03-28Henrik Grubbström (Grubba) } mapping (program:object) objects=([object_program(this_object()):this_object()]);
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;
401fa02002-12-02Martin Stjernholm  if(!objectp (o=objects[p])) o=objects[p]=p();
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.
ca2b071998-03-28Henrik Grubbström (Grubba) object cast_to_object(string oname, string current_file) {
401fa02002-12-02Martin Stjernholm  object o = low_cast_to_object(oname, current_file); if (objectp (o)) return o;
ac0fed2000-03-25Fredrik Hübinette (Hubbe)  error("Cast '"+oname+"' to object failed"+
b1693a2000-04-07Fredrik Hübinette (Hubbe)  ((current_file && current_file!="-")?sprintf(" for '%s'",current_file):"")+".\n");
ac0fed2000-03-25Fredrik Hübinette (Hubbe)  return 0;
ca2b071998-03-28Henrik Grubbström (Grubba) }
eaa4da2001-10-04Fredrik Hübinette (Hubbe) class dirnode
ca2b071998-03-28Henrik Grubbström (Grubba) {
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  string dirname; object|void handler;
4817482000-05-11Martin Stjernholm  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 `!.
14bb592000-05-06Fredrik Hübinette (Hubbe)  mixed module=module_checker();
098c8a2000-03-30Henrik Grubbström (Grubba)  mapping(string:mixed) cache=([]); array(string) files;
ca2b071998-03-28Henrik Grubbström (Grubba) 
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  void create(string d, object|void h) {
acd1632001-12-17Henrik Grubbström (Grubba) #ifdef MODULE_TRACE werror("%*ndirnode(%O,%O);\n",sizeof(backtrace())-1,d,h); #endif
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  dirname=d; handler=h; fc[dirname]=this_object();
dd7d452002-12-09Martin Stjernholm  if(has_suffix(dirname,".pmod"))
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  fc[dirname[..sizeof(dirname)-6]]=this_object(); }
e378192003-01-20Martin Nilsson  void get_files() { if (!(files = get_dir(fakeroot(dirname)))) { werror ("Error listing module directory %O: %s\n", dirname, strerror (errno())); files = ({}); } }
14bb592000-05-06Fredrik Hübinette (Hubbe)  class module_checker { int `!() {
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE
e378192003-01-20Martin Nilsson  werror("%*ndirnode(%O)->module_checker()->`!()\n", sizeof(backtrace()),dirname);
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #endif
c205392003-02-25Henrik Grubbström (Grubba)  // Pretend not to exist for now...
11f0ae2003-02-27Henrik Grubbström (Grubba)  // module=0;
fd4cb12001-12-16Martin Stjernholm  if(module=findmodule(dirname+"/module", handler)) { if(mixed tmp=module->_module_value) module=tmp; /* This allows for `[] to have side effects first time * it is called. (Specifically, the Calendar module uses * this */ cache=([]); _cache_full=0;
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  }
5d6a562001-11-08Fredrik Hübinette (Hubbe) 
14bb592000-05-06Fredrik Hübinette (Hubbe)  return !module; }
52c5792000-05-23Fredrik Hübinette (Hubbe) 
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  mixed `[](string index)
cd99712001-11-09Martin Stjernholm  {
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE
e378192003-01-20Martin Nilsson  werror("%*ndirnode(%O)->module_checker()[%O]\n", sizeof(backtrace()),dirname,index);
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #endif if(module) return module[index]; }
52c5792000-05-23Fredrik Hübinette (Hubbe)  array(string) _indices() { if(module) return indices(module); } array _values() { if(module) return values(module); }
ca2b071998-03-28Henrik Grubbström (Grubba)  }
098c8a2000-03-30Henrik Grubbström (Grubba)  static mixed ind(string index)
ca2b071998-03-28Henrik Grubbström (Grubba)  {
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE
e378192003-01-20Martin Nilsson  werror("%*nDirnode(%O) ind[%O] -> ???\n", sizeof(backtrace()),dirname,index);
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #endif
e118831999-12-22Per Hedbor  if(module) {
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE
e378192003-01-20Martin Nilsson  werror("%*nDirnode(%O) module[%O] -> ???\n", sizeof(backtrace()),dirname,index);
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #endif
cd99712001-11-09Martin Stjernholm  mixed o;
eaa4da2001-10-04Fredrik Hübinette (Hubbe) // _describe(module);
aa68b12001-03-19Fredrik Hübinette (Hubbe)  if(!zero_type(o=module[index])) {
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE
e378192003-01-20Martin Nilsson  werror("%*nDirnode(%O) module[%O] -> %O\n", sizeof(backtrace()),dirname,index, o);
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #endif
aa68b12001-03-19Fredrik Hübinette (Hubbe)  return o; }
a2faf61999-12-01Martin Stjernholm  }
ca2b071998-03-28Henrik Grubbström (Grubba) 
e378192003-01-20Martin Nilsson  if(!files) get_files();
e118831999-12-22Per Hedbor 
e378192003-01-20Martin Nilsson  int(0..1) ret;
e118831999-12-22Per Hedbor  foreach( files, string s )
8c03142002-11-15Martin Nilsson  if( has_value(s, index) || has_value(index,s) )
e118831999-12-22Per Hedbor  { ret=1; break; } if(!ret) return UNDEFINED;
e378192003-01-20Martin Nilsson 
ca2b071998-03-28Henrik Grubbström (Grubba)  index = dirname+"/"+index;
5d6a562001-11-08Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE werror("%*nDirnode(%O) findmodule(%O)\n", sizeof(backtrace()), dirname, dirname+"/"+index); #endif
34241f2001-05-24Henrik Grubbström (Grubba)  if(object o=findmodule(index, handler))
ca2b071998-03-28Henrik Grubbström (Grubba)  { if(mixed tmp=o->_module_value) o=tmp; return o; }
34241f2001-05-24Henrik Grubbström (Grubba)  if (program p=cast_to_program( index, 0, handler ))
aa68b12001-03-19Fredrik Hübinette (Hubbe)  { return p; }
73e9551999-12-28Martin Stjernholm  return UNDEFINED;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
098c8a2000-03-30Henrik Grubbström (Grubba)  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 if(!zero_type(ret=cache[index]))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE
e378192003-01-20Martin Nilsson  werror("%*nDirnode(%O) cache[%O] -> %O\n", sizeof(backtrace()),dirname,index, ret);
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #endif
cd99712001-11-09Martin Stjernholm  if (ret != ZERO_TYPE) return ret;
ca2b071998-03-28Henrik Grubbström (Grubba)  return UNDEFINED; }
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  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;
cd99712001-11-09Martin Stjernholm  cache[index] = zero_type(ret) ? ZERO_TYPE : ret; return ret;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
3e4b811998-10-16Henrik Grubbström (Grubba) 
e378192003-01-20Martin Nilsson  static int(0..1) _cache_full;
3e4b811998-10-16Henrik Grubbström (Grubba)  void fill_cache() {
f4f08d1999-02-26Henrik Grubbström (Grubba) #ifdef RESOLV_DEBUG werror(describe_backtrace(({ sprintf("Filling cache in dirnode %O\n", dirname), backtrace() }))); #endif /* RESOLV_DEBUG */
3e4b811998-10-16Henrik Grubbström (Grubba)  if (_cache_full) { return; } if (module) { foreach(indices(module), string index) { cache[index] = module[index]; } }
e378192003-01-20Martin Nilsson  if(!files) get_files();
5be4aa2001-11-12Martin Stjernholm 
e118831999-12-22Per Hedbor  foreach(files, string fname) {
0e68e62000-02-04Henrik Grubbström (Grubba)  mixed err = catch {
3e4b811998-10-16Henrik Grubbström (Grubba)  if (((< ".pike", ".pmod" >)[fname[sizeof(fname)-5..]]) && !zero_type(`[](fname[..sizeof(fname)-6]))) { continue;
0e68e62000-02-04Henrik Grubbström (Grubba)  } else if ((fname[sizeof(fname)-3..] == ".so") &&
3e4b811998-10-16Henrik Grubbström (Grubba)  !zero_type(`[](fname[..sizeof(fname)-4]))) { continue; } };
0e68e62000-02-04Henrik Grubbström (Grubba)  if (err) { compile_warning(dirname+"."+fname, 0, sprintf("Compilation failed:\n" "%s\n", describe_backtrace(err))); }
3e4b811998-10-16Henrik Grubbström (Grubba)  } _cache_full = 1; }
e378192003-01-20Martin Nilsson  static array(string) _indices()
3e4b811998-10-16Henrik Grubbström (Grubba)  { fill_cache();
e378192003-01-20Martin Nilsson  return indices(filter(cache, lambda(mixed x) { return cache[x] != ZERO_TYPE; } ));
3e4b811998-10-16Henrik Grubbström (Grubba)  }
e378192003-01-20Martin Nilsson  static 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) { if (string name = search (cache, val)) m_delete (cache, name); }
e378192003-01-20Martin Nilsson  static int(0..) _sizeof() { return sizeof(_values()); } static string _sprintf(int as) { return as=='O' && sprintf("master()->dirnode(%O)",dirname); } }
ca2b071998-03-28Henrik Grubbström (Grubba) 
6e2ebb1999-12-28Martin Stjernholm static class ZERO_TYPE {};
94257b1998-10-16Henrik Grubbström (Grubba) class joinnode {
4817482000-05-11Martin Stjernholm  constant is_resolv_joinnode = 1;
94257b1998-10-16Henrik Grubbström (Grubba)  array(object|mapping) joined_modules;
098c8a2000-03-30Henrik Grubbström (Grubba)  mapping(string:mixed) cache=([]);
94257b1998-10-16Henrik Grubbström (Grubba) 
52c5792000-05-23Fredrik Hübinette (Hubbe)  string _sprintf(int as) {
9852f72002-12-03Martin Nilsson  return as=='O' && sprintf("master()->joinnode(%O)",joined_modules);
52c5792000-05-23Fredrik Hübinette (Hubbe)  }
94257b1998-10-16Henrik Grubbström (Grubba)  void create(array(object|mapping) _joined_modules) { joined_modules = _joined_modules; }
098c8a2000-03-30Henrik Grubbström (Grubba)  static mixed ind(string index)
94257b1998-10-16Henrik Grubbström (Grubba)  { array(mixed) res = ({});
ca051c1999-11-23Per Hedbor  foreach(joined_modules, object|mapping o) {
94257b1998-10-16Henrik Grubbström (Grubba)  mixed ret;
ca051c1999-11-23Per Hedbor  if (!zero_type(ret = o[index])) {
8b307e1998-10-17Henrik Grubbström (Grubba)  if (objectp(ret = o[index]) &&
3ad5d62000-05-13Martin Stjernholm  (ret->is_resolv_dirnode || ret->is_resolv_joinnode))
ca051c1999-11-23Per Hedbor  {
8b307e1998-10-17Henrik Grubbström (Grubba)  // Only join directorynodes (or joinnodes). res += ({ ret });
8cdeed2000-09-15Mirar (Pontus Hagland)  } else if ( !zero_type(ret) ) {
ca051c1999-11-23Per Hedbor  return (ret);
8b307e1998-10-17Henrik Grubbström (Grubba)  } else { // Ignore continue; }
94257b1998-10-16Henrik Grubbström (Grubba)  } }
ca051c1999-11-23Per Hedbor  if (sizeof(res) > 1) return joinnode(res); else if (sizeof(res))
94257b1998-10-16Henrik Grubbström (Grubba)  return res[0]; return UNDEFINED; }
098c8a2000-03-30Henrik Grubbström (Grubba)  mixed `[](string index)
94257b1998-10-16Henrik Grubbström (Grubba)  {
098c8a2000-03-30Henrik Grubbström (Grubba)  mixed ret;
94257b1998-10-16Henrik Grubbström (Grubba)  if (!zero_type(ret = cache[index])) { if (ret != ZERO_TYPE) { return ret; } return UNDEFINED; } 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;
94257b1998-10-16Henrik Grubbström (Grubba)  if (zero_type(ret)) { cache[index] = ZERO_TYPE; } else { cache[index] = ret; } return ret; }
098c8a2000-03-30Henrik Grubbström (Grubba)  static int _cache_full;
3e4b811998-10-16Henrik Grubbström (Grubba)  void fill_cache() {
f4f08d1999-02-26Henrik Grubbström (Grubba) #ifdef RESOLV_DEBUG werror(describe_backtrace(({ "Filling cache in joinnode\n", backtrace() }))); #endif /* RESOLV_DEBUG */
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) { if (zero_type(cache[index])) { `[](index); } } } _cache_full = 1; } array(string) _indices() { fill_cache();
cd99712001-11-09Martin Stjernholm  return indices(filter(cache, lambda(mixed x){ return cache[x] != ZERO_TYPE; }));
3e4b811998-10-16Henrik Grubbström (Grubba)  } array(mixed) _values() { fill_cache();
cd99712001-11-09Martin Stjernholm  return values(cache) - ({ZERO_TYPE});
3e4b811998-10-16Henrik Grubbström (Grubba)  }
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--; } else if (objectp (o) && (o->is_resolv_dirnode || o->is_resolv_joinnode)) o->delete_value (val); else if (string name = mappingp (o) && search (o, val)) m_delete (o, name); } }
94257b1998-10-16Henrik Grubbström (Grubba) };
1792a71998-04-10Henrik Grubbström (Grubba) // Variables mustn't be static to allow for replace_master(). // /grubba 1998-04-10 mapping(string:mixed) fc=([]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
34241f2001-05-24Henrik Grubbström (Grubba) object findmodule(string fullname, object|void handler)
ca2b071998-03-28Henrik Grubbström (Grubba) { object o;
eaa4da2001-10-04Fredrik Hübinette (Hubbe) #ifdef MODULE_TRACE werror("%*nfindmodule(%O)\n",sizeof(backtrace()),fullname); #endif
ca2b071998-03-28Henrik Grubbström (Grubba)  if(!zero_type(o=fc[fullname])) {
aa68b12001-03-19Fredrik Hübinette (Hubbe) // werror("fc[%O] -> %O\n",fullname, o);
179eb12002-11-29Henrik Grubbström (Grubba)  if (o == 0) return UNDEFINED;
ca2b071998-03-28Henrik Grubbström (Grubba)  return o; }
61a4242000-08-27Mirar (Pontus Hagland)  if(Stat stat=master_file_stat(fakeroot(fullname+".pmod")))
ca2b071998-03-28Henrik Grubbström (Grubba)  { if(stat[1]==-2)
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  return dirnode(fullname+".pmod", handler);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
401fa02002-12-02Martin Stjernholm  if(objectp (o = low_cast_to_object(fullname+".pmod", "/.", handler)))
ca2b071998-03-28Henrik Grubbström (Grubba)  return fc[fullname]=o; #if constant(load_module)
26f3da2000-07-11Fredrik Hübinette (Hubbe)  if(master_file_stat(fakeroot(fullname+".so")))
34241f2001-05-24Henrik Grubbström (Grubba)  return fc[fullname] = low_cast_to_object(fullname, "/.", handler);
ca2b071998-03-28Henrik Grubbström (Grubba) #endif
401fa02002-12-02Martin Stjernholm  return fc[fullname] = 0;
ca2b071998-03-28Henrik Grubbström (Grubba) }
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  array(string) tmp; string path;
ca2b071998-03-28Henrik Grubbström (Grubba)  if(current_file) {
471ed91998-04-24Fredrik Hübinette (Hubbe)  tmp=EXPLODE_PATH(current_file);
cc2c071998-04-19Fredrik Hübinette (Hubbe)  tmp[-1]=what;
ca2b071998-03-28Henrik Grubbström (Grubba)  path=combine_path_with_cwd( tmp*"/");
57b1af2001-12-13Henrik Grubbström (Grubba)  } else { path = combine_path_with_cwd(what);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
acd1632001-12-17Henrik Grubbström (Grubba) #ifdef MODULE_TRACE werror("%*nhandle_import(%O, %O, %O)\n", sizeof(backtrace()), what, current_file, handler); #endif /* MODULE_TRACE */
34241f2001-05-24Henrik Grubbström (Grubba)  if (handler) { return dirnode(path, handler); }
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  if(fc[path]) return fc[path]; return dirnode(path);
cc2c071998-04-19Fredrik Hübinette (Hubbe) }
a20af62000-09-26Fredrik Hübinette (Hubbe)  multiset no_resolv = (<>);
b07e962001-07-27Martin Nilsson  //!
a20af62000-09-26Fredrik Hübinette (Hubbe) class CompatResolver
cc2c071998-04-19Fredrik Hübinette (Hubbe) {
a20af62000-09-26Fredrik Hübinette (Hubbe)  array(string) pike_include_path=({}); array(string) pike_module_path=({}); array(string) pike_program_path=({});
374c902001-12-20Martin Stjernholm  mapping(string:string) predefines = ([]);
a20af62000-09-26Fredrik Hübinette (Hubbe)  string ver;
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. void create(mixed version)
a20af62000-09-26Fredrik Hübinette (Hubbe)  {
6df5a52001-11-07Martin Nilsson  ver=(string)version;
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}); }
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()] //!
a20af62000-09-26Fredrik Hübinette (Hubbe)  void add_module_path(string tmp) { tmp=normalize_path(combine_path_with_cwd(tmp)); pike_module_path-=({tmp}); pike_module_path=({tmp})+pike_module_path; }
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)); pike_module_path-=({tmp}); }
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; }
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. void add_predefine (string name, string value) { 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; }
6df5a52001-11-07Martin Nilsson  //!
a20af62000-09-26Fredrik Hübinette (Hubbe)  mapping get_default_module() { /* 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)  }; compat_major=saved_compat_major; compat_minor=saved_compat_minor; if(err) throw(err); return x; }
6df5a52001-11-07Martin Nilsson  //!
34241f2001-05-24Henrik Grubbström (Grubba)  mixed resolv_base(string identifier, string|void current_file, object|void current_handler)
a20af62000-09-26Fredrik Hübinette (Hubbe)  {
eaa4da2001-10-04Fredrik Hübinette (Hubbe) // werror("Resolv_base(%O)\n",identifier);
a20af62000-09-26Fredrik Hübinette (Hubbe)  array(mixed) tmp = ({});
b8cd052000-09-26Fredrik Hübinette (Hubbe)  string dir=current_file ? dirname(current_file) : "/";
34241f2001-05-24Henrik Grubbström (Grubba) 
a20af62000-09-26Fredrik Hübinette (Hubbe)  foreach(pike_module_path, string path) {
34241f2001-05-24Henrik Grubbström (Grubba)  string file=combine_path(dir, path, identifier);
401fa02002-12-02Martin Stjernholm  mixed ret = findmodule(file, current_handler); if(objectp (ret)) { // ret is either zero or an object here. if (ret->is_resolv_dirnode || ret->is_resolv_joinnode) {
a20af62000-09-26Fredrik Hübinette (Hubbe)  if (mixed new_ret = ret->_module_value) { ret = new_ret; } tmp += ({ ret }); } else { if (mixed new_ret = ret->_module_value) { ret = new_ret; } if (!sizeof(tmp)) { return ret; } else { // Ignore
2f520e2002-04-28Martin Nilsson  werror( "Ignoring file %O: %t for identifier %O\n", file, ret, identifier );
a20af62000-09-26Fredrik Hübinette (Hubbe)  continue; } } }
8b307e1998-10-17Henrik Grubbström (Grubba)  }
a20af62000-09-26Fredrik Hübinette (Hubbe)  if (sizeof(tmp)) { if (sizeof(tmp) == 1) { return(tmp[0]);
8b307e1998-10-17Henrik Grubbström (Grubba)  }
a20af62000-09-26Fredrik Hübinette (Hubbe)  return joinnode(tmp);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
a20af62000-09-26Fredrik Hübinette (Hubbe)  return UNDEFINED;
94257b1998-10-16Henrik Grubbström (Grubba)  }
a20af62000-09-26Fredrik Hübinette (Hubbe)  mapping resolv_cache = set_weak_flag( ([]), 1 );
6df5a52001-11-07Martin Nilsson  //!
34241f2001-05-24Henrik Grubbström (Grubba)  mixed resolv(string identifier, string|void current_file, object|void current_handler)
a20af62000-09-26Fredrik Hübinette (Hubbe)  {
ff38752002-02-14Henrik Grubbström (Grubba) #ifdef RESOLV_DEBUG
3c6f582002-05-24Martin Stjernholm  werror("Resolv(%O, %O)\n",identifier, current_file);
ff38752002-02-14Henrik Grubbström (Grubba) #endif /* RESOLV_DEBUG */
eaa4da2001-10-04Fredrik Hübinette (Hubbe) 
34241f2001-05-24Henrik Grubbström (Grubba)  // FIXME: Support having the cache in the handler?
3c6f582002-05-24Martin Stjernholm  if( no_resolv[ identifier ] ) { #ifdef RESOLV_DEBUG werror("Resolv(%O, %O) => excluded\n",identifier, current_file); #endif /* RESOLV_DEBUG */
a20af62000-09-26Fredrik Hübinette (Hubbe)  return UNDEFINED;
3c6f582002-05-24Martin Stjernholm  }
a20af62000-09-26Fredrik Hübinette (Hubbe) 
26ece22001-06-18Henrik Grubbström (Grubba)  if (current_file && !stringp(current_file)) {
4619bd2002-07-29Martin Nilsson  error( "resolv(%O, %O, %O): current_file is not a string!\n", identifier, current_file, current_handler, backtrace() );
26ece22001-06-18Henrik Grubbström (Grubba)  }
a20af62000-09-26Fredrik Hübinette (Hubbe)  mixed ret; string id=identifier+":"+(current_file ? dirname(current_file) : "-");
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  if( zero_type (ret = resolv_cache[id]) != 1 ) { // werror("Resolv cached(%O) => %O (%d)\n",id,resolv_cache[id],zero_type(resolv_cache[id]));
3c6f582002-05-24Martin Stjernholm #ifdef RESOLV_DEBUG if (ret == ZERO_TYPE) werror("Resolv(%O, %O) => not found (cached)\n",identifier, current_file); else werror("Resolv(%O, %O) => found %O (cached)\n",identifier, current_file, ret); #endif /* RESOLV_DEBUG */
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  return ret == ZERO_TYPE ? UNDEFINED : ret; }
a20af62000-09-26Fredrik Hübinette (Hubbe)  array(string) tmp=identifier/".";
34241f2001-05-24Henrik Grubbström (Grubba)  ret=resolv_base(tmp[0], current_file, current_handler);
179eb12002-11-29Henrik Grubbström (Grubba)  foreach(tmp[1..],string index) { if (zero_type(ret)) break; ret=ret[index]; }
a20af62000-09-26Fredrik Hübinette (Hubbe)  resolv_cache[id] = zero_type (ret) ? ZERO_TYPE : ret;
3c6f582002-05-24Martin Stjernholm #ifdef RESOLV_DEBUG if (zero_type (ret)) werror("Resolv(%O, %O) => not found\n",identifier, current_file); else werror("Resolv(%O, %O) => found %O\n",identifier, current_file, ret); #endif /* RESOLV_DEBUG */
a20af62000-09-26Fredrik Hübinette (Hubbe)  return ret; }
97e5c72001-07-28Martin Nilsson  //! This function is called whenever an #include directive is encountered //! it receives the argument for #include and should return the file name //! of the file to include
a20af62000-09-26Fredrik Hübinette (Hubbe)  string handle_include(string f, string current_file, int local_include) { array(string) tmp; string path; if(local_include) { tmp=EXPLODE_PATH(current_file); tmp[-1]=f; path=combine_path_with_cwd(tmp*"/"); } else { foreach(pike_include_path, path) { path=combine_path(path,f); if(master_file_stat(fakeroot(path))) break; else path=0; } } return path; }
6df5a52001-11-07Martin Nilsson  //!
a20af62000-09-26Fredrik Hübinette (Hubbe)  string read_include(string f) { AUTORELOAD_CHECK_FILE(f) return master_read_file(f); }
9852f72002-12-03Martin Nilsson  string _sprintf(int t)
a20af62000-09-26Fredrik Hübinette (Hubbe)  {
9852f72002-12-03Martin Nilsson  return t=='O' && sprintf("CompatResolver(%O)",ver);
94257b1998-10-16Henrik Grubbström (Grubba)  }
7c11f41999-10-04Fredrik Hübinette (Hubbe) }
a20af62000-09-26Fredrik Hübinette (Hubbe) inherit CompatResolver;
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 
b1d7d92002-01-07Martin Nilsson //! Returns 1 if we´re in async-mode, e.g. if the main method has //! 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 static 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 
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 //! _real_ programs. It receives the arguments not meant for the driver //! and an array containing the environment variables on the same form as //! a C program receives them.
afa1292000-02-19Martin Nilsson void _main(array(string) orig_argv, array(string) env)
ca2b071998-03-28Henrik Grubbström (Grubba) {
afa1292000-02-19Martin Nilsson  array(string) argv=copy_value(orig_argv);
c05dc42002-09-05Marcus Comstedt  int i,debug,trace,run_tool;
ca2b071998-03-28Henrik Grubbström (Grubba)  object tmp;
afa1292000-02-19Martin Nilsson  array q;
c05dc42002-09-05Marcus Comstedt  string postparseaction=0;
ca2b071998-03-28Henrik Grubbström (Grubba) 
ddd2af2001-12-29Martin Nilsson  predefines = _static_modules.Builtin()->_take_over_initial_predefines();
bfa62b1998-04-30Henrik Grubbström (Grubba)  _pike_file_name = orig_argv[0];
45c7262001-04-17Mirar (Pontus Hagland) #if constant(thread_create) _backend_thread = this_thread(); #endif
bfa62b1998-04-30Henrik Grubbström (Grubba) 
f595e92003-01-01Martin Nilsson  foreach(env, string a) if( sscanf(a, "%s=%s", a, string b)==2 ) { #ifdef __NT__ if(a=="") { sscanf(b, "%s=%s", a, b); a="="+a; } #endif putenv(a, b);
d854161999-04-08Fredrik Hübinette (Hubbe)  }
f595e92003-01-01Martin Nilsson  else werror("Broken environment var %s\n",a);
d854161999-04-08Fredrik Hübinette (Hubbe) 
da2ddc2002-08-11Martin Nilsson  void _error(string a, mixed ... b) {
4619bd2002-07-29Martin Nilsson  werror(a, @b); exit(1); };
624e851999-06-02Marcus Comstedt 
e90a8b1999-06-01Mirar (Pontus Hagland) #ifndef NOT_INSTALLED q=(getenv("PIKE_INCLUDE_PATH")||"")/":"-({""}); for(i=sizeof(q)-1;i>=0;i--) add_include_path(q[i]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
e90a8b1999-06-01Mirar (Pontus Hagland)  q=(getenv("PIKE_PROGRAM_PATH")||"")/":"-({""}); for(i=sizeof(q)-1;i>=0;i--) add_program_path(q[i]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
e90a8b1999-06-01Mirar (Pontus Hagland)  q=(getenv("PIKE_MODULE_PATH")||"")/":"-({""}); for(i=sizeof(q)-1;i>=0;i--) add_module_path(q[i]); #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  };
27a23d2003-01-27Martin Nilsson  mixed main_resolv(string ... syms) { mixed v = resolv(syms[0]); foreach(syms[1..], string sym) if(v) v = v[sym]; if(!v) _error("Could not resolv %s\n" "Is your PIKE_MODULE_PATH environment variable set correctly?\n", syms*"."); return v; };
ca2b071998-03-28Henrik Grubbström (Grubba)  if(sizeof(argv)>1 && sizeof(argv[1]) && argv[1][0]=='-') {
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}), ({"help", NO_ARG, ({"-h", "--help"}), 0, 0}), ({"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}), ({"showpaths", NO_ARG, ({"--show-paths"}), 0, 0}), ({"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}), ({"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}),
c5cc2d1998-04-29Henrik Grubbström (Grubba)  }), 1);
ca2b071998-03-28Henrik Grubbström (Grubba)  /* Parse -M and -I backwards */
8c03142002-11-15Martin Nilsson  for(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++; #endif
8c03142002-11-15Martin Nilsson 
3d14462000-09-24Per Hedbor  case "debug_without": 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": debug+=(int)q[i][1]; break;
862fb41998-04-05Fredrik Hübinette (Hubbe) 
c5cc2d1998-04-29Henrik Grubbström (Grubba) #if constant(_compiler_trace) case "compiler_trace": _compiler_trace(1); break; #endif /* constant(_compiler_trace) */
8f45692001-01-14Henrik Grubbström (Grubba) #if constant(_assembler_debug) case "assembler_debug": _assembler_debug((int)q[i][1]); break; #endif /* constant(_assembler_debug) */
e27a5c1999-11-19Henrik Grubbström (Grubba) #if constant(_optimizer_debug) case "optimizer_debug": _optimizer_debug((int)q[i][1]); break; #endif /* constant(_optimizer_debug) */
c5cc2d1998-04-29Henrik Grubbström (Grubba)  case "trace": 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; case "ipath": add_include_path(q[i][1]); break; 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;
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
afa1292000-02-19Martin Nilsson  foreach(q, array opts)
ca2b071998-03-28Henrik Grubbström (Grubba)  { switch(opts[0]) { case "version":
4619bd2002-07-29Martin Nilsson  werror(version() + " Copyright © 1994-2002 Linköping University\n"
ca2b071998-03-28Henrik Grubbström (Grubba)  "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"
b38f142002-04-30Martin Nilsson  "COPYING and COPYRIGHT in the Pike distribution for more details.\n");
ca2b071998-03-28Henrik Grubbström (Grubba)  exit(0); case "help": werror("Usage: pike [-driver options] script [script arguments]\n" "Driver options include:\n" " -I --include-path=<p>: Add <p> to the include path\n" " -M --module-path=<p> : Add <p> to the module path\n" " -P --program-path=<p>: Add <p> to the program path\n" " -e --execute=<cmd> : Run the given command instead of a script.\n" " -h --help : see this message\n" " -v --version : See what version of pike you have.\n"
94c8552001-01-19Mirar (Pontus Hagland)  " --features : List Pike features.\n"
a6b6df2001-01-19Mirar (Pontus Hagland)  " --info : List information about the Pike build and setup.\n"
2ea8261998-05-12Martin Stjernholm  " --show-paths : See the paths and master that pike uses.\n"
ca2b071998-03-28Henrik Grubbström (Grubba)  " -s# : Set stack size\n" " -m <file> : Use <file> as master object.\n" " -d -d# : Increase debug (# is how much)\n" " -t -t# : Increase trace level\n" ); exit(0);
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":
4619bd2002-07-29Martin Nilsson  werror(format_paths());
2ea8261998-05-12Martin Stjernholm  exit(0);
ca2b071998-03-28Henrik Grubbström (Grubba)  case "execute":
1808722001-08-31Fredrik Hübinette (Hubbe)  random_seed(time() ^ (getpid()<<8));
007a272002-02-09Mikael Brandström  argv = tmp->get_args(argv,1);
dd75be2003-02-26Martin Stjernholm #ifdef __AUTO_BIGNUM__ main_resolv( "Gmp", "bignum" ); #endif /* __AUTO_BIGNUM__ */
f1a1142001-02-23Fredrik Hübinette (Hubbe)  if(trace) predef::trace(trace);
2ac59e2002-12-29Martin Nilsson  mixed ret; if(currentversion <= Version(7,4)) compile_string( "mixed create(int argc, array(string) argv,array(string) env){"+ opts[1]+";}")(sizeof(argv),argv,env); else ret = compile_string(
70e2ca2003-01-01Martin Nilsson  "#define NOT(X) !(X)\n" "#define CHAR(X) 'X'\n"
2ac59e2002-12-29Martin Nilsson  "mixed run(int argc, array(string) argv," "mapping(string:string) env){"+ opts[1]+";}")()->run(sizeof(argv),argv,getenv());
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":
dd75be2003-02-26Martin Stjernholm #ifdef __AUTO_BIGNUM__ main_resolv( "Gmp", "bignum" ); #endif /* __AUTO_BIGNUM__ */
70e2ca2003-01-01Martin Nilsson  write(cpp(master_read_file(opts[1]),opts[1]));
c5cc2d1998-04-29Henrik Grubbström (Grubba)  exit(0);
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
caa3221998-04-15Henrik Grubbström (Grubba)  argv = tmp->get_args(argv,1);
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":
27a23d2003-01-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" "WWW...........http://pike.ida.liu.se/\n" "\n" "pike binary..."+_pike_file_name+"\n"+ format_paths() + "\n" "Features......"+
27a23d2003-01-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)  }
b4682a2003-02-26Martin Nilsson #ifdef __AUTO_BIGNUM__ main_resolv( "Gmp", "bignum" ); #endif /* __AUTO_BIGNUM__ */
1808722001-08-31Fredrik Hübinette (Hubbe)  random_seed(time() ^ (getpid()<<8));
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;
27a23d2003-01-27Martin Nilsson  object ts = main_resolv( "Tools", "Standalone" );
db77fa2002-12-14Martin Nilsson  foreach(indices(ts), string s) { object o = ts[s](); if(!o->main) continue; t[s] = o->description || ""; i = max(i, sizeof(s)); } foreach(sort(indices(t)), string s) werror(" %-"+i+"s %s\n", s, t[s]); exit(1); }
27a23d2003-01-27Martin Nilsson  main_resolv( "Tools", "Hilfe" )->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 {
27a23d2003-01-27Martin Nilsson  prog=main_resolv( "Tools", "Standalone", argv[0] );
66dca02002-09-05Marcus Comstedt  }; if (err) _error( "Pike: Failed to load tool %s:\n"
c05dc42002-09-05Marcus Comstedt  "%s\n", argv[0],
66dca02002-09-05Marcus Comstedt  stringp(err[0])?err[0]:describe_backtrace(err) );
c05dc42002-09-05Marcus Comstedt  argv[0] = search(master()->programs, prog) || argv[0];
66dca02002-09-05Marcus Comstedt  } else { argv[0]=combine_path_with_cwd(argv[0]); mixed err = catch { prog=(program)argv[0]; }; if (err) _error( "Pike: Failed to compile script:\n" "%s\n", stringp(err[0])?err[0]:describe_backtrace(err) ); }
34fb3d1998-10-31Henrik Grubbström (Grubba) 
586d1c2000-09-04Fredrik Hübinette (Hubbe)  if(!prog)
4619bd2002-07-29Martin Nilsson  _error("Pike: Couldn't find script to execute\n(%O)\n", argv[0]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
586d1c2000-09-04Fredrik Hübinette (Hubbe)  object script=prog();
ca2b071998-03-28Henrik Grubbström (Grubba) 
862fb41998-04-05Fredrik Hübinette (Hubbe) #if constant(_debug) if(debug) _debug(debug); #endif
4619bd2002-07-29Martin Nilsson 
ca2b071998-03-28Henrik Grubbström (Grubba)  if(!script->main)
6f501b2002-08-09Martin Nilsson  _error("Error: %s has no main().\n", argv[0]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
3d5cba2002-07-23Martin Stjernholm  if(trace) predef::trace(trace); i=script->main(sizeof(argv),argv,env);
ca2b071998-03-28Henrik Grubbström (Grubba)  if(i >=0) exit(i);
53a32a2000-06-04Francesco Chemolli  _async=1;
87f9082001-03-12Fredrik Hübinette (Hubbe)  while(1) { mixed err=catch { while(1) _static_modules.Builtin.__backend(3600.0); }; 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(); void set_inhibit_compile_errors(mixed f) { inhibit_compile_errors->set(f); }
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) 
0024f92001-06-06Mirar (Pontus Hagland) static 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 += "/"; } if(s[..sizeof(cwd)-1]==cwd) return s[sizeof(cwd)..]; };
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  //! This function is called whenever a compiling error occurs. //! Nothing strange about it. //! Note that previous_object cannot be trusted in ths function, because //! the compiler calls this function.
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), line?(string)line:"-",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); } else {
3112422000-03-27Per Hedbor  val(file, line, err);
01d3c91999-11-04Henrik Grubbström (Grubba)  }
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
97e5c72001-07-28Martin Nilsson  //! This function is called whenever a compiling warning occurs. //! Nothing strange about it. //! Note that previous_object cannot be trusted in ths function, because //! the compiler calls this function.
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), line?(string)line:"-",err ); } else if (objectp(val) && val->compile_warning) {
01d3c91999-11-04Henrik Grubbström (Grubba)  val->compile_warning(file, line, err);
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
97e5c72001-07-28Martin Nilsson 
8594c82001-08-15Martin Stjernholm //! This function is called when an exception is catched during //! compilation. Its message is also reported to @[compile_error] if //! this function returns zero. int compile_exception (array|object trace) {
ad53042001-08-16Martin Stjernholm  if (objectp (trace) && (trace->is_cpp_error || trace->is_compilation_error)) // Errors thrown directly by cpp() and compile() are normally not // interesting; they've already been reported to compile_error.
5802de2001-08-16Martin Stjernholm  return 1;
8594c82001-08-15Martin Stjernholm  if (mixed val = get_inhibit_compile_errors()) { if (objectp (val) && val->compile_exception) return val->compile_exception (trace); } 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 // which aren't destructed and have destroy() 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.
8f23062000-06-09Martin Stjernholm  werror ("GC warning: Garbing cycle where destroy() will be called " "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) 
f4f08d1999-02-26Henrik Grubbström (Grubba) static mixed _charset_mod;
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) {
db25e61999-02-26Henrik Grubbström (Grubba)  // werror(sprintf("decode_charset(%O, %O)\n", data, charset));
f4f08d1999-02-26Henrik Grubbström (Grubba)  if (!_charset_mod) { mixed mod = resolv("Locale"); _charset_mod = mod && mod["Charset"]; if (!_charset_mod) { compile_warning("-", 0, "No Locale.Charset module!"); return 0; } } object decoder; catch { decoder = _charset_mod->decoder(charset); }; if (!decoder) { compile_warning("-", 0, sprintf("Unknown charset %O!", charset)); return 0; } return decoder->feed(data)->drain(); }
ca2b071998-03-28Henrik Grubbström (Grubba) 
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]; identify_stack = identify_stack[..sizeof (identify_stack) - 2];
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]++) identify_stack += indices (stuff); } else if (mappingp (stuff)) { if (!ident[stuff]++) identify_stack += indices (stuff) + values (stuff); }
26ece22001-06-18Henrik Grubbström (Grubba) 
da0a822000-08-29Martin Stjernholm  } }
2602b82000-08-29Martin Stjernholm  string describe_string (string m, int maxlen) { canclip++; if(sizeof(m) < maxlen) { string t = sprintf("%O", m); if (sizeof(t) < (maxlen + 2)) { return t; } t = 0; } clipped++; if(maxlen>10) { return sprintf("%O+[%d]",m[..maxlen-5],sizeof(m)-(maxlen-5)); }else{ return "string["+sizeof(m)+"]"; } } 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)  {
da0a822000-08-29Martin Stjernholm  if (stringp (ident[m])) return ident[m]; else if (intp (ident[m]) && ident[m] > 1) ident[m] = "@" + identcount++;
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": case "float": return (string)m; case "string": return describe_string (m, maxlen); case "array": res = describe_array (m, maxlen); break; case "mapping": res = describe_mapping (m, maxlen); break; case "multiset": res = describe_multiset (m, maxlen); break; case "function": if (string tmp=describe_function(m)) res = tmp; break; case "program": if(string tmp=describe_program(m)) res = tmp; break; default: /* object or type. */ if (catch { if(string tmp=sprintf("%O", m)) res = tmp; }) { // Extra paranoia case. res = sprintf("Instance of %O", _typeof(m));
f645f02001-10-26Henrik Grubbström (Grubba)  }
0a064e2002-11-24Henrik Grubbström (Grubba)  break;
da0a822000-08-29Martin Stjernholm  }
0a064e2002-11-24Henrik Grubbström (Grubba)  if (stringp(ident[m]))
da0a822000-08-29Martin Stjernholm  return ident[m] + "=" + res; return res; }
e8ebc01999-08-27Fredrik Hübinette (Hubbe) 
da0a822000-08-29Martin Stjernholm  string describe_comma_list(array x, int maxlen) { string ret="";
e8ebc01999-08-27Fredrik Hübinette (Hubbe) 
da0a822000-08-29Martin Stjernholm  if(!sizeof(x)) return ""; if(maxlen<0) return ",,,"+sizeof(x);
5e09161999-10-15Fredrik Hübinette (Hubbe) 
da0a822000-08-29Martin Stjernholm  int clip=min(maxlen/2,sizeof(x)); int len=maxlen; int done=0;
ba20b11999-10-15Fredrik Hübinette (Hubbe) 
da0a822000-08-29Martin Stjernholm  // int loopcount=0;
ba20b11999-10-15Fredrik Hübinette (Hubbe)  while(1) {
da0a822000-08-29Martin Stjernholm  // if(loopcount>10000) werror("len=%d\n",len); array(string) z=allocate(clip); array(int) isclipped=allocate(clip); array(int) clippable=allocate(clip); for(int e=0;e<clip;e++)
ba20b11999-10-15Fredrik Hübinette (Hubbe)  {
da0a822000-08-29Martin Stjernholm  clipped=0; canclip=0; z[e]=describe(x[e],len); isclipped[e]=clipped; clippable[e]=canclip;
ba20b11999-10-15Fredrik Hübinette (Hubbe)  } while(1) {
da0a822000-08-29Martin Stjernholm  // if(loopcount>10000) werror("clip=%d maxlen=%d\n",clip,maxlen); string ret = z[..clip-1]*","; // if(loopcount>10000) werror("sizeof(ret)=%d z=%O isclipped=%O done=%d\n",sizeof(ret),z[..clip-1],isclipped[..clip-1],done); if(done || sizeof(ret)<=maxlen+1) { int tmp=sizeof(x)-clip-1; // if(loopcount>10000) werror("CLIPPED::::: %O\n",isclipped); clipped=`+(0,@isclipped); if(tmp>=0) { clipped++; ret+=",,,"+tmp; } canclip++; return ret; } int last_newlen=len; int newlen; int clipsuggest; while(1) { // if(loopcount++ > 20000) return ""; // if(!(loopcount & 0xfff)) werror("GNORK\n"); int smallsize=0; int num_large=0; clipsuggest=0;
ba20b11999-10-15Fredrik Hübinette (Hubbe) 
da0a822000-08-29Martin Stjernholm  for(int e=0;e<clip;e++)
ba20b11999-10-15Fredrik Hübinette (Hubbe)  {
da0a822000-08-29Martin Stjernholm  // if(loopcount>10000) werror("sizeof(z[%d])=%d len=%d\n",e,sizeof(z[e]),len);
ba20b11999-10-15Fredrik Hübinette (Hubbe) 
5e09161999-10-15Fredrik Hübinette (Hubbe)  if((sizeof(z[e])>=last_newlen || isclipped[e]) && clippable[e])
ba20b11999-10-15Fredrik Hübinette (Hubbe)  num_large++; else smallsize+=sizeof(z[e]); if(num_large * 15 + smallsize < maxlen) clipsuggest=e+1; }
da0a822000-08-29Martin Stjernholm  // if(loopcount>10000) werror("num_large=%d maxlen=%d smallsize=%d clippsuggest=%d\n",num_large,maxlen,smallsize,clipsuggest); newlen=num_large ? (maxlen-smallsize)/num_large : 0;
ba20b11999-10-15Fredrik Hübinette (Hubbe) 
da0a822000-08-29Martin Stjernholm  // if(loopcount>10000) werror("newlen=%d\n",newlen);
ba20b11999-10-15Fredrik Hübinette (Hubbe) 
da0a822000-08-29Martin Stjernholm  if(newlen<8 || newlen >= last_newlen) break; last_newlen=newlen; // if(loopcount>10000) werror("len decreased, retrying.\n"); }
e8ebc01999-08-27Fredrik Hübinette (Hubbe) 
da0a822000-08-29Martin Stjernholm  if(newlen < 8 && clip) { clip-= (clip/4) || 1; if(clip > clipsuggest) clip=clipsuggest; // if(loopcount>10000) werror("clip decreased, retrying.\n"); }else{ len=newlen; done++; break; }
ba20b11999-10-15Fredrik Hübinette (Hubbe)  } }
da0a822000-08-29Martin Stjernholm  return ret; }
e8ebc01999-08-27Fredrik Hübinette (Hubbe) }
be242d2002-11-23Henrik Grubbström (Grubba) 
a632422002-11-23Marcus Comstedt static string get_clean_program_path ( program p, string pref1, string suff1, string suff2 )
d3a3322002-11-23Marcus Comstedt { array(string) sort_paths_by_length(array(string) paths) { sort(map(paths, sizeof), paths); return reverse(paths); }; string path = search(programs, p); if (path) {
a632422002-11-23Marcus Comstedt  if (path == "/master") return "master"+suff2;
d3a3322002-11-23Marcus Comstedt  foreach(sort_paths_by_length(map(pike_module_path - ({""}), lambda(string s) { if (s[-1] == '/') return s; return s+"/"; })), string prefix) { if (has_prefix(path, prefix)) { path = path[sizeof(prefix)..]; break; } } path = trim_file_name(path); string modname = replace(path, ".pmod/", "."); if(search(modname, "/")<0) path=modname;
a632422002-11-23Marcus Comstedt  if (has_suffix(path, ".module.pmod")) { return pref1+path[..sizeof(path)-13]+suff1;
d3a3322002-11-23Marcus Comstedt  } if (has_suffix(path, ".pmod")) {
a632422002-11-23Marcus Comstedt  return pref1+path[..sizeof(path)-6]+suff1;
d3a3322002-11-23Marcus Comstedt  } if (has_suffix(path, ".so")) {
a632422002-11-23Marcus Comstedt  return pref1+path[..sizeof(path)-4]+suff1;
d3a3322002-11-23Marcus Comstedt  } if (has_suffix(path, ".pike")) { return path[..sizeof(path)-6]+suff2; } return path + suff2; } return 0; }
be242d2002-11-23Henrik Grubbström (Grubba) //! Describe the path to the module @[mod]. //! //! @param mod //! If @[mod] is a program, attempt to describe the path //! to a clone of @[mod]. //! //! @param ret_obj //! If an instance of @[mod] is found, it will be returned //! by changing element @tt{0@} of @[ret_obj]. //! //! @returns //! The a description of the path. //! //! @note //! The returned description will end with a proper indexing method //! currently either @tt{"."@} or @tt{"->"@}. string describe_module(object|program mod, array(object)|void ret_obj) { if (!mod) return ""; program parent_fun; if (objectp(mod)) { parent_fun = object_program(mod); if (ret_obj) ret_obj[0] = mod; } else { parent_fun = mod;
401fa02002-12-02Martin Stjernholm  if (objectp (mod = objects[parent_fun]) && ret_obj) ret_obj[0] = mod;
be242d2002-11-23Henrik Grubbström (Grubba)  } if (mod) { catch { string res = sprintf("%O", mod);
d3a3322002-11-23Marcus Comstedt  if (res != "object" && res != "")
401fa02002-12-02Martin Stjernholm  return (objectp (objects[parent_fun]) && programs["/master"] != parent_fun?
a632422002-11-23Marcus Comstedt  res+".":res+"->");
be242d2002-11-23Henrik Grubbström (Grubba)  }; } if (!object_program(parent_fun)) { // We might be a top-level entity.
a632422002-11-23Marcus Comstedt  string path = get_clean_program_path(parent_fun, "", ".", "()->");
d3a3322002-11-23Marcus Comstedt  if(path) return path;
be242d2002-11-23Henrik Grubbström (Grubba)  } // Begin by describing our parent. array(object) parent_obj = ({ 0 }); string res = describe_module(function_object(parent_fun)||
c3b5642003-01-09Henrik Grubbström (Grubba)  function_program(parent_fun)||
be242d2002-11-23Henrik Grubbström (Grubba)  object_program(parent_fun), parent_obj); // werror("So far: %O parent_obj:%O\n", res, parent_obj);
401fa02002-12-02Martin Stjernholm  object|program parent = objectp (parent_obj[0]) ? parent_obj[0] : object_program(parent_fun); if (mod && (objectp (parent) || parent)) {
be242d2002-11-23Henrik Grubbström (Grubba)  // Object identified. catch { // Check if we're an object in parent. int i = search(values(parent), mod); if (i >= 0) { return res + indices(parent)[i] + "."; } }; } // We're cloned from something in parent. if (string fun_name = function_name(parent_fun)) { return res + fun_name + "()->"; } // No such luck. // Try identifying a clone of ourselves.
401fa02002-12-02Martin Stjernholm  if (!mod && (objectp (parent) || parent)) {
be242d2002-11-23Henrik Grubbström (Grubba)  catch { // Check if there's a clone of parent_fun in parent_obj. int i; array(mixed) val = values(parent); array(string) ind = indices(parent); for (i=0; i < sizeof(val); i++) { if (objectp(val[i]) && object_program(val[i]) == parent_fun) { return res + ind[i] + "."; } } }; } // We're really out of luck here...
d3a3322002-11-23Marcus Comstedt  return res + (describe_program(parent_fun)||"unknown_program") + "()->";
be242d2002-11-23Henrik Grubbström (Grubba) }
97e5c72001-07-28Martin Nilsson //!
dd75be2003-02-26Martin Stjernholm string describe_object(object o)
bec57d1999-09-06Fredrik Hübinette (Hubbe) { string s;
90b03d2003-01-16Martin Stjernholm  if(zero_type (o)) return 0; // Destructed.
be242d2002-11-23Henrik Grubbström (Grubba)  function parent_fun = object_program(o); /* Constant object? */ catch {
c3b5642003-01-09Henrik Grubbström (Grubba)  object|program parent_obj = (function_object(parent_fun) || function_program(parent_fun));
be242d2002-11-23Henrik Grubbström (Grubba) 
10ab772002-12-04Marcus Comstedt  if (objectp (parent_obj) || parent_obj) {
be242d2002-11-23Henrik Grubbström (Grubba)  /* Check if we have a constant object. */ object tmp = objects[parent_obj];
401fa02002-12-02Martin Stjernholm  if (objectp (tmp)) parent_obj = tmp;
be242d2002-11-23Henrik Grubbström (Grubba)  /* Try finding ourselves in parent_obj. */ int i; if (objectp(o)) { i = search(values(parent_obj), o); } else { i = search(map(values(parent_obj), lambda(mixed x) { if (objectp(x)) return object_program(x); return 0; }), o); } if (i >= 0) { s = indices(parent_obj)[i];
d3a3322002-11-23Marcus Comstedt  return describe_module(parent_obj) + s;
be242d2002-11-23Henrik Grubbström (Grubba)  } } };
401fa02002-12-02Martin Stjernholm  if(objectp (objects[parent_fun]))
a632422002-11-23Marcus Comstedt  if(s=get_clean_program_path(parent_fun, "", "", "()")) return s;
be242d2002-11-23Henrik Grubbström (Grubba)  /* Try identifying the program. */ if(( s=describe_program(parent_fun) ))
a632422002-11-23Marcus Comstedt  return s+"()";
be242d2002-11-23Henrik Grubbström (Grubba) 
bec57d1999-09-06Fredrik Hübinette (Hubbe)  return 0; }
97e5c72001-07-28Martin Nilsson //!
62e87b1998-04-14Fredrik Hübinette (Hubbe) string describe_program(program p) { string s; if(!p) return 0;
d3a3322002-11-23Marcus Comstedt 
f4a0422002-11-24Henrik Grubbström (Grubba)  if(s=get_clean_program_path(p, "object_program(", ")", ""))
d3a3322002-11-23Marcus Comstedt  return s;
62e87b1998-04-14Fredrik Hübinette (Hubbe) 
c84bd12003-01-13Henrik Grubbström (Grubba)  if(mixed tmp=(function_object(p) || function_program(p))) {
10ab772002-12-04Marcus Comstedt  if(s = function_name(p))
c84bd12003-01-13Henrik Grubbström (Grubba)  { return describe_module(tmp) + s; } }
e8ce5e2001-04-09Fredrik Hübinette (Hubbe) 
bec57d1999-09-06Fredrik Hübinette (Hubbe)  if(s=_static_modules.Builtin()->program_defined(p)) return EXPLODE_PATH(s)[-1];
62e87b1998-04-14Fredrik Hübinette (Hubbe)  return 0; }
97e5c72001-07-28Martin Nilsson //!
2602b82000-08-29Martin Stjernholm string describe_function (function f) { if (!f) return 0; string name; if(string s=search(programs,f)) {
01f0272001-11-19Martin Nilsson  if(has_suffix(s, ".pmod")) name = EXPLODE_PATH(s[..sizeof(s)-6])[-1];
2602b82000-08-29Martin Stjernholm  else name = trim_file_name(s); } else if (catch (name = function_name (f))) name = "function";
9f71092000-11-20Martin Stjernholm  object o = function_object(f);
530e2c2000-12-02Martin Stjernholm  if(objectp (o)) { // Check if it's an object in a way that (hopefully) doesn't // call any functions in it (neither `== nor `!).
2602b82000-08-29Martin Stjernholm  string s; if (!catch (s = sprintf("%O",o)) && s != "object") return s+"->"+name; } return name; }
ca2b071998-03-28Henrik Grubbström (Grubba) /* It is possible that this should be a real efun, * it is currently used by handle_error to convert a backtrace to a * readable message. */
8f45692001-01-14Henrik Grubbström (Grubba) 
b07e962001-07-27Martin Nilsson //! @appears describe_backtrace
8f45692001-01-14Henrik Grubbström (Grubba) //! Returns a string containing a readable message that describes where //! the backtrace was made. //! //! The argument @[trace] should normally be the return value from a call //! to @[backtrace()], or a caught error. //! //! @seealso //! @[backtrace()], @[describe_error()], @[catch()], @[throw()] //!
ba20b11999-10-15Fredrik Hübinette (Hubbe) string describe_backtrace(mixed trace, void|int linewidth)
ca2b071998-03-28Henrik Grubbström (Grubba) { int e;
5be4aa2001-11-12Martin Stjernholm  string ret = "";
d4fd0a1999-12-06Henrik Grubbström (Grubba)  int backtrace_len=((int)getenv("PIKE_BACKTRACE_LEN")) || bt_max_string_len;
ca2b071998-03-28Henrik Grubbström (Grubba) 
ba20b11999-10-15Fredrik Hübinette (Hubbe)  if(!linewidth) { linewidth=99999; catch { linewidth=_static_modules.files()->_stdin->tcgetattr()->columns; };
fe8fb32000-01-15Fredrik Hübinette (Hubbe)  if(linewidth<10) linewidth=99999;
ba20b11999-10-15Fredrik Hübinette (Hubbe)  }
f417dd1999-03-19Fredrik Hübinette (Hubbe)  if((arrayp(trace) && sizeof(trace)==2 && stringp(trace[0])) || (objectp(trace) && trace->is_generic_error))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
a232721999-10-06Henrik Grubbström (Grubba)  if (catch {
9798481999-12-06Henrik Grubbström (Grubba)  ret = trace[0] || "No error message!\n";
a232721999-10-06Henrik Grubbström (Grubba)  trace = trace[1]; }) { return "Error indexing backtrace!\n"; }
5be4aa2001-11-12Martin Stjernholm  if(!arrayp(trace)) return ret + "No backtrace.\n"; }else if (!arrayp (trace)) return sprintf ("Unrecognized backtrace format: %O\n", trace);
ca2b071998-03-28Henrik Grubbström (Grubba)  {
da0a822000-08-29Martin Stjernholm  Describer desc = Describer(); desc->identify_parts (trace);
9f71092000-11-20Martin Stjernholm  int end = 0; if( (sizeof(trace)>1) && arrayp(trace[0]) && (sizeof(trace[0]) > 2) && (trace[0][2] == _main)) end = 1; mapping(string:int) prev_pos = ([]); array(string) frames = ({}); int loop_start = 0, loop_next, loops; for(e = sizeof(trace)-1; e>=end; e--)
ca2b071998-03-28Henrik Grubbström (Grubba)  { mixed tmp; string row;
513cbc2003-01-27Martin Nilsson  if (array err=[array]catch {
a232721999-10-06Henrik Grubbström (Grubba)  tmp = trace[e]; if(stringp(tmp))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
ba20b11999-10-15Fredrik Hübinette (Hubbe)  row=tmp;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
a232721999-10-06Henrik Grubbström (Grubba)  else if(arrayp(tmp))
ca2b071998-03-28Henrik Grubbström (Grubba)  {
ba20b11999-10-15Fredrik Hübinette (Hubbe)  string pos;
dbe79a1999-12-07Henrik Grubbström (Grubba)  if(sizeof(tmp)>=2 && stringp(tmp[0])) { if (intp(tmp[1])) {
9f71092000-11-20Martin Stjernholm  string exact_pos = tmp[0] + ":" + tmp[1];
dbe79a1999-12-07Henrik Grubbström (Grubba)  pos=trim_file_name(tmp[0])+":"+tmp[1]; } else { pos = sprintf("%s:Bad line %t", trim_file_name(tmp[0]), tmp[1]); }
a232721999-10-06Henrik Grubbström (Grubba)  }else{ mixed desc="Unknown program"; if(sizeof(tmp)>=3 && functionp(tmp[2])) {
e118831999-12-22Per Hedbor  catch {
a232721999-10-06Henrik Grubbström (Grubba)  if(mixed tmp=function_object(tmp[2])) if(tmp=object_program(tmp)) if(tmp=describe_program(tmp)) desc=tmp; }; }
ba20b11999-10-15Fredrik Hübinette (Hubbe)  pos=desc; }
9f71092000-11-20Martin Stjernholm 
ba20b11999-10-15Fredrik Hübinette (Hubbe)  string data; if(sizeof(tmp)>=3) {
dfca1f2000-08-22Martin Stjernholm  if(functionp(tmp[2])) {
2602b82000-08-29Martin Stjernholm  data = describe_function (tmp[2]);
dfca1f2000-08-22Martin Stjernholm  }
ba20b11999-10-15Fredrik Hübinette (Hubbe)  else if (stringp(tmp[2])) { data= tmp[2]; } else data ="unknown function"; data+="("+
da0a822000-08-29Martin Stjernholm  desc->describe_comma_list(tmp[3..], backtrace_len)+
ba20b11999-10-15Fredrik Hübinette (Hubbe)  ")"; if(sizeof(pos)+sizeof(data) < linewidth-4) { row=sprintf("%s: %s",pos,data); }else{ row=sprintf("%s:\n%s",pos,sprintf(" %*-/s",linewidth-6,data)); }
dbe79a1999-12-07Henrik Grubbström (Grubba)  } else { row = pos;
62e87b1998-04-14Fredrik Hübinette (Hubbe)  }
ca2b071998-03-28Henrik Grubbström (Grubba)  }
a232721999-10-06Henrik Grubbström (Grubba)  else {
9798481999-12-06Henrik Grubbström (Grubba)  if (tmp) {
e0e05f2000-03-23Martin Stjernholm  if (catch (row = sprintf("%O", tmp))) row = describe_program(object_program(tmp)) + " with broken _sprintf()";
9798481999-12-06Henrik Grubbström (Grubba)  } else { row = "Destructed object"; }
a232721999-10-06Henrik Grubbström (Grubba)  }
6e343b2001-03-14Martin Stjernholm  }) { row = sprintf("Error indexing backtrace line %d: %s (%O)!", e, err[0], err[1]); }
5d6a562001-11-08Fredrik Hübinette (Hubbe)  int dup_frame; if (!zero_type(dup_frame = prev_pos[row])) { dup_frame -= sizeof(frames); if (!loop_start) { loop_start = dup_frame; loop_next = dup_frame + 1; loops = 0; continue; } else { int new_loop = 0; if (!loop_next) loop_next = loop_start, new_loop = 1; if (dup_frame == loop_next++) { loops += new_loop; continue; } } } prev_pos[row] = sizeof(frames); if (loop_start) { array(string) tail; if (!loop_next) tail = ({}), loops++; else tail = frames[loop_start + sizeof(frames) .. loop_next - 1 + sizeof(frames)]; if (loops) frames += ({sprintf ("... last %d frames above repeated %d times ...\n", -loop_start, loops)}); frames += tail; prev_pos = ([]); loop_start = 0; }
9f71092000-11-20Martin Stjernholm  frames += ({row + "\n"}); } if (loop_start) { // Want tail to contain a full loop rather than being empty; it // looks odd when the repeat message ends the backtrace.
5d6a562001-11-08Fredrik Hübinette (Hubbe)  array(string) tail = frames[loop_start + sizeof(frames) .. loop_next - 1 + sizeof(frames)];
d48c1f2001-12-18Martin Stjernholm  if (loops) frames += ({sprintf("... last %d frames above repeated %d times ...\n", -loop_start, loops)});
9f71092000-11-20Martin Stjernholm  frames += tail;
ca2b071998-03-28Henrik Grubbström (Grubba)  }
9f71092000-11-20Martin Stjernholm  ret += frames * "";
ca2b071998-03-28Henrik Grubbström (Grubba)  }
5be4aa2001-11-12Martin Stjernholm  return ret;
ca2b071998-03-28Henrik Grubbström (Grubba) }
471ed91998-04-24Fredrik Hübinette (Hubbe) 
b07e962001-07-27Martin Nilsson //! @appears describe_error
8f45692001-01-14Henrik Grubbström (Grubba) //! Returns only the error message from a backtrace. //! //! If there is no error message in the backtrace, a fallback message //! will be returned. //! //! @seealso //! @[backtrace()], @[describe_backtrace()] //!
a66ff22000-01-11Martin Stjernholm string describe_error (mixed trace) {
513cbc2003-01-27Martin Nilsson  if((arrayp(trace) && sizeof([array]trace)==2 && stringp(([array]trace)[0])) || (objectp(trace) && ([object]trace)->is_generic_error))
a66ff22000-01-11Martin Stjernholm  { if (catch {
513cbc2003-01-27Martin Nilsson  return ([array(string)]trace)[0] || "No error message.\n";
a66ff22000-01-11Martin Stjernholm  }) { return "Error indexing backtrace!\n"; } } return sprintf ("Backtrace is of unknown type %t!\n", trace); }
471ed91998-04-24Fredrik Hübinette (Hubbe) 
da24482002-05-24Martin Nilsson class Codec (void|string fname, void|int mkobj)
471ed91998-04-24Fredrik Hübinette (Hubbe) {
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  program prog_to_mkobj;
5d6a562001-11-08Fredrik Hübinette (Hubbe)  object __register_new_program(program p)
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  { if(fname) { programs[fname]=prog_to_mkobj=p; fname=0;
5d6a562001-11-08Fredrik Hübinette (Hubbe)  if (mkobj)
401fa02002-12-02Martin Stjernholm  return objectp (objects[p]) ? objects[p] : (objects[p]=__null_program());
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  }
5d6a562001-11-08Fredrik Hübinette (Hubbe)  return 0;
eaa4da2001-10-04Fredrik Hübinette (Hubbe)  }
513cbc2003-01-27Martin Nilsson  mapping(string:mixed) f=all_constants();
471ed91998-04-24Fredrik Hübinette (Hubbe)  string nameof(mixed x) {
513cbc2003-01-27Martin Nilsson  if(string s=search(f,x)) return "efun:"+s;
471ed91998-04-24Fredrik Hübinette (Hubbe) 
51b0fb2000-03-20Martin Stjernholm  if (programp(x)) {
513cbc2003-01-27Martin Nilsson  if(string s=search(programs,x)) return s;
471ed91998-04-24Fredrik Hübinette (Hubbe) 
513cbc2003-01-27Martin Nilsson  if(int tmp=search(values(_static_modules), x))
51b0fb2000-03-20Martin Stjernholm  return "_static_modules."+(indices(_static_modules)[tmp]);
471ed91998-04-24Fredrik Hübinette (Hubbe)  }
51b0fb2000-03-20Martin Stjernholm  else if (objectp(x))
513cbc2003-01-27Martin Nilsson  if(program p=search(objects,x)) if(string s=search(programs,p)) return s;
ff38752002-02-14Henrik Grubbström (Grubba)  return UNDEFINED;
471ed91998-04-24Fredrik Hübinette (Hubbe)  } function functionof(string x) {
513cbc2003-01-27Martin Nilsson  if(sscanf(x,"efun:%s",x)) return [function]f[x]; if(sscanf(x,"resolv:%s",x)) return [function]resolv(x);
471ed91998-04-24Fredrik Hübinette (Hubbe)  return 0; } object objectof(string x) {
513cbc2003-01-27Martin Nilsson  if(sscanf(x,"efun:%s",x)) return [object]f[x]; if(sscanf(x,"resolv:%s",x)) return [object]resolv(x);
f848412001-08-29Marcus Comstedt  if(sscanf(x,"mpath:%s",x))
401fa02002-12-02Martin Stjernholm  foreach(pike_module_path, string path) {
11f0ae2003-02-27Henrik Grubbström (Grubba)  object ret = low_cast_to_object(combine_path(path,x),0, this_object());
401fa02002-12-02Martin Stjernholm  if (objectp (ret)) return ret; }
11f0ae2003-02-27Henrik Grubbström (Grubba)  return low_cast_to_object(x, 0, this_object());
471ed91998-04-24Fredrik Hübinette (Hubbe)  } program programof(string x) {
513cbc2003-01-27Martin Nilsson  if(sscanf(x,"efun:%s",x)) return [program]f[x]; if(sscanf(x,"resolv:%s",x)) return [program]resolv(x);
f848412001-08-29Marcus Comstedt  if(sscanf(x,"mpath:%s",x)) foreach(pike_module_path, string path)
11f0ae2003-02-27Henrik Grubbström (Grubba)  if(program ret=cast_to_program(combine_path(path,x), 0, this_object()))
f848412001-08-29Marcus Comstedt  return ret;
11f0ae2003-02-27Henrik Grubbström (Grubba)  return cast_to_program(x, 0, this_object());
471ed91998-04-24Fredrik Hübinette (Hubbe)  } mixed encode_object(object x) {
513cbc2003-01-27Martin Nilsson  if(x->_encode) return ([function]x->_encode)();
471ed91998-04-24Fredrik Hübinette (Hubbe)  error("Cannot encode objects yet.\n"); }
d28a712001-07-02Henrik Grubbström (Grubba)  void decode_object(object o, mixed data)
471ed91998-04-24Fredrik Hübinette (Hubbe)  {
b1693a2000-04-07Fredrik Hübinette (Hubbe)  o->_decode(data);
471ed91998-04-24Fredrik Hübinette (Hubbe)  } }
a20af62000-09-26Fredrik Hübinette (Hubbe) 
5d6a562001-11-08Fredrik Hübinette (Hubbe) 
3e57bd2003-02-27Marcus Comstedt mapping(string:Codec) codecs = set_weak_flag(([]),1);
11f0ae2003-02-27Henrik Grubbström (Grubba) Codec get_codec(string|void fname, int|void mkobj) { string key = fname + "\0" + mkobj; if (codecs[key]) return codecs[key]; return codecs[key] = Codec(fname, mkobj); }
6df5a52001-11-07Martin Nilsson //! Contains version information about a Pike version.
a20af62000-09-26Fredrik Hübinette (Hubbe) class Version {
6df5a52001-11-07Martin Nilsson  //! The major and minor parts of the version.
a20af62000-09-26Fredrik Hübinette (Hubbe)  int major; int minor;
6df5a52001-11-07Martin Nilsson  //! @decl void create(int major, int minor) //! Set the version in the object.
a20af62000-09-26Fredrik Hübinette (Hubbe)  void create(int maj, int min)
6df5a52001-11-07Martin Nilsson  { major = maj; minor = min; }
a20af62000-09-26Fredrik Hübinette (Hubbe) 
513cbc2003-01-27Martin Nilsson #define CMP(X) ((major - ([object]X)->major) || (minor - ([object]X)->minor))
a20af62000-09-26Fredrik Hübinette (Hubbe) 
6df5a52001-11-07Martin Nilsson  //! Methods define so that version objects //! can be compared and ordered.
513cbc2003-01-27Martin Nilsson  int `<(mixed v) { return objectp(v) && CMP(v) < 0; } int `>(mixed v) { return objectp(v) && CMP(v) > 0; } int `==(mixed v) { return objectp(v) && CMP(v)== 0; }
a20af62000-09-26Fredrik Hübinette (Hubbe)  int _hash() { return major * 4711 + minor ; }
9852f72002-12-03Martin Nilsson  string _sprintf(int t) { switch(t) { case 's': return sprintf("%d.%d",major,minor); case 'O': return sprintf("%O(%s)", this_program, this_object()); } }
6df5a52001-11-07Martin Nilsson  //! The version object can be casted into a string.
a20af62000-09-26Fredrik Hübinette (Hubbe)  mixed cast(string type) { switch(type) { case "string": return sprintf("%d.%d",major,minor); } } }
6df5a52001-11-07Martin Nilsson //! Version information about the current Pike version.
a20af62000-09-26Fredrik Hübinette (Hubbe) Version currentversion=Version(__MAJOR__,__MINOR__);
6df5a52001-11-07Martin Nilsson 
a20af62000-09-26Fredrik Hübinette (Hubbe) mapping(Version:CompatResolver) compat_handler_cache=set_weak_flag( ([]), 1); CompatResolver get_compilation_handler(int major, int minor) { CompatResolver ret; Version v=Version(major,minor); if(v > currentversion) { /* do we want to make an error if major.minor > __MAJOR__.__MINOR ? */ return 0; } if(!zero_type(ret=compat_handler_cache[v])) return ret;
5be4aa2001-11-12Martin Stjernholm  array files;
a20af62000-09-26Fredrik Hübinette (Hubbe)  array(Version) available=({}); #if "¤share_prefix¤"[0]!='¤'
5be4aa2001-11-12Martin Stjernholm  if (!(files = get_dir("¤share_prefix¤"))) { werror ("Error listing directory %O: %s\n", "¤share_prefix¤", strerror (errno())); files = ({}); } foreach(files, string ver)
a20af62000-09-26Fredrik Hübinette (Hubbe)  { if(sscanf(ver,"%d.%d",int maj, int min)) { Version x=Version(maj, min) ; if(x >= v) available|=({ x }); } } #endif #if "¤lib_prefix¤"[0]!='¤'
5be4aa2001-11-12Martin Stjernholm  if (!(files = get_dir("¤lib_prefix¤"))) { werror ("Error listing directory %O: %s\n", "¤lib_prefix¤", strerror (errno())); files = ({}); } foreach(files, string ver)
a20af62000-09-26Fredrik Hübinette (Hubbe)  { if(sscanf(ver,"%d.%d",int maj, int min)) { Version x=Version(maj, min) ; if(x >= v) available|=({ x }); } } #endif sort(available); #ifndef RESOLVER_HACK /* We need to define RESOLVER_HACK when we add * version-specific stuff in the CompatResolver. * As long as all the compatibility is done in the * module dierctories, RESOLVER_HACK can be undefined */ /* No compat needed */ if(!sizeof(available)) { compat_handler_cache[v]=0; return 0; } /* Same as available[0] */ if(ret=compat_handler_cache[available[0]]) return compat_handler_cache[v]=ret; #endif ret=CompatResolver(v);
b8cd052000-09-26Fredrik Hübinette (Hubbe)  /* Add default paths */ ret->pike_module_path=pike_module_path; ret->pike_include_path=pike_include_path;
a20af62000-09-26Fredrik Hübinette (Hubbe) 
b8cd052000-09-26Fredrik Hübinette (Hubbe)  foreach(reverse(available), Version tmp)
a20af62000-09-26Fredrik Hübinette (Hubbe)  { string base; #if "¤lib_prefix¤"[0]!='¤'
b8cd052000-09-26Fredrik Hübinette (Hubbe)  base=combine_path("¤lib_prefix¤",sprintf("%s",tmp));
a20af62000-09-26Fredrik Hübinette (Hubbe)  ret->add_module_path(combine_path(base,"modules")); ret->add_include_path(combine_path(base,"include")); #endif #if "¤share_prefix¤"[0]!='¤'
b8cd052000-09-26Fredrik Hübinette (Hubbe)  base=combine_path("¤share_prefix¤",sprintf("%s",tmp));
a20af62000-09-26Fredrik Hübinette (Hubbe)  ret->add_module_path(combine_path(base,"modules")); ret->add_include_path(combine_path(base,"include")); #endif }
b8cd052000-09-26Fredrik Hübinette (Hubbe)  if( v <= Version(0,6)) ret->pike_module_path+=({"."});
a20af62000-09-26Fredrik Hübinette (Hubbe)  compat_handler_cache[v] = ret; #ifndef RESOLVER_HACK compat_handler_cache[available[0]] = ret; /* may be equal to 'v' */ #endif return ret; }
9852f72002-12-03Martin Nilsson string _sprintf(int t)
a20af62000-09-26Fredrik Hübinette (Hubbe) {
9852f72002-12-03Martin Nilsson  switch(t) { case 't': return "master"; case 'O': return "master()"; }
a20af62000-09-26Fredrik Hübinette (Hubbe) }