db25e61999-02-26Henrik Grubbström (Grubba) /* $Id: master.pike.in,v 1.41 1999/02/26 01:14:07 grubba Exp $
ce8aee1998-04-21Per Hedbor  *
ca2b071998-03-28Henrik Grubbström (Grubba)  * Master-file for Pike. * * Based on master.pike 1.67. */
c896b41998-04-29Henrik Grubbström (Grubba) // Some configurable parameters useful for debugging // Used by describe_backtrace() et al. #if !defined(BT_MAX_STRING_LEN) || (BT_MAX_STRING_LEN <= 0) #undef BT_MAX_STRING_LEN #define BT_MAX_STRING_LEN 60 #endif /* !defined(BT_MAX_STRING_LEN) || (BT_MAX_STRING_LEN <= 0) */ /* * Functions begin here. */
ca2b071998-03-28Henrik Grubbström (Grubba) int is_absolute_path(string p) { #ifdef __NT__ p=replace(p,"\\","/"); if(sscanf(p,"%[a-zA-Z]:",string s) && sizeof(s)==1) 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]=='/'; } string *explode_path(string p) { #ifdef __NT__ p=replace(p,"\\","/");
471ed91998-04-24Fredrik Hübinette (Hubbe) #define EXPLODE_PATH(X) (replace((X),"\\","/")/"/") #else #define EXPLODE_PATH(X) ((X)/"/")
ca2b071998-03-28Henrik Grubbström (Grubba) #endif return p/"/"; } string dirname(string x) {
471ed91998-04-24Fredrik Hübinette (Hubbe)  string *tmp=EXPLODE_PATH(x);
ca2b071998-03-28Henrik Grubbström (Grubba)  return tmp[..sizeof(tmp)-2]*"/"; } string basename(string x) {
471ed91998-04-24Fredrik Hübinette (Hubbe)  string *tmp=EXPLODE_PATH(x);
ca2b071998-03-28Henrik Grubbström (Grubba)  return tmp[-1]; }
471ed91998-04-24Fredrik Hübinette (Hubbe) #define DIRNAME dirname #define BASENAME(X) (EXPLODE_PATH(X)[-1])
ca2b071998-03-28Henrik Grubbström (Grubba)  #define GETCWD_CACHE #define FILE_STAT_CACHE #define UNDEFINED (([])[0]) #define error(X) throw( ({ (X), backtrace()[0..sizeof(backtrace())-2] }) ) string describe_backtrace(mixed *trace); object low_cast_to_object(string oname, string current_file); string *pike_include_path=({}); string *pike_module_path=({}); string *pike_program_path=({}); int want_warnings; program compile_string(string data, void|string name) { return compile(cpp(data,name||"-")); } program compile_file(string file) {
f514b71999-02-26Henrik Grubbström (Grubba)  return compile(cpp(_static_modules.files()->Fd(file,"r")->read(),file, 1));
ca2b071998-03-28Henrik Grubbström (Grubba) } #ifdef GETCWD_CACHE string current_path; int cd(string s) { current_path=0; return predef::cd(s); } string getcwd() { return current_path || (current_path=predef::getcwd()); } #endif 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 = ([]); mixed *master_file_stat(string x) { string file, dir=combine_path_with_cwd(x);
471ed91998-04-24Fredrik Hübinette (Hubbe)  file=BASENAME(dir); dir=DIRNAME(dir);
ca2b071998-03-28Henrik Grubbström (Grubba)  multiset(string) d; if(time() > invalidate_time) { dir_cache=([]); invalidate_time=time()+FILE_STAT_CACHE_TIME; } if(zero_type(d=dir_cache[dir])) { if(string *tmp=get_dir(dir)) { d=dir_cache[dir]=aggregate_multiset(@tmp); }else{ dir_cache[dir]=0; } } if(d && !d[file]) return 0; return predef::file_stat(x); } #else #define master_file_stat file_stat #endif mapping (string:string) environment=([]); mixed getenv(string|void s) { if(!s) return environment; return environment[s]; } void putenv(string var, string val) { environment[var]=val; } void add_include_path(string tmp) { tmp=combine_path_with_cwd(tmp); pike_include_path-=({tmp}); pike_include_path=({tmp})+pike_include_path; } void remove_include_path(string tmp) { tmp=combine_path_with_cwd(tmp); pike_include_path-=({tmp}); } void add_module_path(string tmp) { tmp=combine_path_with_cwd(tmp); pike_module_path-=({tmp}); pike_module_path=({tmp})+pike_module_path; } void remove_module_path(string tmp) { tmp=combine_path_with_cwd(tmp); pike_module_path-=({tmp}); } void add_program_path(string tmp) { tmp=combine_path_with_cwd(tmp); pike_program_path-=({tmp}); pike_program_path=({tmp})+pike_program_path; } void remove_program_path(string tmp) { tmp=combine_path_with_cwd(tmp); pike_program_path-=({tmp}); } mapping (string:program) programs=(["/master":object_program(this_object())]); #define capitalize(X) (upper_case((X)[..0])+(X)[1..]) static program low_findprog(string pname, string ext) { program ret; array s; string fname=pname+ext; if(ret=programs[fname]) return ret;
471ed91998-04-24Fredrik Hübinette (Hubbe)  if( (s=master_file_stat(fname)) && s[1]>=0 )
ca2b071998-03-28Henrik Grubbström (Grubba)  { switch(ext) { case "": case ".pike":
b085961998-05-19Fredrik Hübinette (Hubbe)  if(array s2=master_file_stat(fname+".o")) {
0cd76f1998-10-22Fredrik Hübinette (Hubbe)  if(s2[1]>=0 && s2[3]>=s[3])
b085961998-05-19Fredrik Hübinette (Hubbe)  { mixed err=catch { return decode_value(_static_modules.files()->Fd(fname+".o","r")->read(),Codec()); }; if(want_warnings) werror("Failed to decode %s.o\n",fname); }
471ed91998-04-24Fredrik Hübinette (Hubbe)  }
ca2b071998-03-28Henrik Grubbström (Grubba)  if ( mixed e=catch { ret=compile_file(fname); } ) { if(arrayp(e) && sizeof(e)==2 && arrayp(e[1]) && sizeof(e[1]) == sizeof(backtrace())) e[1]=({}); throw(e); } break; #if constant(load_module) case ".so":
caa3221998-04-15Henrik Grubbström (Grubba)  if (fname == "") { werror(sprintf("low_find_prog(\"%s\", \"%s\") => load_module(\"\")\n" "%s\n", pname, ext, describe_backtrace(backtrace()))); }
ca2b071998-03-28Henrik Grubbström (Grubba)  ret=load_module(fname); #endif /* load_module */ } return programs[fname]=ret; }else{ return UNDEFINED; } } static program findprog(string pname, string ext) { switch(ext) { case ".pike": case ".so": return low_findprog(pname,ext); default: pname+=ext; return low_findprog(pname,"") || low_findprog(pname,".pike") || low_findprog(pname,".so"); } } /* 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. */ program cast_to_program(string pname, string current_file) { string ext; string nname;
471ed91998-04-24Fredrik Hübinette (Hubbe)  array(string) tmp=EXPLODE_PATH(pname);
ca2b071998-03-28Henrik Grubbström (Grubba)  if(sscanf(reverse(tmp[-1]),"%s.%s",ext, nname)) { ext="."+reverse(ext); tmp[-1]=reverse(nname); pname=tmp*"/"; }else{ ext=""; }
471ed91998-04-24Fredrik Hübinette (Hubbe)  if(IS_ABSOLUTE_PATH(pname))
ca2b071998-03-28Henrik Grubbström (Grubba)  { pname=combine_path("/",pname); return findprog(pname,ext); }else{ string cwd; if(current_file) {
471ed91998-04-24Fredrik Hübinette (Hubbe)  cwd=DIRNAME(current_file);
ca2b071998-03-28Henrik Grubbström (Grubba)  }else{ cwd=getcwd(); } if(program ret=findprog(combine_path(cwd,pname),ext)) return ret; foreach(pike_program_path, string path) if(program ret=findprog(combine_path(path,pname),ext)) return ret; return 0; } } /* This function is called when an error occurs that is not caught * with catch(). It's argument consists of: * ({ error_string, backtrace }) where backtrace is the output from the * backtrace() efun. */ void handle_error(mixed *trace) { predef::trace(0);
62e87b1998-04-14Fredrik Hübinette (Hubbe)  if(mixed x=catch { werror(describe_backtrace(trace)); }) { werror("Error in handle_error in master object:\n"); werror("%O\nOriginal error:\n%O\n",x,trace); }
ca2b071998-03-28Henrik Grubbström (Grubba) } object new(mixed prog, mixed ... args) { if(stringp(prog)) prog=cast_to_program(prog,backtrace()[-2][0]); return prog(@args); }
c5cc2d1998-04-29Henrik Grubbström (Grubba) multiset mkmultiset(array a) { return aggregate_multiset(@a); } function clone = new; /* This array contains the names of the functions * that a replacing master-object may want to override. */ constant master_efuns = ({ "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", "mkmultiset", "new", "clone", "getenv", "putenv", #ifdef GETCWD_CACHE "cd", "getcwd", #endif });
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) 
c5cc2d1998-04-29Henrik Grubbström (Grubba)  foreach(master_efuns, string e) { if (o[e]) { add_constant(e, o[e]); } else { throw(({ sprintf("Function %O is missing from master.pike.\n", e), backtrace() })); } } add_constant("strlen", sizeof); add_constant("UNDEFINED", UNDEFINED); add_constant("write", _static_modules.files()->_stdout->write);
ca2b071998-03-28Henrik Grubbström (Grubba)  random_seed(time() + (getpid() * 0x11111111)); } /* * 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. */ program handle_inherit(string pname, string current_file) { return cast_to_program(pname, current_file); } mapping (program:object) objects=([object_program(this_object()):this_object()]); object low_cast_to_object(string oname, string current_file) { program p; object o; p=cast_to_program(oname, current_file); if(!p) return 0; if(!(o=objects[p])) o=objects[p]=p(); return o; } /* 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. */ object cast_to_object(string oname, string current_file) { if(object o=low_cast_to_object(oname, current_file)) return o; error("Cast to object failed\n"); } class dirnode { string dirname; mixed module; mapping cache=([]);
cc2c071998-04-19Fredrik Hübinette (Hubbe)  void create(string name)
ca2b071998-03-28Henrik Grubbström (Grubba)  { dirname=name;
cc2c071998-04-19Fredrik Hübinette (Hubbe)  if(module=findmodule(dirname+"/module"))
ca2b071998-03-28Henrik Grubbström (Grubba)  if(mixed tmp=module->_module_value) module=tmp; } object|program ind(string index) { if(module) if(object o=module[index]) return o; index = dirname+"/"+index;
cc2c071998-04-19Fredrik Hübinette (Hubbe)  if(object o=findmodule(index))
ca2b071998-03-28Henrik Grubbström (Grubba)  { if(mixed tmp=o->_module_value) o=tmp; return o; } return (program) index; } object|program `[](string index) { mixed ret; if(!zero_type(ret=cache[index])) { if(ret) return ret; return UNDEFINED; } return cache[index]=ind(index); }
3e4b811998-10-16Henrik Grubbström (Grubba)  int _cache_full; 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]; } } foreach(get_dir(dirname), string fname) { catch { if (((< ".pike", ".pmod" >)[fname[sizeof(fname)-5..]]) && !zero_type(`[](fname[..sizeof(fname)-6]))) { continue; } }; catch { if ((fname[sizeof(fname)-3..] == ".so") && !zero_type(`[](fname[..sizeof(fname)-4]))) { continue; } }; } _cache_full = 1; } array(string) _indices() { fill_cache(); return indices(cache); } array(mixed) _values() { fill_cache(); return values(cache); }
ca2b071998-03-28Henrik Grubbström (Grubba) };
94257b1998-10-16Henrik Grubbström (Grubba) class joinnode { class ZERO_TYPE {}; array(object|mapping) joined_modules; mapping cache=([]); void create(array(object|mapping) _joined_modules) { joined_modules = _joined_modules; } object|mapping ind(string index) { array(mixed) res = ({}); foreach(joined_modules, object|mapping o) { mixed ret; if (!zero_type(ret = o[index])) {
8b307e1998-10-17Henrik Grubbström (Grubba)  if (objectp(ret = o[index]) && (< joinnode, dirnode >)[object_program(ret)]) { // Only join directorynodes (or joinnodes). res += ({ ret }); } else if (!sizeof(res)) { return(ret); } else { // Ignore werror(sprintf("Ignoring index %s: %t\n", index, ret)); continue; }
94257b1998-10-16Henrik Grubbström (Grubba)  } } if (sizeof(res) > 1) { return joinnode(res); } else if (sizeof(res)) { return res[0]; } return UNDEFINED; } object|mapping `[](string index) { object|mapping ret; if (!zero_type(ret = cache[index])) { if (ret != ZERO_TYPE) { return ret; } return UNDEFINED; } ret = ind(index); if (zero_type(ret)) { cache[index] = ZERO_TYPE; } else { cache[index] = ret; } return ret; }
3e4b811998-10-16Henrik Grubbström (Grubba)  int _cache_full; 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; } foreach(joined_modules, object|mapping o) { foreach(indices(o), string index) { if (zero_type(cache[index])) { `[](index); } } } _cache_full = 1; } array(string) _indices() { fill_cache(); return indices(cache); } array(mixed) _values() { fill_cache(); return values(cache); }
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)  object findmodule(string fullname) { mixed *stat; object o; if(!zero_type(o=fc[fullname])) { return o; } if(mixed *stat=master_file_stat(fullname+".pmod")) { if(stat[1]==-2)
cc2c071998-04-19Fredrik Hübinette (Hubbe)  return fc[fullname]=dirnode(fullname+".pmod");
ca2b071998-03-28Henrik Grubbström (Grubba)  } if(o=low_cast_to_object(fullname+".pmod","/.")) return fc[fullname]=o; #if constant(load_module) if(master_file_stat(fullname+".so")) return fc[fullname]=low_cast_to_object(fullname,"/."); #endif return fc[fullname]=UNDEFINED; }
cc2c071998-04-19Fredrik Hübinette (Hubbe) mixed handle_import(string what, string|void current_file)
ca2b071998-03-28Henrik Grubbström (Grubba) { string *tmp,path; 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*"/"); }
cc2c071998-04-19Fredrik Hübinette (Hubbe)  return fc[path]=dirnode(path); } mixed resolv(string identifier, string|void current_file) {
94257b1998-10-16Henrik Grubbström (Grubba)  array(mixed) tmp = ({}); foreach(pike_module_path, string path)
ca2b071998-03-28Henrik Grubbström (Grubba)  {
94257b1998-10-16Henrik Grubbström (Grubba)  string file=combine_path(path,identifier); if(mixed ret=findmodule(file)) {
8b307e1998-10-17Henrik Grubbström (Grubba)  if ((objectp(ret)) && (< joinnode, dirnode >)[object_program(ret)]) { 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 werror(sprintf("Ignoring file %O: %t for identifier %O\n", file, ret, identifier)); continue; }
ca2b071998-03-28Henrik Grubbström (Grubba)  }
94257b1998-10-16Henrik Grubbström (Grubba)  }
ca2b071998-03-28Henrik Grubbström (Grubba)  }
94257b1998-10-16Henrik Grubbström (Grubba)  if (sizeof(tmp)) { if (sizeof(tmp) == 1) { return(tmp[0]); } return joinnode(tmp);
ca2b071998-03-28Henrik Grubbström (Grubba)  } return UNDEFINED; }
bfa62b1998-04-30Henrik Grubbström (Grubba) // These are useful if you want to start other Pike processes // with the same options as this one was started with. string _pike_file_name;
ac51841998-04-29Henrik Grubbström (Grubba) string _master_file_name;
ca2b071998-03-28Henrik Grubbström (Grubba) /* 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. */
086bfa1998-04-09Fredrik Hübinette (Hubbe) void _main(string *orig_argv, string *env)
ca2b071998-03-28Henrik Grubbström (Grubba) {
086bfa1998-04-09Fredrik Hübinette (Hubbe)  string *argv=copy_value(orig_argv);
862fb41998-04-05Fredrik Hübinette (Hubbe)  int i,debug,trace;
ca2b071998-03-28Henrik Grubbström (Grubba)  object script; object tmp; string a,b; mixed *q;
bfa62b1998-04-30Henrik Grubbström (Grubba)  _pike_file_name = orig_argv[0];
ca2b071998-03-28Henrik Grubbström (Grubba)  foreach(env,a) if(sscanf(a,"%s=%s",a,b)) environment[a]=b;
09232f1998-05-27Fredrik Hübinette (Hubbe) #if defined(__NT__) && !defined(NOT_INSTALLED)
f73cff1998-05-13Fredrik Hübinette (Hubbe)  function rget=lambda(string ent) {
f26d331998-06-05Fredrik Hübinette (Hubbe)  catch { return RegGetValue(HKEY_CURRENT_USER,"SOFTWARE\\Idonex\\Pike\\0.6",ent); }; catch { return RegGetValue(HKEY_LOCAL_MACHINE,"SOFTWARE\\Idonex\\Pike\\0.6",ent); };
f73cff1998-05-13Fredrik Hübinette (Hubbe)  };
09232f1998-05-27Fredrik Hübinette (Hubbe)  string tmppath=rget("share_prefix");
f73cff1998-05-13Fredrik Hübinette (Hubbe)  // add path for architecture-shared files
09232f1998-05-27Fredrik Hübinette (Hubbe)  add_include_path(tmppath+"/include"); add_module_path(tmppath+"/modules");
f73cff1998-05-13Fredrik Hübinette (Hubbe) 
f26d331998-06-05Fredrik Hübinette (Hubbe)  tmppath=rget("lib_prefix");
f73cff1998-05-13Fredrik Hübinette (Hubbe)  // add path for architecture-dependant files
09232f1998-05-27Fredrik Hübinette (Hubbe)  add_include_path(tmppath+"/include"); add_module_path(tmppath+"/modules");
f73cff1998-05-13Fredrik Hübinette (Hubbe) #else
fce2ec1999-01-21Fredrik Hübinette (Hubbe)  #if "¤share_prefix¤"[0]!='¤' // add path for architecture-dependant files
76b1071998-04-17Fredrik Hübinette (Hubbe)  add_include_path("¤share_prefix¤/include"); add_module_path("¤share_prefix¤/modules");
fce2ec1999-01-21Fredrik Hübinette (Hubbe) #endif
fc33d21998-04-17Mirar (Pontus Hagland)  // add path for architecture-dependant files add_include_path("¤lib_prefix¤/include"); add_module_path("¤lib_prefix¤/modules");
f73cff1998-05-13Fredrik Hübinette (Hubbe) #endif
fc33d21998-04-17Mirar (Pontus Hagland) 
ca2b071998-03-28Henrik Grubbström (Grubba)  q=(getenv("PIKE_INCLUDE_PATH")||"")/":"-({""}); for(i=sizeof(q)-1;i>=0;i--) add_include_path(q[i]); q=(getenv("PIKE_PROGRAM_PATH")||"")/":"-({""}); for(i=sizeof(q)-1;i>=0;i--) add_program_path(q[i]); q=(getenv("PIKE_MODULE_PATH")||"")/":"-({""}); for(i=sizeof(q)-1;i>=0;i--) add_module_path(q[i]); if(sizeof(argv)>1 && sizeof(argv[1]) && argv[1][0]=='-') { tmp=resolv("Getopt");
a7a45a1998-05-11Henrik Grubbström (Grubba)  if (!tmp) { werror("master.pike: Couldn't resolv Getopt module.\n" "Is your PIKE_MODULE_PATH environment variable set correctly?\n"); exit(1); }
ca2b071998-03-28Henrik Grubbström (Grubba)  q=tmp->find_all_options(argv,({ ({"version",tmp->NO_ARG,({"-v","--version"})}),
c5cc2d1998-04-29Henrik Grubbström (Grubba)  ({"help",tmp->NO_ARG,({"-h","--help"})}), ({"execute",tmp->HAS_ARG,({"-e","--execute"})}), ({"preprocess",tmp->HAS_ARG,({"-E","--preprocess"})}), ({"modpath",tmp->HAS_ARG,({"-M","--module-path"})}), ({"ipath",tmp->HAS_ARG,({"-I","--include-path"})}), ({"ppath",tmp->HAS_ARG,({"-P","--program-path"})}),
2ea8261998-05-12Martin Stjernholm  ({"showpaths",tmp->NO_ARG,"--show-paths"}),
c5cc2d1998-04-29Henrik Grubbström (Grubba)  ({"warnings",tmp->NO_ARG,({"-w","--warnings"})}),
ac51841998-04-29Henrik Grubbström (Grubba)  ({"master",tmp->HAS_ARG,"-m"}),
c5cc2d1998-04-29Henrik Grubbström (Grubba)  ({"compiler_trace",tmp->NO_ARG,"--compiler-trace"}), ({"debug",tmp->MAY_HAVE_ARG,"--debug",0,1}), ({"trace",tmp->MAY_HAVE_ARG,"--trace",0,1}),
c801c81998-04-29Henrik Grubbström (Grubba)  ({"ignore",tmp->MAY_HAVE_ARG,"-Dqdatpl",0,1}),
ac51841998-04-29Henrik Grubbström (Grubba)  ({"ignore",tmp->HAS_ARG,"-s"}),
c5cc2d1998-04-29Henrik Grubbström (Grubba)  }), 1);
ca2b071998-03-28Henrik Grubbström (Grubba)  /* Parse -M and -I backwards */ for(i=sizeof(q)-1;i>=0;i--) { switch(q[i][0]) {
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) */ 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)  case "master": _master_file_name = q[i][1]; break;
ca2b071998-03-28Henrik Grubbström (Grubba)  } } foreach(q, mixed *opts) { switch(opts[0]) { case "version": werror(version() + " Copyright (C) 1994-1997 Fredrik Hübinette\n" "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" "COPYING and DISCLAIMER in the Pike distribution for more details.\n"); 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"
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);
2ea8261998-05-12Martin Stjernholm  case "showpaths": werror("Include path : " + pike_include_path*"\n" " " + "\n" "Module path : " + pike_module_path*"\n" " " + "\n" "Program path : " + pike_program_path*"\n" " " + "\n"
3692711999-02-05Martin Stjernholm  "Master file : " + (_master_file_name || __FILE__) + "\n");
2ea8261998-05-12Martin Stjernholm  exit(0);
ca2b071998-03-28Henrik Grubbström (Grubba)  case "execute": compile_string("#include <simulate.h>\nmixed create(){"+opts[1]+";}")(); exit(0);
fcf7281998-04-28Fredrik Hübinette (Hubbe) 
c5cc2d1998-04-29Henrik Grubbström (Grubba)  case "preprocess": _static_modules.files()->_stdout->write(cpp(_static_modules.files()->Fd(opts[1],"r")->read(),opts[1])); 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)  } if(sizeof(argv)==1) {
caa3221998-04-15Henrik Grubbström (Grubba)  /* Attempt to resolv Tools.Hilfe.StdinHilfe */ tmp = resolv("Tools"); if (!tmp) { werror("Couldn't find Tools.\n"); exit(1);
ca2b071998-03-28Henrik Grubbström (Grubba)  }
caa3221998-04-15Henrik Grubbström (Grubba)  tmp = tmp["Hilfe"]; if (!tmp) { werror("Couldn't find Hilfe.\n"); exit(1); } tmp->StdinHilfe(); exit(0); } else {
ca2b071998-03-28Henrik Grubbström (Grubba)  argv=argv[1..]; }
471ed91998-04-24Fredrik Hübinette (Hubbe)  argv[0]=combine_path_with_cwd(argv[0]);
ca2b071998-03-28Henrik Grubbström (Grubba) 
34fb3d1998-10-31Henrik Grubbström (Grubba)  program tmp; mixed err = catch { tmp=(program)argv[0]; }; if (err) { werror(sprintf("Pike: Failed to compile script:\n" "%s\n", stringp(err[0])?err[0]:describe_backtrace(err))); exit(1); } // FIXME: Isn't the following code dead?
ca2b071998-03-28Henrik Grubbström (Grubba)  if(!tmp) { werror("Pike: Couldn't find script to execute.\n"); exit(1); } object script=tmp();
862fb41998-04-05Fredrik Hübinette (Hubbe) #if constant(_debug) if(debug) _debug(debug); #endif
ca2b071998-03-28Henrik Grubbström (Grubba)  if(!script->main) { werror("Error: "+argv[0]+" has no main().\n"); exit(1); }
fcf7281998-04-28Fredrik Hübinette (Hubbe)  if(trace) predef::trace(trace);
ca2b071998-03-28Henrik Grubbström (Grubba)  i=script->main(sizeof(argv),argv,env); if(i >=0) exit(i); } mixed inhibit_compile_errors; void set_inhibit_compile_errors(mixed f) { inhibit_compile_errors=f; } string trim_file_name(string s) {
471ed91998-04-24Fredrik Hübinette (Hubbe)  if(getenv("SHORT_PIKE_ERRORS")) return BASENAME(s);
ca2b071998-03-28Henrik Grubbström (Grubba)  return s; } /* * 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. */ void compile_error(string file,int line,string err) { if(!inhibit_compile_errors) { werror(sprintf("%s:%d:%s\n",trim_file_name(file),line,err)); } else if(functionp(inhibit_compile_errors)) { inhibit_compile_errors(file,line,err); } } /* * 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. */ void compile_warning(string file,int line,string err) { if(!inhibit_compile_errors) { if(want_warnings) werror(sprintf("%s:%d:%s\n",trim_file_name(file),line,err)); } }
f4f08d1999-02-26Henrik Grubbström (Grubba) static mixed _charset_mod; /* This function is called by cpp() when it wants to do * character code conversion. */ 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) /* 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 * Note that previous_object cannot be trusted in ths function, because * the compiler calls this function. */ string handle_include(string f, string current_file, int local_include) { string *tmp, path; if(local_include) {
471ed91998-04-24Fredrik Hübinette (Hubbe)  tmp=EXPLODE_PATH(current_file);
ca2b071998-03-28Henrik Grubbström (Grubba)  tmp[-1]=f; path=combine_path_with_cwd(tmp*"/"); } else { foreach(pike_include_path, path) { path=combine_path(path,f); if(master_file_stat(path)) break; else path=0; } } return path; } string read_include(string f) {
781ebe1998-04-08Fredrik Hübinette (Hubbe)  object o=_static_modules.files()->Fd(); if(o->open(f,"r")) return o->read();
ca2b071998-03-28Henrik Grubbström (Grubba) } // FIXME string stupid_describe(mixed m) { switch(string typ=sprintf("%t",m)) { case "int": case "float": return (string)m; case "string":
c896b41998-04-29Henrik Grubbström (Grubba)  if(sizeof(m) < BT_MAX_STRING_LEN)
ca2b071998-03-28Henrik Grubbström (Grubba)  {
c896b41998-04-29Henrik Grubbström (Grubba)  string t = sprintf("%O", m); if (sizeof(t) < (BT_MAX_STRING_LEN + 2)) { return t; } t = 0;
ca2b071998-03-28Henrik Grubbström (Grubba)  } case "array": case "mapping": case "multiset": return typ+"["+sizeof(m)+"]"; default:
c896b41998-04-29Henrik Grubbström (Grubba)  return typ;
ca2b071998-03-28Henrik Grubbström (Grubba)  } }
62e87b1998-04-14Fredrik Hübinette (Hubbe) string describe_program(program p) { string s; if(!p) return 0; if(s=search(programs,p)) { if(sscanf(reverse(s),"%s.%s",string ext,string rest) && ext=="domp")
471ed91998-04-24Fredrik Hübinette (Hubbe)  return EXPLODE_PATH(reverse(rest))[-1];
62e87b1998-04-14Fredrik Hübinette (Hubbe)  return s; }
337ad81998-04-15Fredrik Hübinette (Hubbe)  if(functionp(p)) if(mixed tmp=function_object(p)) if(s=describe_program(object_program(tmp))) return s+"."+function_name(p);
62e87b1998-04-14Fredrik Hübinette (Hubbe)  return 0; }
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. */ string describe_backtrace(mixed *trace) { int e; string ret; if(arrayp(trace) && sizeof(trace)==2 && stringp(trace[0])) { ret=trace[0]; trace=trace[1]; }else{ ret=""; } if(!arrayp(trace)) { ret+="No backtrace.\n"; }else{ for(e=sizeof(trace)-1;e>=0;e--) { mixed tmp; string row; tmp=trace[e]; if(stringp(tmp)) { row=tmp; } else if(arrayp(tmp)) { row=""; if(sizeof(tmp)>=3) { if(functionp(tmp[2])) row=function_name(tmp[2]);
6160771998-04-10Henrik Grubbström (Grubba)  else if (stringp(tmp[2])) { row = tmp[2]; } else
ca2b071998-03-28Henrik Grubbström (Grubba)  row="unknown function"; row+="("; for(int e=3;e<sizeof(tmp);e++) { row+=stupid_describe(tmp[e])+","; } if(sizeof(tmp)>3) row=row[..sizeof(row)-2]; row+=") in "; } if(sizeof(tmp)>=2 && stringp(tmp[0]) && intp(tmp[1])) { row+="line "+tmp[1]+" in "+trim_file_name(tmp[0]); }else{
62e87b1998-04-14Fredrik Hübinette (Hubbe)  mixed desc="Unknown program"; if(sizeof(tmp)>=3 && functionp(tmp[2])) { if(mixed tmp=function_object(tmp[2])) if(tmp=object_program(tmp)) if(tmp=describe_program(tmp)) desc=tmp; } row+=desc;
ca2b071998-03-28Henrik Grubbström (Grubba)  } } else { row="Destructed object"; } ret+=row+"\n"; } } return ret; }
471ed91998-04-24Fredrik Hübinette (Hubbe)  class Codec { mapping f=all_constants(); string nameof(mixed x) { if(mixed tmp=search(f,x)) return "efun:"+tmp; switch(sprintf("%t",x)) { case "program": if(mixed tmp=search(programs,x)) return tmp; if(mixed tmp=search(values(_static_modules), x)) return "_static_modules."+(indices(_static_modules)[tmp]); break; case "object": if(mixed tmp=search(objects,x)) if(tmp=search(programs,tmp)) return tmp; break; } return ([])[0]; } function functionof(string x) { if(sscanf(x,"efun:%s",x)) return f[x]; return 0; } object objectof(string x) { if(sscanf(x,"efun:%s",x)) return f[x]; return (object)x; } program programof(string x) { if(sscanf(x,"efun:%s",x)) return f[x]; return (program)x; } mixed encode_object(object x) { error("Cannot encode objects yet.\n"); } mixed decode_object(object x) { error("Cannot encode objects yet.\n"); } }