int main(int argc, char* argv[]) { char** copyv; int i; /* duplicate the arguments */ copyv = alloca((argc+1) * sizeof(char*)); for(i=0;i<argc;++i) { copyv[i] = alloca(strlen(argv[i]) + 1); strcpy(copyv[i], argv[i]); } copyv[i] = 0; /* set the entry point to restart the program */ if (sigsetjmp(OS_HUP, 1) != 0) { /* restart the program */ execv(copyv[0], copyv); /* abort if fail */ abort(); } if (target_init() != 0) return EXIT_FAILURE; if (file_init() != 0) { target_done(); return EXIT_FAILURE; } if (os_main(argc, argv) != 0) { file_done(); target_done(); return EXIT_FAILURE; } file_done(); target_done(); return EXIT_SUCCESS; }
/* * file_connect() gets called from Curl_protocol_connect() to allow us to * do protocol-specific actions at connect-time. We emulate a * connect-then-transfer protocol and "connect" to the file here */ static CURLcode file_connect(struct connectdata *conn, bool *done) { struct SessionHandle *data = conn->data; char *real_path = curl_easy_unescape(data, data->state.path, 0, NULL); struct FILEPROTO *file; int fd; #ifdef DOS_FILESYSTEM int i; char *actual_path; #endif if(!real_path) return CURLE_OUT_OF_MEMORY; /* If there already is a protocol-specific struct allocated for this sessionhandle, deal with it */ Curl_reset_reqproto(conn); if(!data->state.proto.file) { file = calloc(sizeof(struct FILEPROTO), 1); if(!file) { free(real_path); return CURLE_OUT_OF_MEMORY; } data->state.proto.file = file; } else { /* file is not a protocol that can deal with "persistancy" */ file = data->state.proto.file; Curl_safefree(file->freepath); if(file->fd != -1) close(file->fd); file->path = NULL; file->freepath = NULL; file->fd = -1; } #ifdef DOS_FILESYSTEM /* If the first character is a slash, and there's something that looks like a drive at the beginning of the path, skip the slash. If we remove the initial slash in all cases, paths without drive letters end up relative to the current directory which isn't how browsers work. Some browsers accept | instead of : as the drive letter separator, so we do too. On other platforms, we need the slash to indicate an absolute pathname. On Windows, absolute paths start with a drive letter. */ actual_path = real_path; if((actual_path[0] == '/') && actual_path[1] && (actual_path[2] == ':' || actual_path[2] == '|')) { actual_path[2] = ':'; actual_path++; } /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */ for (i=0; actual_path[i] != '\0'; ++i) if(actual_path[i] == '/') actual_path[i] = '\\'; fd = open_readonly(actual_path, O_RDONLY|O_BINARY); /* no CR/LF translation */ file->path = actual_path; #else fd = open_readonly(real_path, O_RDONLY); file->path = real_path; #endif file->freepath = real_path; /* free this when done */ file->fd = fd; if(!data->set.upload && (fd == -1)) { failf(data, "Couldn't open file %s", data->state.path); file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); return CURLE_FILE_COULDNT_READ_FILE; } *done = TRUE; return CURLE_OK; }
/* * file_connect() gets called from Curl_protocol_connect() to allow us to * do protocol-specific actions at connect-time. We emulate a * connect-then-transfer protocol and "connect" to the file here */ static CURLcode file_connect(struct connectdata *conn, bool *done) { struct SessionHandle *data = conn->data; char *real_path; struct FILEPROTO *file = data->req.protop; int fd; #ifdef DOS_FILESYSTEM int i; char *actual_path; #endif int real_path_len; real_path = curl_easy_unescape(data, data->state.path, 0, &real_path_len); if(!real_path) return CURLE_OUT_OF_MEMORY; #ifdef DOS_FILESYSTEM /* If the first character is a slash, and there's something that looks like a drive at the beginning of the path, skip the slash. If we remove the initial slash in all cases, paths without drive letters end up relative to the current directory which isn't how browsers work. Some browsers accept | instead of : as the drive letter separator, so we do too. On other platforms, we need the slash to indicate an absolute pathname. On Windows, absolute paths start with a drive letter. */ actual_path = real_path; if((actual_path[0] == '/') && actual_path[1] && (actual_path[2] == ':' || actual_path[2] == '|')) { actual_path[2] = ':'; actual_path++; real_path_len--; } /* change path separators from '/' to '\\' for DOS, Windows and OS/2 */ for(i=0; i < real_path_len; ++i) if(actual_path[i] == '/') actual_path[i] = '\\'; else if(!actual_path[i]) /* binary zero */ return CURLE_URL_MALFORMAT; fd = open_readonly(actual_path, O_RDONLY|O_BINARY); file->path = actual_path; #else if(memchr(real_path, 0, real_path_len)) /* binary zeroes indicate foul play */ return CURLE_URL_MALFORMAT; fd = open_readonly(real_path, O_RDONLY); file->path = real_path; #endif file->freepath = real_path; /* free this when done */ file->fd = fd; if(!data->set.upload && (fd == -1)) { failf(data, "Couldn't open file %s", data->state.path); file_done(conn, CURLE_FILE_COULDNT_READ_FILE, FALSE); return CURLE_FILE_COULDNT_READ_FILE; } *done = TRUE; return CURLE_OK; }
int main( int argc, char * * argv, char * * arg_environ ) { int n; char * s; struct bjam_option optv[N_OPTS]; char const * all = "all"; int status; int arg_c = argc; char * * arg_v = argv; char const * progname = argv[0]; module_t * environ_module; #if defined(unix) || defined(__unix) sigset_t sigmask; struct sigaction sa; sigemptyset(&sigmask); sigaddset(&sigmask, SIGCHLD); sigprocmask(SIG_BLOCK, &sigmask, NULL); sa.sa_flags = 0; sa.sa_handler = child_sig_handler; sigemptyset(&sa.sa_mask); sigaction(SIGCHLD, &sa, NULL); sigemptyset(&empty_sigmask); #endif saved_argv0 = argv[0]; BJAM_MEM_INIT(); # ifdef OS_MAC InitGraf(&qd.thePort); # endif --argc; ++argv; if ( getoptions( argc, argv, "-:l:m:d:j:p:f:gs:t:ano:qv", optv ) < 0 ) { printf( "\nusage: %s [ options ] targets...\n\n", progname ); printf( "-a Build all targets, even if they are current.\n" ); printf( "-dx Set the debug level to x (0-9).\n" ); printf( "-fx Read x instead of Jambase.\n" ); /* printf( "-g Build from newest sources first.\n" ); */ printf( "-jx Run up to x shell commands concurrently.\n" ); printf( "-lx Limit actions to x number of seconds after which they are stopped.\n" ); printf( "-mx Limit action output buffer to x kb's of data, after which action output is read and ignored.\n" ); printf( "-n Don't actually execute the updating actions.\n" ); printf( "-ox Write the updating actions to file x.\n" ); printf( "-px x=0, pipes action stdout and stderr merged into action output.\n" ); printf( "-q Quit quickly as soon as a target fails.\n" ); printf( "-sx=y Set variable x=y, overriding environment.\n" ); printf( "-tx Rebuild x, even if it is up-to-date.\n" ); printf( "-v Print the version of jam and exit.\n" ); printf( "--x Option is ignored.\n\n" ); exit( EXITBAD ); } /* Version info. */ if ( ( s = getoptval( optv, 'v', 0 ) ) ) { printf( "Boost.Jam " ); printf( "Version %s. %s.\n", VERSION, OSMINOR ); printf( " Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. \n" ); printf( " Copyright 2001 David Turner.\n" ); printf( " Copyright 2001-2004 David Abrahams.\n" ); printf( " Copyright 2002-2008 Rene Rivera.\n" ); printf( " Copyright 2003-2008 Vladimir Prus.\n" ); return EXITOK; } /* Pick up interesting options. */ if ( ( s = getoptval( optv, 'n', 0 ) ) ) globs.noexec++, globs.debug[2] = 1; if ( ( s = getoptval( optv, 'p', 0 ) ) ) { /* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action * stdout and stderr. */ globs.pipe_action = atoi( s ); if ( ( 3 < globs.pipe_action ) || ( globs.pipe_action < 0 ) ) { printf( "Invalid pipe descriptor '%d', valid values are -p[0..3].\n", globs.pipe_action ); exit( EXITBAD ); } } if ( ( s = getoptval( optv, 'q', 0 ) ) ) globs.quitquick = 1; if ( ( s = getoptval( optv, 'a', 0 ) ) ) anyhow++; if ( ( s = getoptval( optv, 'j', 0 ) ) ) { globs.jobs = atoi( s ); if (globs.jobs == 0) { printf("Invalid value for the '-j' option.\n"); exit(EXITBAD); } } if ( ( s = getoptval( optv, 'g', 0 ) ) ) globs.newestfirst = 1; if ( ( s = getoptval( optv, 'l', 0 ) ) ) globs.timeout = atoi( s ); if ( ( s = getoptval( optv, 'm', 0 ) ) ) globs.maxbuf = atoi( s ) * 1024; /* Turn on/off debugging */ for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n ) { int i; /* First -d, turn off defaults. */ if ( !n ) for ( i = 0; i < DEBUG_MAX; ++i ) globs.debug[i] = 0; i = atoi( s ); if ( ( i < 0 ) || ( i >= DEBUG_MAX ) ) { printf( "Invalid debug level '%s'.\n", s ); continue; } /* n turns on levels 1-n. */ /* +n turns on level n. */ if ( *s == '+' ) globs.debug[i] = 1; else while ( i ) globs.debug[i--] = 1; } constants_init(); { PROFILE_ENTER( MAIN ); #ifdef HAVE_PYTHON { PROFILE_ENTER( MAIN_PYTHON ); Py_Initialize(); { static PyMethodDef BjamMethods[] = { {"call", bjam_call, METH_VARARGS, "Call the specified bjam rule."}, {"import_rule", bjam_import_rule, METH_VARARGS, "Imports Python callable to bjam."}, {"define_action", bjam_define_action, METH_VARARGS, "Defines a command line action."}, {"variable", bjam_variable, METH_VARARGS, "Obtains a variable from bjam's global module."}, {"backtrace", bjam_backtrace, METH_VARARGS, "Returns bjam backtrace from the last call into Python."}, {"caller", bjam_caller, METH_VARARGS, "Returns the module from which the last call into Python is made."}, {NULL, NULL, 0, NULL} }; Py_InitModule( "bjam", BjamMethods ); } PROFILE_EXIT( MAIN_PYTHON ); } #endif #ifndef NDEBUG run_unit_tests(); #endif #if YYDEBUG != 0 if ( DEBUG_PARSE ) yydebug = 1; #endif /* Set JAMDATE. */ var_set( root_module(), constant_JAMDATE, list_new( L0, outf_time(time(0)) ), VAR_SET ); /* Set JAM_VERSION. */ var_set( root_module(), constant_JAM_VERSION, list_new( list_new( list_new( L0, object_new( VERSION_MAJOR_SYM ) ), object_new( VERSION_MINOR_SYM ) ), object_new( VERSION_PATCH_SYM ) ), VAR_SET ); /* Set JAMUNAME. */ #if defined(unix) || defined(__unix) { struct utsname u; if ( uname( &u ) >= 0 ) { var_set( root_module(), constant_JAMUNAME, list_new( list_new( list_new( list_new( list_new( L0, object_new( u.sysname ) ), object_new( u.nodename ) ), object_new( u.release ) ), object_new( u.version ) ), object_new( u.machine ) ), VAR_SET ); } } #endif /* unix */ /* Load up environment variables. */ /* First into the global module, with splitting, for backward * compatibility. */ var_defines( root_module(), use_environ, 1 ); environ_module = bindmodule( constant_ENVIRON ); /* Then into .ENVIRON, without splitting. */ var_defines( environ_module, use_environ, 0 ); /* * Jam defined variables OS & OSPLAT. We load them after environment, so * that setting OS in environment does not change Jam's notion of the * current platform. */ var_defines( root_module(), othersyms, 1 ); /* Load up variables set on command line. */ for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n ) { char *symv[2]; symv[ 0 ] = s; symv[ 1 ] = 0; var_defines( root_module(), symv, 1 ); var_defines( environ_module, symv, 0 ); } /* Set the ARGV to reflect the complete list of arguments of invocation. */ for ( n = 0; n < arg_c; ++n ) { var_set( root_module(), constant_ARGV, list_new( L0, object_new( arg_v[n] ) ), VAR_APPEND ); } /* Initialize built-in rules. */ load_builtins(); /* Add the targets in the command line to the update list. */ for ( n = 1; n < arg_c; ++n ) { if ( arg_v[ n ][ 0 ] == '-' ) { char * f = "-:l:d:j:f:gs:t:ano:qv"; for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break; if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n; } else { OBJECT * target = object_new( arg_v[ n ] ); mark_target_for_updating( target ); object_free( target ); } } if (!targets_to_update()) { mark_target_for_updating( constant_all ); } /* Parse ruleset. */ { FRAME frame[ 1 ]; frame_init( frame ); for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n ) { OBJECT * filename = object_new( s ); parse_file( filename, frame ); object_free( filename ); } if ( !n ) { parse_file( constant_plus, frame ); } } status = yyanyerrors(); /* Manually touch -t targets. */ for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n ) { OBJECT * target = object_new( s ); touch_target( target ); object_free( target ); } /* If an output file is specified, set globs.cmdout to that. */ if ( ( s = getoptval( optv, 'o', 0 ) ) ) { if ( !( globs.cmdout = fopen( s, "w" ) ) ) { printf( "Failed to write to '%s'\n", s ); exit( EXITBAD ); } ++globs.noexec; } /* The build system may set the PARALLELISM variable to override -j options. */ { LIST *p = L0; p = var_get ( root_module(), constant_PARALLELISM ); if ( p ) { int j = atoi( object_str( p->value ) ); if ( j == -1 ) { printf( "Invalid value of PARALLELISM: %s\n", object_str( p->value ) ); } else { globs.jobs = j; } } } /* KEEP_GOING overrides -q option. */ { LIST *p = L0; p = var_get( root_module(), constant_KEEP_GOING ); if ( p ) { int v = atoi( object_str( p->value ) ); if ( v == 0 ) globs.quitquick = 1; else globs.quitquick = 0; } } /* Now make target. */ { PROFILE_ENTER( MAIN_MAKE ); LIST * targets = targets_to_update(); if (targets) { int targets_count = list_length( targets ); OBJECT * * targets2 = (OBJECT * *) BJAM_MALLOC( targets_count * sizeof( OBJECT * ) ); int n = 0; for ( ; targets; targets = list_next( targets ) ) targets2[ n++ ] = targets->value; status |= make( targets_count, targets2, anyhow ); BJAM_FREE( (void *)targets2 ); } else { status = last_update_now_status; } PROFILE_EXIT( MAIN_MAKE ); } PROFILE_EXIT( MAIN ); } if ( DEBUG_PROFILE ) profile_dump(); #ifdef OPT_HEADER_CACHE_EXT hcache_done(); #endif clear_targets_to_update(); /* Widely scattered cleanup. */ file_done(); rules_done(); stamps_done(); search_done(); class_done(); modules_done(); regex_done(); exec_done(); pwd_done(); path_done(); function_done(); list_done(); constants_done(); object_done(); /* Close cmdout. */ if ( globs.cmdout ) fclose( globs.cmdout ); #ifdef HAVE_PYTHON Py_Finalize(); #endif BJAM_MEM_CLOSE(); return status ? EXITBAD : EXITOK; }
/** * Gets the current timeout value to use for the main loop * * First check to see if any active groups have an expired timeout, and * handle that timeout. Once all expired timeouts have been handled, find * the active group with the earliest timeout and return the time until that * timeout. If there are no active groups, return NULL. */ struct timeval *getrecenttimeout(void) { static struct timeval tv = {0,0}; struct timeval current_timestamp, min_timestamp; int i, found_timeout, done, sent_naks; struct group_list_t *group; unsigned int section, nak_count; unsigned char *naks; gettimeofday(¤t_timestamp, NULL); done = 0; while (!done) { found_timeout = 0; done = 1; for (i = 0; i < MAXLIST; i++) { group = &group_list[i]; if (group->group_id != 0) { if (cmptimestamp(current_timestamp, group->timeout_time) >= 0) { switch (group->phase) { case PHASE_REGISTERED: send_register(group); break; case PHASE_RECEIVING: case PHASE_MIDGROUP: glog1(group, "Transfer timed out"); send_abort(group, "Transfer timed out"); break; case PHASE_COMPLETE: send_complete(group, 0); break; } done = 0; } else if ((!found_timeout) || (cmptimestamp(group->timeout_time, min_timestamp) < 0)) { glog5(group, "found min timeout time: %d:%06d", group->timeout_time.tv_sec, group->timeout_time.tv_usec); min_timestamp = group->timeout_time; found_timeout = 1; } // Check for a NAK timeout for sending a STATUS or COMPLETE if ((group->fileinfo.nak_time.tv_sec != 0) && cmptimestamp(current_timestamp, group->fileinfo.nak_time) >= 0) { group->fileinfo.nak_time.tv_sec = 0; group->fileinfo.nak_time.tv_usec = 0; // Send NAKs sent_naks = 0; retry_naks: for (section = group->fileinfo.nak_section_first; section < group->fileinfo.nak_section_last; section++) { naks = NULL; nak_count = get_naks(group, section, &naks); glog3(group, "read %d NAKs for section %d", nak_count, section); if (nak_count > 0) { send_status(group, section, naks, nak_count); sent_naks = 1; } free(naks); naks = NULL; } if (file_done(group, 1)) { glog2(group, "File transfer complete"); send_complete(group, 0); file_cleanup(group, 0); } else if (group->fileinfo.got_done && !sent_naks) { // We didn't send any NAKs since the last time // but the server is asking for some, // so check all prior sections group->fileinfo.nak_section_last = group->fileinfo.nak_section_first; group->fileinfo.nak_section_first = 0; group->fileinfo.got_done = 0; goto retry_naks; } } else if ((group->fileinfo.nak_time.tv_sec != 0) && ((!found_timeout) || (cmptimestamp(group->fileinfo.nak_time, min_timestamp) < 0))) { glog5(group, "found min nak time: %d:%06d", group->fileinfo.nak_time.tv_sec, group->fileinfo.nak_time.tv_usec); min_timestamp = group->fileinfo.nak_time; found_timeout = 1; } // Check congestion control feedback timer if (!group->isclr) { if ((group->cc_time.tv_sec != 0) && (cmptimestamp(current_timestamp, group->cc_time) >= 0)) { send_cc_ack(group); } else if ((group->cc_time.tv_sec != 0) && ((!found_timeout) || (cmptimestamp(group->cc_time, min_timestamp) < 0))) { glog5(group, "found min CC time: %d:%06d", group->cc_time.tv_sec, group->cc_time.tv_usec); min_timestamp = group->cc_time; found_timeout = 1; } } } } // Check timeout for proxy key request if (has_proxy && (proxy_pubkey.key == 0)) { if (cmptimestamp(current_timestamp, next_keyreq_time) >= 0) { send_key_req(); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_keyreq_time, min_timestamp) < 0)) { min_timestamp = next_keyreq_time; found_timeout = 1; } } // Check timeout for sending heartbeat if (hbhost_count) { if (cmptimestamp(current_timestamp, next_hb_time) >= 0) { send_hb_request(listener, hb_hosts, hbhost_count, &next_hb_time, hb_interval, uid); done = 0; } else if ((!found_timeout) || (cmptimestamp(next_hb_time, min_timestamp) < 0)) { min_timestamp = next_hb_time; found_timeout = 1; } } } if (found_timeout) { tv = diff_timeval(min_timestamp, current_timestamp); return &tv; } else { return NULL; } }
int main( int argc, char * * argv, char * * arg_environ ) { int n; char * s; struct bjam_option optv[ N_OPTS ]; char const * all = "all"; int status; int arg_c = argc; char * * arg_v = argv; char const * progname = argv[ 0 ]; module_t * environ_module; saved_argv0 = argv[ 0 ]; BJAM_MEM_INIT(); #ifdef OS_MAC InitGraf( &qd.thePort ); #endif --argc; ++argv; #ifdef HAVE_PYTHON #define OPTSTRING "-:l:m:d:j:p:f:gs:t:ano:qvz" #else #define OPTSTRING "-:l:m:d:j:p:f:gs:t:ano:qv" #endif if ( getoptions( argc, argv, OPTSTRING, optv ) < 0 ) { err_printf( "\nusage: %s [ options ] targets...\n\n", progname ); err_printf( "-a Build all targets, even if they are current.\n" ); err_printf( "-dx Set the debug level to x (0-9).\n" ); err_printf( "-fx Read x instead of Jambase.\n" ); /* err_printf( "-g Build from newest sources first.\n" ); */ err_printf( "-jx Run up to x shell commands concurrently.\n" ); err_printf( "-lx Limit actions to x number of seconds after which they are stopped.\n" ); err_printf( "-mx Maximum target output saved (kb), default is to save all output.\n" ); err_printf( "-n Don't actually execute the updating actions.\n" ); err_printf( "-ox Mirror all output to file x.\n" ); err_printf( "-px x=0, pipes action stdout and stderr merged into action output.\n" ); err_printf( "-q Quit quickly as soon as a target fails.\n" ); err_printf( "-sx=y Set variable x=y, overriding environment.\n" ); err_printf( "-tx Rebuild x, even if it is up-to-date.\n" ); err_printf( "-v Print the version of jam and exit.\n" ); #ifdef HAVE_PYTHON err_printf( "-z Disable Python Optimization and enable asserts\n" ); #endif err_printf( "--x Option is ignored.\n\n" ); exit( EXITBAD ); } /* Version info. */ if ( ( s = getoptval( optv, 'v', 0 ) ) ) { out_printf( "Boost.Jam Version %s. %s.\n", VERSION, OSMINOR ); out_printf( " Copyright 1993-2002 Christopher Seiwald and Perforce " "Software, Inc.\n" ); out_printf( " Copyright 2001 David Turner.\n" ); out_printf( " Copyright 2001-2004 David Abrahams.\n" ); out_printf( " Copyright 2002-2015 Rene Rivera.\n" ); out_printf( " Copyright 2003-2015 Vladimir Prus.\n" ); return EXITOK; } /* Pick up interesting options. */ if ( ( s = getoptval( optv, 'n', 0 ) ) ) { ++globs.noexec; globs.debug[ 2 ] = 1; } if ( ( s = getoptval( optv, 'p', 0 ) ) ) { /* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action * stdout and stderr. */ globs.pipe_action = atoi( s ); if ( globs.pipe_action < 0 || 3 < globs.pipe_action ) { err_printf( "Invalid pipe descriptor '%d', valid values are -p[0..3]." "\n", globs.pipe_action ); exit( EXITBAD ); } } if ( ( s = getoptval( optv, 'q', 0 ) ) ) globs.quitquick = 1; if ( ( s = getoptval( optv, 'a', 0 ) ) ) anyhow++; if ( ( s = getoptval( optv, 'j', 0 ) ) ) { globs.jobs = atoi( s ); if ( globs.jobs < 1 || globs.jobs > MAXJOBS ) { err_printf( "Invalid value for the '-j' option, valid values are 1 " "through %d.\n", MAXJOBS ); exit( EXITBAD ); } } if ( ( s = getoptval( optv, 'g', 0 ) ) ) globs.newestfirst = 1; if ( ( s = getoptval( optv, 'l', 0 ) ) ) globs.timeout = atoi( s ); if ( ( s = getoptval( optv, 'm', 0 ) ) ) globs.max_buf = atoi( s ) * 1024; /* convert to kb */ #ifdef HAVE_PYTHON if ( ( s = getoptval( optv, 'z', 0 ) ) ) python_optimize = 0; /* disable python optimization */ #endif /* Turn on/off debugging */ for ( n = 0; ( s = getoptval( optv, 'd', n ) ); ++n ) { int i; /* First -d, turn off defaults. */ if ( !n ) for ( i = 0; i < DEBUG_MAX; ++i ) globs.debug[i] = 0; i = atoi( s ); if ( ( i < 0 ) || ( i >= DEBUG_MAX ) ) { out_printf( "Invalid debug level '%s'.\n", s ); continue; } /* n turns on levels 1-n. */ /* +n turns on level n. */ if ( *s == '+' ) globs.debug[ i ] = 1; else while ( i ) globs.debug[ i-- ] = 1; } /* If an output file is specified, set globs.out to that. */ if ( ( s = getoptval( optv, 'o', 0 ) ) ) { if ( !( globs.out = fopen( s, "w" ) ) ) { err_printf( "Failed to write to '%s'\n", s ); exit( EXITBAD ); } /* ++globs.noexec; */ } constants_init(); cwd_init(); { PROFILE_ENTER( MAIN ); #ifdef HAVE_PYTHON { PROFILE_ENTER( MAIN_PYTHON ); Py_OptimizeFlag = python_optimize; Py_Initialize(); { static PyMethodDef BjamMethods[] = { {"call", bjam_call, METH_VARARGS, "Call the specified bjam rule."}, {"import_rule", bjam_import_rule, METH_VARARGS, "Imports Python callable to bjam."}, {"define_action", bjam_define_action, METH_VARARGS, "Defines a command line action."}, {"variable", bjam_variable, METH_VARARGS, "Obtains a variable from bjam's global module."}, {"backtrace", bjam_backtrace, METH_VARARGS, "Returns bjam backtrace from the last call into Python."}, {"caller", bjam_caller, METH_VARARGS, "Returns the module from which the last call into Python is made."}, {NULL, NULL, 0, NULL} }; Py_InitModule( "bjam", BjamMethods ); } PROFILE_EXIT( MAIN_PYTHON ); } #endif #ifndef NDEBUG run_unit_tests(); #endif #if YYDEBUG != 0 if ( DEBUG_PARSE ) yydebug = 1; #endif /* Set JAMDATE. */ { timestamp current; timestamp_current( ¤t ); var_set( root_module(), constant_JAMDATE, list_new( outf_time( ¤t ) ), VAR_SET ); } /* Set JAM_VERSION. */ var_set( root_module(), constant_JAM_VERSION, list_push_back( list_push_back( list_new( object_new( VERSION_MAJOR_SYM ) ), object_new( VERSION_MINOR_SYM ) ), object_new( VERSION_PATCH_SYM ) ), VAR_SET ); /* Set JAMUNAME. */ #ifdef unix { struct utsname u; if ( uname( &u ) >= 0 ) { var_set( root_module(), constant_JAMUNAME, list_push_back( list_push_back( list_push_back( list_push_back( list_new( object_new( u.sysname ) ), object_new( u.nodename ) ), object_new( u.release ) ), object_new( u.version ) ), object_new( u.machine ) ), VAR_SET ); } } #endif /* unix */ /* Set JAM_TIMESTAMP_RESOLUTION. */ { timestamp fmt_resolution[ 1 ]; file_supported_fmt_resolution( fmt_resolution ); var_set( root_module(), constant_JAM_TIMESTAMP_RESOLUTION, list_new( object_new( timestamp_timestr( fmt_resolution ) ) ), VAR_SET ); } /* Load up environment variables. */ /* First into the global module, with splitting, for backward * compatibility. */ var_defines( root_module(), use_environ, 1 ); environ_module = bindmodule( constant_ENVIRON ); /* Then into .ENVIRON, without splitting. */ var_defines( environ_module, use_environ, 0 ); /* * Jam defined variables OS & OSPLAT. We load them after environment, so * that setting OS in environment does not change Jam's notion of the * current platform. */ var_defines( root_module(), othersyms, 1 ); /* Load up variables set on command line. */ for ( n = 0; ( s = getoptval( optv, 's', n ) ); ++n ) { char * symv[ 2 ]; symv[ 0 ] = s; symv[ 1 ] = 0; var_defines( root_module(), symv, 1 ); var_defines( environ_module, symv, 0 ); } /* Set the ARGV to reflect the complete list of arguments of invocation. */ for ( n = 0; n < arg_c; ++n ) var_set( root_module(), constant_ARGV, list_new( object_new( arg_v[ n ] ) ), VAR_APPEND ); /* Initialize built-in rules. */ load_builtins(); /* Add the targets in the command line to the update list. */ for ( n = 1; n < arg_c; ++n ) { if ( arg_v[ n ][ 0 ] == '-' ) { char * f = "-:l:d:j:f:gs:t:ano:qv"; for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break; if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n; } else { OBJECT * const target = object_new( arg_v[ n ] ); mark_target_for_updating( target ); object_free( target ); } } if ( list_empty( targets_to_update() ) ) mark_target_for_updating( constant_all ); /* Parse ruleset. */ { FRAME frame[ 1 ]; frame_init( frame ); for ( n = 0; ( s = getoptval( optv, 'f', n ) ); ++n ) { OBJECT * const filename = object_new( s ); parse_file( filename, frame ); object_free( filename ); } if ( !n ) parse_file( constant_plus, frame ); } status = yyanyerrors(); /* Manually touch -t targets. */ for ( n = 0; ( s = getoptval( optv, 't', n ) ); ++n ) { OBJECT * const target = object_new( s ); touch_target( target ); object_free( target ); } /* The build system may set the PARALLELISM variable to override -j * options. */ { LIST * const p = var_get( root_module(), constant_PARALLELISM ); if ( !list_empty( p ) ) { int const j = atoi( object_str( list_front( p ) ) ); if ( j < 1 || j > MAXJOBS ) out_printf( "Invalid value of PARALLELISM: %s. Valid values " "are 1 through %d.\n", object_str( list_front( p ) ), MAXJOBS ); else globs.jobs = j; } } /* KEEP_GOING overrides -q option. */ { LIST * const p = var_get( root_module(), constant_KEEP_GOING ); if ( !list_empty( p ) ) globs.quitquick = atoi( object_str( list_front( p ) ) ) ? 0 : 1; } /* Now make target. */ { PROFILE_ENTER( MAIN_MAKE ); LIST * const targets = targets_to_update(); if ( !list_empty( targets ) ) status |= make( targets, anyhow ); else status = last_update_now_status; PROFILE_EXIT( MAIN_MAKE ); } PROFILE_EXIT( MAIN ); } if ( DEBUG_PROFILE ) profile_dump(); #ifdef OPT_HEADER_CACHE_EXT hcache_done(); #endif clear_targets_to_update(); /* Widely scattered cleanup. */ property_set_done(); file_done(); rules_done(); timestamp_done(); search_done(); class_done(); modules_done(); regex_done(); cwd_done(); path_done(); function_done(); list_done(); constants_done(); object_done(); /* Close log out. */ if ( globs.out ) fclose( globs.out ); #ifdef HAVE_PYTHON Py_Finalize(); #endif BJAM_MEM_CLOSE(); return status ? EXITBAD : EXITOK; }
int main( int argc, char **argv, char **arg_environ ) { int n; char *s; struct option optv[N_OPTS]; const char *all = "all"; int anyhow = 0; int status; int arg_c = argc; char ** arg_v = argv; const char *progname = argv[0]; # ifdef OS_MAC InitGraf(&qd.thePort); # endif argc--, argv++; if( getoptions( argc, argv, "-:l:d:j:f:gs:t:ano:qv", optv ) < 0 ) { printf( "\nusage: %s [ options ] targets...\n\n", progname ); printf( "-a Build all targets, even if they are current.\n" ); printf( "-dx Set the debug level to x (0-9).\n" ); printf( "-fx Read x instead of Jambase.\n" ); /* printf( "-g Build from newest sources first.\n" ); */ printf( "-jx Run up to x shell commands concurrently.\n" ); printf( "-lx Limit actions to x number of seconds after which they are stopped.\n" ); printf( "-n Don't actually execute the updating actions.\n" ); printf( "-ox Write the updating actions to file x.\n" ); printf( "-q Quit quickly as soon as a target fails.\n" ); printf( "-sx=y Set variable x=y, overriding environment.\n" ); printf( "-tx Rebuild x, even if it is up-to-date.\n" ); printf( "-v Print the version of jam and exit.\n" ); printf( "--x Option is ignored.\n\n" ); exit( EXITBAD ); } /* Version info. */ if( ( s = getoptval( optv, 'v', 0 ) ) ) { printf( "Boost.Jam " ); printf( "Version %s. %s.\n", VERSION, OSMINOR ); printf( " Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. \n" ); printf( " Copyright 2001 David Turner.\n" ); printf( " Copyright 2001-2004 David Abrahams.\n" ); printf( " Copyright 2002-2005 Rene Rivera.\n" ); printf( " Copyright 2003-2005 Vladimir Prus.\n" ); return EXITOK; } /* Pick up interesting options */ if( ( s = getoptval( optv, 'n', 0 ) ) ) globs.noexec++, globs.debug[2] = 1; if( ( s = getoptval( optv, 'q', 0 ) ) ) globs.quitquick = 1; if( ( s = getoptval( optv, 'a', 0 ) ) ) anyhow++; if( ( s = getoptval( optv, 'j', 0 ) ) ) globs.jobs = atoi( s ); if( ( s = getoptval( optv, 'g', 0 ) ) ) globs.newestfirst = 1; if( ( s = getoptval( optv, 'l', 0 ) ) ) globs.timeout = atoi( s ); /* Turn on/off debugging */ for( n = 0; s = getoptval( optv, 'd', n ); n++ ) { int i; /* First -d, turn off defaults. */ if( !n ) for( i = 0; i < DEBUG_MAX; i++ ) globs.debug[i] = 0; i = atoi( s ); if( i < 0 || i >= DEBUG_MAX ) { printf( "Invalid debug level '%s'.\n", s ); continue; } /* n turns on levels 1-n */ /* +n turns on level n */ if( *s == '+' ) globs.debug[i] = 1; else while( i ) globs.debug[i--] = 1; } { PROFILE_ENTER(MAIN); #ifdef HAVE_PYTHON { PROFILE_ENTER(MAIN_PYTHON); Py_Initialize(); { static PyMethodDef BjamMethods[] = { {"call", bjam_call, METH_VARARGS, "Call the specified bjam rule."}, {"import_rule", bjam_import_rule, METH_VARARGS, "Imports Python callable to bjam."}, {NULL, NULL, 0, NULL} }; Py_InitModule("bjam", BjamMethods); } PROFILE_EXIT(MAIN_PYTHON); } #endif #ifndef NDEBUG run_unit_tests(); #endif #if YYDEBUG != 0 if ( DEBUG_PARSE ) yydebug = 1; #endif /* Set JAMDATE first */ { char *date; time_t clock; time( &clock ); date = newstr( ctime( &clock ) ); /* Trim newline from date */ if( strlen( date ) == 25 ) date[ 24 ] = 0; var_set( "JAMDATE", list_new( L0, newstr( date ) ), VAR_SET ); } var_set( "JAM_VERSION", list_new( list_new( list_new( L0, newstr( VERSION_MAJOR_SYM ) ), newstr( VERSION_MINOR_SYM ) ), newstr( VERSION_PATCH_SYM ) ), VAR_SET ); /* And JAMUNAME */ # ifdef unix { struct utsname u; if( uname( &u ) >= 0 ) { var_set( "JAMUNAME", list_new( list_new( list_new( list_new( list_new( L0, newstr( u.sysname ) ), newstr( u.nodename ) ), newstr( u.release ) ), newstr( u.version ) ), newstr( u.machine ) ), VAR_SET ); } } # endif /* unix */ /* load up environment variables */ /* first into global module, with splitting, for backward compatibility */ var_defines( use_environ, 1 ); /* then into .ENVIRON, without splitting */ enter_module( bindmodule(".ENVIRON") ); var_defines( use_environ, 0 ); exit_module( bindmodule(".ENVIRON") ); /* * Jam defined variables OS, OSPLAT * We load them after environment, so that * setting OS in environment does not * change Jam notion of the current platform. */ var_defines( othersyms, 1 ); /* Load up variables set on command line. */ for( n = 0; s = getoptval( optv, 's', n ); n++ ) { char *symv[2]; symv[0] = s; symv[1] = 0; var_defines( symv, 1 ); } /* Set the ARGV to reflect the complete list of arguments of invocation. */ for ( n = 0; n < arg_c; ++n ) { var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND ); } /* Initialize built-in rules */ load_builtins(); /* Add the targets in the command line to update list */ for ( n = 1; n < arg_c; ++n ) { if ( arg_v[n][0] == '-' ) { char *f = "-:l:d:j:f:gs:t:ano:qv"; for( ; *f; f++ ) if( *f == arg_v[n][1] ) break; if ( f[1] == ':' && arg_v[n][2] == '\0' ) { ++n; } } else { mark_target_for_updating(arg_v[n]); } } /* Parse ruleset */ { FRAME frame[1]; frame_init( frame ); for( n = 0; s = getoptval( optv, 'f', n ); n++ ) parse_file( s, frame ); if( !n ) parse_file( "+", frame ); } status = yyanyerrors(); /* Manually touch -t targets */ for( n = 0; s = getoptval( optv, 't', n ); n++ ) touchtarget( s ); /* If an output file is specified, set globs.cmdout to that */ if( s = getoptval( optv, 'o', 0 ) ) { if( !( globs.cmdout = fopen( s, "w" ) ) ) { printf( "Failed to write to '%s'\n", s ); exit( EXITBAD ); } globs.noexec++; } /* Now make target */ { PROFILE_ENTER(MAIN_MAKE); LIST* targets = targets_to_update(); if ( !targets ) { status |= make( 1, &all, anyhow ); } else { int targets_count = list_length(targets); const char **targets2 = (const char **)malloc(targets_count * sizeof(char *)); int n = 0; if ( DEBUG_PROFILE ) profile_memory( targets_count * sizeof(char *) ); for ( ; targets; targets = list_next(targets) ) { targets2[n++] = targets->string; } status |= make( targets_count, targets2, anyhow ); free(targets); } PROFILE_EXIT(MAIN_MAKE); } PROFILE_EXIT(MAIN); } if ( DEBUG_PROFILE ) profile_dump(); /* Widely scattered cleanup */ var_done(); file_done(); donerules(); donestamps(); donestr(); /* close cmdout */ if( globs.cmdout ) fclose( globs.cmdout ); #ifdef HAVE_PYTHON Py_Finalize(); #endif return status ? EXITBAD : EXITOK; }