|
|
|
|
|
#include "global.h" |
RCSID("$Id: main.c,v 1.62 1999/01/31 09:01:55 hubbe Exp $"); |
#include "fdlib.h" |
#include "backend.h" |
#include "module.h" |
#include "object.h" |
#include "lex.h" |
#include "pike_types.h" |
#include "builtin_functions.h" |
#include "array.h" |
#include "stralloc.h" |
#include "interpret.h" |
#include "error.h" |
#include "pike_macros.h" |
#include "callback.h" |
#include "signal_handler.h" |
#include "threads.h" |
#include "dynamic_load.h" |
#include "gc.h" |
#include "multiset.h" |
#include "mapping.h" |
#include "cpp.h" |
#include "main.h" |
#include "operators.h" |
#include "security.h" |
|
#include <errno.h> |
|
#ifdef HAVE_LOCALE_H |
#include <locale.h> |
#endif |
|
#include "time_stuff.h" |
|
#ifdef HAVE_SYS_RESOURCE_H |
#include <sys/resource.h> |
#endif |
|
|
char *master_file; |
char **ARGV; |
|
int debug_options=0; |
int d_flag=0; |
int c_flag=0; |
int t_flag=0; |
int default_t_flag=0; |
int a_flag=0; |
int l_flag=0; |
int p_flag=0; |
#ifdef YYDEBUG |
extern int yydebug; |
#endif /* YYDEBUG */ |
static long instructions_left; |
|
static void time_to_exit(struct callback *cb,void *tmp,void *ignored) |
{ |
if(instructions_left-- < 0) |
{ |
push_int(0); |
f_exit(1); |
} |
} |
|
static struct callback_list post_master_callbacks; |
|
struct callback *add_post_master_callback(callback_func call, |
void *arg, |
callback_func free_func) |
{ |
return add_to_callback(&post_master_callbacks, call, arg, free_func); |
} |
|
|
static struct callback_list exit_callbacks; |
|
struct callback *add_exit_callback(callback_func call, |
void *arg, |
callback_func free_func) |
{ |
return add_to_callback(&exit_callbacks, call, arg, free_func); |
} |
|
#ifdef __NT__ |
static void get_master_key(long cat) |
{ |
HKEY k; |
char buffer[4096]; |
DWORD len=sizeof(buffer)-1,type=REG_SZ; |
long ret; |
if(RegOpenKeyEx(cat, |
(LPCTSTR)"SOFTWARE\\Idonex\\Pike\\0.6", |
0,KEY_READ,&k)==ERROR_SUCCESS) |
{ |
if(RegQueryValueEx(k, |
"PIKE_MASTER", |
0, |
&type, |
buffer, |
&len)==ERROR_SUCCESS) |
{ |
master_file=strdup(buffer); |
} |
RegCloseKey(k); |
} |
} |
#endif /* __NT__ */ |
|
int dbm_main(int argc, char **argv) |
{ |
JMP_BUF back; |
int e, num, do_backend; |
char *p; |
struct array *a; |
#ifdef DECLARE_ENVIRON |
extern char **environ; |
#endif |
|
ARGV=argv; |
|
fd_init(); |
|
#ifdef HAVE_SETLOCALE |
#ifdef LC_NUMERIC |
setlocale(LC_NUMERIC, "C"); |
#endif |
#ifdef LC_CTYPE |
setlocale(LC_CTYPE, ""); |
#endif |
#ifdef LC_TIME |
setlocale(LC_TIME, "C"); |
#endif |
#ifdef LC_COLLATE |
setlocale(LC_COLLATE, ""); |
#endif |
#ifdef LC_MESSAGES |
setlocale(LC_MESSAGES, ""); |
#endif |
#endif |
init_backend(); |
master_file = 0; |
#if __NT__ |
if(!master_file) get_master_key(HKEY_CURRENT_USER); |
if(!master_file) get_master_key(HKEY_LOCAL_MACHINE); |
#endif |
#ifdef HAVE_GETENV |
if(getenv("PIKE_MASTER")) |
master_file = getenv("PIKE_MASTER"); |
#endif |
|
if(!master_file) master_file = DEFAULT_MASTER; |
|
for(e=1; e<argc; e++) |
{ |
if(argv[e][0]=='-') |
{ |
for(p=argv[e]+1; *p;) |
{ |
switch(*p) |
{ |
case 'D': |
add_predefine(p+1); |
p+=strlen(p); |
break; |
|
case 'm': |
if(p[1]) |
{ |
master_file=p+1; |
p+=strlen(p); |
}else{ |
e++; |
if(e >= argc) |
{ |
fprintf(stderr,"Missing argument to -m\n"); |
exit(1); |
} |
master_file=argv[e]; |
p+=strlen(p); |
} |
break; |
|
case 's': |
if(!p[1]) |
{ |
e++; |
if(e >= argc) |
{ |
fprintf(stderr,"Missing argument to -s\n"); |
exit(1); |
} |
p=argv[e]; |
}else{ |
p++; |
if(*p=='s') |
{ |
if(!p[1]) |
{ |
e++; |
if(e >= argc) |
{ |
fprintf(stderr,"Missing argument to -ss\n"); |
exit(1); |
} |
p=argv[e]; |
}else{ |
p++; |
} |
#ifdef _REENTRANT |
thread_stack_size=STRTOL(p,&p,0); |
#endif |
p+=strlen(p); |
break; |
} |
} |
stack_size=STRTOL(p,&p,0); |
p+=strlen(p); |
|
if(stack_size < 256) |
{ |
fprintf(stderr,"Stack size must at least be 256.\n"); |
exit(1); |
} |
break; |
|
case 'q': |
if(!p[1]) |
{ |
e++; |
if(e >= argc) |
{ |
fprintf(stderr,"Missing argument to -q\n"); |
exit(1); |
} |
p=argv[e]; |
}else{ |
p++; |
} |
instructions_left=STRTOL(p,&p,0); |
p+=strlen(p); |
add_to_callback(&evaluator_callbacks, |
time_to_exit, |
0,0); |
|
break; |
|
case 'd': |
more_d_flags: |
switch(p[1]) |
{ |
case '0': case '1': case '2': case '3': case '4': |
case '5': case '6': case '7': case '8': case '9': |
d_flag+=STRTOL(p+1,&p,10); |
break; |
|
case 'c': |
p++; |
#ifdef YYDEBUG |
yydebug++; |
#endif /* YYDEBUG */ |
break; |
|
case 's': |
debug_options|=DEBUG_SIGNALS; |
p++; |
d_flag--; |
goto more_d_flags; |
|
case 't': |
debug_options|=NO_TAILRECURSION; |
p++; |
d_flag--; |
goto more_d_flags; |
|
default: |
d_flag++,p++; |
} |
break; |
|
case 'a': |
if(p[1]>='0' && p[1]<='9') |
a_flag+=STRTOL(p+1,&p,10); |
else |
a_flag++,p++; |
break; |
|
case 't': |
if(p[1]>='0' && p[1]<='9') |
t_flag+=STRTOL(p+1,&p,10); |
else |
t_flag++,p++; |
default_t_flag = t_flag; |
break; |
|
case 'p': |
if(p[1]>='0' && p[1]<='9') |
p_flag+=STRTOL(p+1,&p,10); |
else |
p_flag++,p++; |
break; |
|
case 'l': |
if(p[1]>='0' && p[1]<='9') |
l_flag+=STRTOL(p+1,&p,10); |
else |
l_flag++,p++; |
break; |
|
default: |
p+=strlen(p); |
} |
} |
}else{ |
break; |
} |
} |
|
#if !defined(RLIMIT_NOFILE) && defined(RLIMIT_OFILE) |
#define RLIMIT_NOFILE RLIMIT_OFILE |
#endif |
|
stack_top = (char *)&argv; |
|
|
|
|
|
|
|
|
|
#if STACK_DIRECTION < 0 |
|
stack_top += (~((unsigned long)stack_top)) & 0xffff; |
#else /* STACK_DIRECTION >= 0 */ |
|
stack_top -= ( ((unsigned long)stack_top)) & 0xffff; |
#endif /* STACK_DIRECTION < 0 */ |
|
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_STACK) |
{ |
struct rlimit lim; |
if(!getrlimit(RLIMIT_STACK, &lim)) |
{ |
#ifdef RLIM_INFINITY |
if(lim.rlim_cur == RLIM_INFINITY) |
lim.rlim_cur=1024*1024*128; |
#endif |
stack_top += STACK_DIRECTION * (lim.rlim_cur - 8192 * sizeof(char *)); |
|
#ifdef STACK_DEBUG |
fprintf(stderr, "1: C-stack: 0x%08p - 0x%08p, direction:%d\n", |
&argv, stack_top, STACK_DIRECTION); |
#endif /* STACK_DEBUG */ |
} |
} |
#else /* !HAVE_GETRLIMIT || !RLIMIT_STACK */ |
|
stack_top += STACK_DIRECTION * (1024*1024 * 8 - 8192 * sizeof(char *)); |
#ifdef STACK_DEBUG |
fprintf(stderr, "2: C-stack: 0x%08p - 0x%08p, direction:%d\n", |
&argv, stack_top, STACK_DIRECTION); |
#endif /* STACK_DEBUG */ |
#endif /* HAVE_GETRLIMIT && RLIMIT_STACK */ |
|
#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE) |
{ |
struct rlimit lim; |
long tmp; |
if(!getrlimit(RLIMIT_NOFILE, &lim)) |
{ |
#ifdef RLIM_INFINITY |
if(lim.rlim_max == RLIM_INFINITY) |
lim.rlim_max=MAX_OPEN_FILEDESCRIPTORS; |
#endif |
tmp=MINIMUM(lim.rlim_max, MAX_OPEN_FILEDESCRIPTORS); |
lim.rlim_cur=tmp; |
setrlimit(RLIMIT_NOFILE, &lim); |
} |
} |
#endif |
|
GETTIMEOFDAY(¤t_time); |
|
init_shared_string_table(); |
init_interpreter(); |
init_types(); |
init_cpp(); |
init_lex(); |
init_program(); |
|
low_th_init(); |
|
init_modules(); |
master(); |
call_callback(& post_master_callbacks, 0); |
free_callback_list(& post_master_callbacks); |
|
if(SETJMP(back)) |
{ |
if(throw_severity == THROW_EXIT) |
{ |
num=throw_value.u.integer; |
}else{ |
ONERROR tmp; |
SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!"); |
push_svalue(& throw_value); |
APPLY_MASTER("handle_error", 1); |
pop_stack(); |
UNSET_ONERROR(tmp); |
num=10; |
} |
}else{ |
back.severity=THROW_EXIT; |
|
a=allocate_array_no_init(argc,0); |
for(num=0;num<argc;num++) |
{ |
ITEM(a)[num].u.string=make_shared_string(argv[num]); |
ITEM(a)[num].type=T_STRING; |
} |
push_array(a); |
|
for(num=0;environ[num];num++); |
a=allocate_array_no_init(num,0); |
for(num=0;environ[num];num++) |
{ |
ITEM(a)[num].u.string=make_shared_string(environ[num]); |
ITEM(a)[num].type=T_STRING; |
} |
push_array(a); |
|
apply(master(),"_main",2); |
pop_stack(); |
|
backend(); |
num=0; |
} |
UNSETJMP(back); |
|
do_exit(num); |
return num; |
} |
|
#undef ATTRIBUTE |
#define ATTRIBUTE(X) |
|
void do_exit(int num) ATTRIBUTE((noreturn)) |
{ |
call_callback(&exit_callbacks, (void *)0); |
free_callback_list(&exit_callbacks); |
|
exit_modules(); |
|
#ifdef DEBUG_MALLOC |
{ |
extern void cleanup_memhdrs(void); |
cleanup_memhdrs(); |
} |
#endif |
|
exit(num); |
} |
|
|
void low_init_main(void) |
{ |
init_pike_security(); |
th_init(); |
init_operators(); |
init_builtin_efuns(); |
init_signals(); |
init_dynamic_load(); |
} |
|
void exit_main(void) |
{ |
cleanup_objects(); |
} |
|
void init_main(void) |
{ |
} |
|
void low_exit_main(void) |
{ |
void cleanup_added_efuns(void); |
void cleanup_pike_types(void); |
void cleanup_program(void); |
void cleanup_compiler(void); |
void cleanup_backend(void); |
|
th_cleanup(); |
exit_dynamic_load(); |
exit_signals(); |
exit_lex(); |
exit_cpp(); |
cleanup_interpret(); |
cleanup_added_efuns(); |
exit_operators(); |
cleanup_pike_types(); |
cleanup_program(); |
cleanup_compiler(); |
cleanup_backend(); |
|
do_gc(); |
free_svalue(& throw_value); |
throw_value.type=T_INT; |
|
#if defined(PIKE_DEBUG) && defined(DEBUG_MALLOC) |
if(verbose_debug_exit) |
{ |
INT32 num,size,recount=0; |
fprintf(stderr,"Exited normally, counting bytes.\n"); |
|
count_memory_in_arrays(&num, &size); |
if(num) |
{ |
recount++; |
fprintf(stderr,"Arrays left: %d (%d bytes) (zapped)\n",num,size); |
} |
|
zap_all_arrays(); |
|
count_memory_in_mappings(&num, &size); |
if(num) |
{ |
recount++; |
fprintf(stderr,"Mappings left: %d (%d bytes) (zapped)\n",num,size); |
} |
|
zap_all_mappings(); |
|
count_memory_in_multisets(&num, &size); |
if(num) |
fprintf(stderr,"Multisets left: %d (%d bytes)\n",num,size); |
|
|
if(recount) |
{ |
fprintf(stderr,"Garbage collecting..\n"); |
do_gc(); |
|
count_memory_in_arrays(&num, &size); |
fprintf(stderr,"Arrays left: %d (%d bytes)\n",num,size); |
count_memory_in_mappings(&num, &size); |
fprintf(stderr,"Mappings left: %d (%d bytes)\n",num,size); |
count_memory_in_multisets(&num, &size); |
fprintf(stderr,"Multisets left: %d (%d bytes)\n",num,size); |
} |
|
|
count_memory_in_programs(&num, &size); |
if(num) |
fprintf(stderr,"Programs left: %d (%d bytes)\n",num,size); |
|
{ |
struct program *p; |
for(p=first_program;p;p=p->next) |
{ |
describe_something(p, T_PROGRAM, 1); |
} |
} |
|
|
count_memory_in_objects(&num, &size); |
if(num) |
fprintf(stderr,"Objects left: %d (%d bytes)\n",num,size); |
|
cleanup_shared_string_table(); |
} |
#else |
|
zap_all_arrays(); |
zap_all_mappings(); |
|
cleanup_shared_string_table(); |
#endif |
cleanup_callbacks(); |
} |
|
|
|