/* * /+\ * +\ 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. */ /* * 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 * 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 * 01/21/02 (seiwald) - new -q to quit quickly on build failure * 03/16/02 (seiwald) - support for -g (reorder builds by source time) * 09/19/02 (seiwald) - new -d displays * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr() * 11/04/02 (seiwald) - const-ing for string literals */ # 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" /* Macintosh is "special" */ # ifdef OS_MAC # include <QuickDraw.h> # endif /* And UNIX for this */ # ifdef unix # include <sys/utsname.h> # endif #ifdef OPT_DEBUG_MEM_TOTALS_EXT static int malloc_bytes = 0; static int realloc_bytes = 0; #endif /* OPT_DEBUG_MEM_TOTALS_EXT */ struct globs globs = { #ifdef OPT_DEBUG_MAKE_PRINT_TARGET_NAME 1, /* printtarget */ #endif #ifdef OPT_IMPROVED_PROGRESS_EXT 0, /* updating */ 0, /* start */ #endif 0, /* noexec */ 1, /* jobs */ 0, /* quitquick */ 0, /* newestfirst */ # ifdef OS_MAC { 0 }, /* display - suppress actions output */ # else { 0, 1 }, /* display actions */ # endif 0 /* output commands, not run them */ } ; /* Symbols to be defined as true for use in Jambase */ static const char *othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, DPG_JAMVERSION, 0 } ; /* Known for sure: * mac needs arg_enviro * OS2 needs extern environ */ # ifdef OS_MAC # define use_environ arg_environ # ifdef MPW QDGlobals qd; # endif # endif # ifndef use_environ # define use_environ environ # if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT ) extern char **environ; # endif # endif main( int argc, char **argv, char **arg_environ ) { int n; const char *s; struct option optv[N_OPTS]; const char *all = "all"; int anyhow = 0; int status; #ifdef OPT_PRINT_TOTAL_TIME_EXT time_t start; time(&start); #endif # ifdef OS_MAC InitGraf(&qd.thePort); # endif argc--, argv++; if( ( n = getoptions( argc, argv, "d:j:f:gs:t:ano:qv", optv ) ) < 0 ) { printf( "\nusage: jam [ options ] targets...\n\n" ); printf( "-a Build all targets, even if they are current.\n" ); printf( "-dx Display (a)actions (c)causes (d)dependencies\n" ); printf( " (m)make tree (x)commands (0-9) debug levels.\n" ); #ifdef OPT_GRAPH_DEBUG_EXT printf( " (g)graph (f)fate changes.\n"); #endif /* OPT_GRAPH_DEBUG_EXT */ 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( "-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" ); #ifdef OPT_DEBUG_MAKE_PRINT_TARGET_NAME printf( "-T Toggle printing of target's name.\n"); #endif /* OPT_DEBUG_MAKE_PRINT_TARGET_NAME */ printf( "-v Print the version of jam and exit.\n\n" ); #ifdef OPT_IMPROVE_DEBUG_LEVEL_HELP_EXT printf( "\n" ); printf( "The debug levels are:\n" ); printf( " 1 - show make actions when executed\n" ); printf( " 2 - show text of actions\n" ); printf( " 3 - show progress of make. Show files when bound\n" ); printf( " 4 - show execcmds()'s work\n" ); printf( " 5 - show rule invocations\n" ); printf( " 6 - show header scan, dir scan, attempts at binding\n" ); printf( " 7 - show variable setting\n" ); printf( " 8 - show variable fetches and expansions. " "show 'if' calculations\n" ); printf( " 9 - show scanner tokens. Show memory use\n" ); printf( "\n" ); printf( " To select individual debug levels, try: -d+n -d+n...\n" ); #endif exit( EXITBAD ); } argc -= n, argv += n; /* Version info. */ if( ( s = getoptval( optv, 'v', 0 ) ) ) { printf( "Jam %s. %s. ", VERSION, OSMINOR ); printf( "Copyright 1993-2002 Christopher Seiwald.\n" ); #ifdef OPT_PATCHED_VERSION_VAR_EXT printf( "PATCHED_VERSION %s.%s\n", PATCHED_VERSION_MAJOR, PATCHED_VERSION_MINOR); #ifdef DEBUG_J printf( "This is a DEBUG version.\n"); #endif #endif return EXITOK; } /* Pick up interesting options */ #ifdef OPT_DEBUG_MAKE_PRINT_TARGET_NAME if( ( s = getoptval( optv, 't', 0 ) ) ) globs.printtarget = !globs.printtarget; #endif /* OPT_DEBUG_MAKE_PRINT_TARGET_NAME */ if( ( s = getoptval( optv, 'n', 0 ) ) ) globs.noexec++, DEBUG_MAKE = DEBUG_MAKEQ = DEBUG_EXEC = 1; if( ( s = getoptval( optv, 'q', 0 ) ) ) globs.quitquick = 1; if( ( s = getoptval( optv, 'a', 0 ) ) ) anyhow++; #ifdef OPT_IMPROVE_JOBS_SETTING_EXT { const char *jobs = getenv("JAM_JOBS"); if (jobs) globs.jobs = atoi( jobs ); } #endif /* OPT_IMPROVE_JOBS_SETTING_EXT */ if( ( s = getoptval( optv, 'j', 0 ) ) ) globs.jobs = atoi( s ); if( ( s = getoptval( optv, 'g', 0 ) ) ) globs.newestfirst = 1; /* Turn on/off debugging */ for( n = 0; s = getoptval( optv, 'd', n ); n++ ) { int i = atoi( s ); /* First -d, turn off defaults. */ if( !n ) DEBUG_MAKE = DEBUG_MAKEQ = DEBUG_EXEC = 0; /* n turns on levels 1-n */ /* +n turns on level n */ /* c turns on named display c */ if( i < 0 || i >= DEBUG_MAX ) { printf( "Invalid debug level '%s'.\n", s ); } else if( *s == '+' ) { globs.debug[i] = 1; } else if( i ) while( i ) { globs.debug[i--] = 1; } else while( *s ) switch( *s++ ) { case 'a': DEBUG_MAKE = DEBUG_MAKEQ = 1; break; case 'c': DEBUG_CAUSES = 1; break; case 'd': DEBUG_DEPENDS = 1; break; #ifdef OPT_GRAPH_DEBUG_EXT case 'f': DEBUG_FATE = 1; break; case 'g': DEBUG_GRAPH = 1; break; #endif /* OPT_GRAPH_DEBUG_EXT */ case 'm': DEBUG_MAKEPROG = 1; break; case 'x': DEBUG_EXEC = 1; break; #ifdef OPT_DEBUG_MEM_TOTALS_EXT case 'T': DEBUG_MEM_TOTALS = 1; break; #endif #ifdef OPT_DEBUG_MAKE1_LOG_EXT case 'M' : DEBUG_MAKE1 = 1; break; #endif case '0': break; default: printf( "Invalid debug flag '%c'.\n", s[-1] ); } } /* Set JAMDATE first */ { char buf[ 128 ]; time_t clock; time( &clock ); strcpy( buf, ctime( &clock ) ); /* Trim newline from date */ if( strlen( buf ) == 25 ) buf[ 24 ] = 0; var_set( "JAMDATE", list_new( L0, buf, 0 ), VAR_SET ); } /* And JAMUNAME */ # ifdef unix { struct utsname u; if( uname( &u ) >= 0 ) { LIST *l = L0; l = list_new( l, u.machine, 0 ); l = list_new( l, u.version, 0 ); l = list_new( l, u.release, 0 ); l = list_new( l, u.nodename, 0 ); l = list_new( l, u.sysname, 0 ); var_set( "JAMUNAME", l, VAR_SET ); } } # endif /* unix */ #ifdef OPT_VAR_CWD_EXT /* And CWD */ { char filebuf[4096]; if (getcwd(filebuf, sizeof(filebuf))) { var_set( "CWD", list_new( L0, filebuf, 0 ), VAR_SET ); } } #endif /* * Jam defined variables OS, OSPLAT */ var_defines( othersyms ); #ifdef OPT_PATCHED_VERSION_VAR_EXT #define QUOTE2(x) #x #define QUOTE(x) QUOTE2(x) { char *s; char options[sizeof(QUOTE(JAM_OPTIONS)) + 1]; strcpy(options, QUOTE(JAM_OPTIONS)); var_set("PATCHED_JAM_VERSION", list_new(list_new(L0, PATCHED_VERSION_MAJOR, 0), PATCHED_VERSION_MINOR, 0), VAR_SET); for (s = strtok(options, ":"); s; s = strtok(NULL, ":")) { var_set("PATCHED_JAM_VERSION", list_new(L0, s, 0), VAR_APPEND); } } #endif /* load up environment variables */ var_defines( (const char **)use_environ ); /* Load up variables set on command line. */ for( n = 0; s = getoptval( optv, 's', n ); n++ ) { const char *symv[2]; symv[0] = s; symv[1] = 0; var_defines( symv ); } /* Initialize built-in rules */ load_builtins(); /* Parse ruleset */ for( n = 0; s = getoptval( optv, 'f', n ); n++ ) parse_file( s ); if( !n ) parse_file( "+" ); 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 */ if( !argc ) status |= make( 1, &all, anyhow ); else status |= make( argc, (const char **)argv, anyhow ); /* Widely scattered cleanup */ var_done(); donerules(); donestamps(); donestr(); #ifdef OPT_DEBUG_MEM_TOTALS_EXT list_done(); parse_done(); if (DEBUG_MEM || DEBUG_MEM_TOTALS) { printf("%dK total malloc()\n", malloc_bytes / 1024); printf("%dK total realloc()\n", realloc_bytes / 1024); } #endif /* close cmdout */ if( globs.cmdout ) fclose( globs.cmdout ); #ifdef OPT_PRINT_TOTAL_TIME_EXT { time_t now; long elapsed; const char* elapsed_logfile_name; time( &now ); elapsed = (long)difftime(now, start); if (elapsed > 10) { long minutes = elapsed / 60; long seconds = elapsed % 60; printf("...finished in "); if (minutes > 0) printf("%ld min ", minutes); if (seconds > 0) printf("%ld sec ", seconds); printf("\n"); } elapsed_logfile_name = getenv("JAM_ELAPSED_LOGFILE"); if (elapsed_logfile_name) { FILE* file = fopen(elapsed_logfile_name, "a"); if (!file) { printf("could not open elapsed log file \"%s\"\n", elapsed_logfile_name); printf("check the JAM_ELAPSED_LOGFILE " "environment variable.\n"); } else { fprintf(file, "when %ld elapsed %ld\n", (long)now, elapsed); fclose(file); } } } #endif return status ? EXITBAD : EXITOK; } #if defined(PURE) && !defined(NT) int check_leaks(void) { if (purify_new_leaks()) { /* Dereference a NULL pointer in such a way that Purify can * bring up the debugger */ char* null_pointer = 0; *null_pointer = 'Z'; return 1; } return 0; } #endif #ifdef OPT_DEBUG_MEM_TOTALS_EXT void* track_malloc(size_t mem) { malloc_bytes += mem; #undef malloc return malloc(mem); #define malloc(x) do_not_call_malloc_after_this(x) } void* track_realloc(void *ptr, size_t size) { realloc_bytes += size; #undef realloc return realloc(ptr, size); #define realloc(a,b) do_not_call_realloc_after_this(a,b) } #endif
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#20 | 4338 | Matt Armstrong |
Now jam will read the default -j argument from the JAM_JOBS environment variable. |
||
#19 | 4337 | Matt Armstrong | New -dM build flag to get make1.c debug logging. | ||
#18 | 4080 | Matt Armstrong | j -v will print whether the .exe is a debug version or not | ||
#17 | 3969 | Matt Armstrong |
Integrate from //guest/matt_armstrong/jam/fix/2/...@3963 -- no real changes. |
||
#16 | 3950 | Matt Armstrong |
Integrate from //guest/matt_armstrong/jam/fix/1/... thru change 3948 and make no changes. |
||
#15 | 3665 | Matt Armstrong |
Fix debug statement logging. Under NT, don't compile debug versions by default. |
||
#14 | 3656 | Matt Armstrong |
Partial support for a -T flag that prints out more detailed memory usage statistics. |
||
#13 | 3628 | Matt Armstrong | Add an MD5 function to Jam. | ||
#12 | 3623 | Matt Armstrong | Left over crap from a previous install. | ||
#11 | 3622 | Matt Armstrong |
Append the features present in this Jam to the PATCHED_JAM_VERSION variable. |
||
#10 | 3516 | Matt Armstrong |
Steal OPT_INTERRUPT_FIX and re-steal OPT_GRAPH_DEBUG_EXT from Craig. |
||
#9 | 3447 | Matt Armstrong |
With OPT_PRINT_TOTAL_TIME_EXT, setting the JAM_ELAPSED_LOGFILE environment variable to a filename will cause build times to be written to that log file. |
||
#8 | 3327 | Matt Armstrong |
Patchlevel a.c. Remove OPT_IMPROVE_TEMP_FILE_DELETE_EXT since upstream has a fix. Implement OPT_FIX_NT_ARSCAN_LEAK to fix a memory leak in the NT arscan functions. Get Pure builds running on NT. |
||
#7 | 3318 | Matt Armstrong | Provide a check_leaks() function in PURE builds. | ||
#6 | 2817 | Matt Armstrong | Update with current known working version. | ||
#5 | 2507 | Matt Armstrong | update from the mainline | ||
#4 | 2089 | Matt Armstrong | More integrations from upstream. | ||
#3 | 2087 | Matt Armstrong | I think most of this is updates from stock jam. | ||
#2 | 1271 | Matt Armstrong |
This is "my" custom version of Jam. See the LOCAL_DIFFERENCES.txt file for a description of differences from the upstream jam. |
||
#1 | 1270 | Matt Armstrong | In prep for publishing all my patches to jam. | ||
//guest/perforce_software/jam/src/jam.c | |||||
#7 | 486 | Perforce staff |
Jam 2.3. See RELNOTES for a list of changes from 2.2.x. Just about every source file was touched when jam got ANSI-fied. |
||
#6 | 213 | Perforce staff | Peter Glasscock's MPW port. | ||
#5 | 212 | Perforce staff |
An interpretative integration of Peter Glasscock's -o file support. This is handled in the make1() routine, rather than in all the exec*.c files. -o x writes the actions to file x rather than actually running them. Implies -n (but not -d2). |
||
#4 | 76 | Laura Wingerd |
Integrate command-block-too-long fix, plus minor doc updates. Jam/MR release level is now 2.2.5. (change 72, change 73, change 74, change 75) |
||
#3 | 5 | Perforce maintenance | Jam/MR 2.2.4 (HDRPATTERN, JAMUNAME, JAMSHELL, plus misc tweaks) | ||
#2 | 3 | Perforce maintenance | Jam/MR 2.2.1 (fix for NT handle leak) | ||
#1 | 2 | laura | Add Jam/MR 2.2 source |