?? jam.c
字號:
/* * /+\ * +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. * \+/ * * This file is part of jam. * * License is hereby granted to use this software and distribute it * freely, as long as this copyright notice is retained and modifications * are clearly marked. * * ALL WARRANTIES ARE HEREBY DISCLAIMED. *//* This file is ALSO: * Copyright 2001-2004 David Abrahams. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) *//* * jam.c - make redux * * See Jam.html for usage information. * * These comments document the code. * * The top half of the code is structured such: * * jam * / | \ * +---+ | \ * / | \ * jamgram option \ * / | \ \ * / | \ \ * / | \ | * scan | compile make * | | / | \ / | \ * | | / | \ / | \ * | | / | \ / | \ * jambase parse | rules search make1 * | | | \ * | | | \ * | | | \ * builtins timestamp command execute * | * | * | * filesys * * * The support routines are called by all of the above, but themselves * are layered thus: * * variable|expand * / | | | * / | | | * / | | | * lists | | pathsys * \ | | * \ | | * \ | | * newstr | * \ | * \ | * \ | * hash * * Roughly, the modules are: * * builtins.c - jam's built-in rules * command.c - maintain lists of commands * compile.c - compile parsed jam statements * execunix.c - execute a shell script on UNIX * execvms.c - execute a shell script, ala VMS * expand.c - expand a buffer, given variable values * file*.c - scan directories and archives on * * hash.c - simple in-memory hashing routines * hdrmacro.c - handle header file parsing for filename macro definitions * headers.c - handle #includes in source files * jambase.c - compilable copy of Jambase * jamgram.y - jam grammar * lists.c - maintain lists of strings * make.c - bring a target up to date, once rules are in place * make1.c - execute command to bring targets up to date * newstr.c - string manipulation routines * option.c - command line option processing * parse.c - make and destroy parse trees as driven by the parser * path*.c - manipulate file names on * * hash.c - simple in-memory hashing routines * regexp.c - Henry Spencer's regexp * rules.c - access to RULEs, TARGETs, and ACTIONs * scan.c - the jam yacc scanner * search.c - find a target along $(SEARCH) or $(LOCATE) * timestamp.c - get the timestamp of a file or archive member * variable.c - handle jam multi-element variables * * 05/04/94 (seiwald) - async multiprocess (-j) support * 02/08/95 (seiwald) - -n implies -d2. * 02/22/95 (seiwald) - -v for version info. * 09/11/00 (seiwald) - PATCHLEVEL folded into VERSION. * 01/10/01 (seiwald) - pathsys.h split from filesys.h */# include "jam.h"# include "option.h"# include "patchlevel.h"/* These get various function declarations. */# include "lists.h"# include "parse.h"# include "variable.h"# include "compile.h"# include "builtins.h"# include "rules.h"# include "newstr.h"# include "scan.h"# include "timestamp.h"# include "make.h"# include "strings.h"# include "expand.h"# include "filesys.h"# include "output.h"/* Macintosh is "special" */# ifdef OS_MAC# include <QuickDraw.h># endif/* And UNIX for this */# ifdef unix# include <sys/utsname.h># include <signal.h># endifstruct globs globs = { 0, /* noexec */ 1, /* jobs */ 0, /* quitquick */ 0, /* newestfirst */ 0, /* pipes action stdout and stderr merged to action output */# ifdef OS_MAC { 0, 0 }, /* debug - suppress tracing output */# else { 0, 1 }, /* debug ... */# endif 0, /* output commands, not run them */ 0 /* action timeout */} ;/* Symbols to be defined as true for use in Jambase */static char *othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 } ;/* Known for sure: * mac needs arg_enviro * OS2 needs extern environ */# ifdef OS_MAC# define use_environ arg_environ# ifdef MPWQDGlobals qd;# endif# endif/* on Win32-LCC */# if defined( OS_NT ) && defined( __LCC__ )# define use_environ _environ# endif# if defined( __MWERKS__)# define use_environ _environextern char **_environ;#endif# ifndef use_environ# define use_environ environ# if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT ) extern char **environ;# endif# endif# if YYDEBUG != 0extern int yydebug;# endif#ifndef NDEBUGstatic void run_unit_tests(){# if defined( USE_EXECNT ) extern void execnt_unit_test(); execnt_unit_test();# endif string_unit_test(); var_expand_unit_test();}#endif#ifdef HAVE_PYTHON extern PyObject* bjam_call(PyObject *self, PyObject *args); extern PyObject* bjam_import_rule(PyObject* self, PyObject* args); extern PyObject* bjam_define_action(PyObject* self, PyObject* args); extern PyObject* bjam_variable(PyObject* self, PyObject* args); extern PyObject* bjam_backtrace(PyObject* self, PyObject *args);#endifint 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]; BJAM_MEM_INIT();# ifdef OS_MAC InitGraf(&qd.thePort);# endif argc--, argv++; if( getoptions( argc, argv, "-:l: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( "-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-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, '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( ( 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."}, {"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."}, {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 */ var_set( "JAMDATE", list_new( L0, outf_time(time(0)) ), 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 ); enter_module( bindmodule(".ENVIRON") ); var_defines( symv, 0 ); exit_module( bindmodule(".ENVIRON") ); } /* 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 **)BJAM_MALLOC(targets_count * sizeof(char *)); int n = 0; 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 BJAM_MEM_CLOSE(); return status ? EXITBAD : EXITOK;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -