The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

jam.c

Go to the documentation of this file.
00001 /*
00002  * /+\
00003  * +\   Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
00004  * \+/
00005  *
00006  * This file is part of jam.
00007  *
00008  * License is hereby granted to use this software and distribute it
00009  * freely, as long as this copyright notice is retained and modifications 
00010  * are clearly marked.
00011  *
00012  * ALL WARRANTIES ARE HEREBY DISCLAIMED.
00013  */
00014 
00015 /*  This file is ALSO:
00016  *  (C) Copyright David Abrahams 2001. Permission to copy, use,
00017  *  modify, sell and distribute this software is granted provided this
00018  *  copyright notice appears in all copies. This software is provided
00019  *  "as is" without express or implied warranty, and with no claim as
00020  *  to its suitability for any purpose.
00021  */
00022 
00023 /*
00024  * jam.c - make redux
00025  *
00026  * See Jam.html for usage information.
00027  *
00028  * These comments document the code.
00029  *
00030  * The top half of the code is structured such:
00031  *
00032  *                       jam 
00033  *                      / | \ 
00034  *                 +---+  |  \
00035  *                /       |   \ 
00036  *         jamgram     option  \ 
00037  *        /  |   \              \
00038  *       /   |    \              \
00039  *      /    |     \             |
00040  *  scan     |     compile      make
00041  *   |       |    /  | \       / |  \
00042  *   |       |   /   |  \     /  |   \
00043  *   |       |  /    |   \   /   |    \
00044  * jambase parse     |   rules  search make1
00045  *                   |           |      |   \
00046  *                   |           |      |    \
00047  *                   |           |      |     \
00048  *               builtins    timestamp command execute
00049  *                               |
00050  *                               |
00051  *                               |
00052  *                             filesys
00053  *
00054  *
00055  * The support routines are called by all of the above, but themselves
00056  * are layered thus:
00057  *
00058  *                     variable|expand
00059  *                      /  |   |   |
00060  *                     /   |   |   |
00061  *                    /    |   |   |
00062  *                 lists   |   |   pathsys
00063  *                    \    |   |
00064  *                     \   |   |
00065  *                      \  |   |
00066  *                     newstr  |
00067  *                        \    |
00068  *                         \   |
00069  *                          \  |
00070  *                          hash
00071  *
00072  * Roughly, the modules are:
00073  *
00074  *      builtins.c - jam's built-in rules
00075  *      command.c - maintain lists of commands
00076  *      compile.c - compile parsed jam statements
00077  *      execunix.c - execute a shell script on UNIX
00078  *      execvms.c - execute a shell script, ala VMS
00079  *      expand.c - expand a buffer, given variable values
00080  *      file*.c - scan directories and archives on *
00081  *      hash.c - simple in-memory hashing routines 
00082  *  hdrmacro.c - handle header file parsing for filename macro definitions
00083  *      headers.c - handle #includes in source files
00084  *      jambase.c - compilable copy of Jambase
00085  *      jamgram.y - jam grammar
00086  *      lists.c - maintain lists of strings
00087  *      make.c - bring a target up to date, once rules are in place
00088  *      make1.c - execute command to bring targets up to date
00089  *      newstr.c - string manipulation routines
00090  *      option.c - command line option processing
00091  *      parse.c - make and destroy parse trees as driven by the parser
00092  *      path*.c - manipulate file names on *
00093  *      hash.c - simple in-memory hashing routines 
00094  *      regexp.c - Henry Spencer's regexp
00095  *      rules.c - access to RULEs, TARGETs, and ACTIONs
00096  *      scan.c - the jam yacc scanner
00097  *      search.c - find a target along $(SEARCH) or $(LOCATE) 
00098  *      timestamp.c - get the timestamp of a file or archive member
00099  *      variable.c - handle jam multi-element variables
00100  *
00101  * 05/04/94 (seiwald) - async multiprocess (-j) support
00102  * 02/08/95 (seiwald) - -n implies -d2.
00103  * 02/22/95 (seiwald) - -v for version info.
00104  * 09/11/00 (seiwald) - PATCHLEVEL folded into VERSION.
00105  * 01/10/01 (seiwald) - pathsys.h split from filesys.h
00106  */
00107 
00108 # include "jam.h"
00109 # include "option.h"
00110 # include "patchlevel.h"
00111 
00112 /* These get various function declarations. */
00113 
00114 # include "lists.h"
00115 # include "parse.h"
00116 # include "variable.h"
00117 # include "compile.h"
00118 # include "builtins.h"
00119 # include "rules.h"
00120 # include "newstr.h"
00121 # include "scan.h"
00122 # include "timestamp.h"
00123 # include "make.h"
00124 # include "strings.h"
00125 # include "expand.h"
00126 
00127 /* Macintosh is "special" */
00128 
00129 # ifdef OS_MAC
00130 # include <QuickDraw.h>
00131 # endif
00132 
00133 /* And UNIX for this */
00134 
00135 # ifdef unix
00136 # include <sys/utsname.h>
00137 # endif
00138 
00139 struct globs globs = {
00140         0,                      /* noexec */
00141         1,                      /* jobs */
00142         0,                      /* quitquick */
00143         0,                      /* newestfirst */
00144 # ifdef OS_MAC
00145         { 0, 0 },               /* debug - suppress tracing output */
00146 # else
00147         { 0, 1 },               /* debug ... */
00148 # endif
00149         0                       /* output commands, not run them */
00150 } ;
00151 
00152 /* Symbols to be defined as true for use in Jambase */
00153 
00154 static char *othersyms[] = { OSMAJOR, OSMINOR, OSPLAT, JAMVERSYM, 0 } ;
00155 
00156 /* Known for sure: 
00157  *      mac needs arg_enviro
00158  *      OS2 needs extern environ
00159  */
00160 
00161 # ifdef OS_MAC
00162 # define use_environ arg_environ
00163 # ifdef MPW
00164 QDGlobals qd;
00165 # endif
00166 # endif
00167 
00168 /* on Win32-LCC */
00169 # if defined( OS_NT ) && defined( __LCC__ )
00170 #   define  use_environ _environ
00171 # endif
00172 
00173 # if defined( __MWERKS__)
00174 # define use_environ _environ
00175 extern char **_environ;
00176 #endif
00177 
00178 # ifndef use_environ
00179 # define use_environ environ
00180 # if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT ) 
00181 extern char **environ;
00182 # endif
00183 # endif
00184 
00185 # if YYDEBUG != 0
00186 extern int yydebug;
00187 # endif
00188 
00189 #ifndef NDEBUG
00190 static void run_unit_tests()
00191 {
00192 # if defined( USE_EXECNT )
00193     extern void execnt_unit_test();
00194     execnt_unit_test();
00195 # endif 
00196     string_unit_test();
00197     var_expand_unit_test();
00198 }
00199 #endif
00200 
00201 int  main( int argc, char **argv, char **arg_environ )
00202 {
00203     int         n;
00204     char                *s;
00205     struct option       optv[N_OPTS];
00206     const char  *all = "all";
00207     int         anyhow = 0;
00208     int         status;
00209     int arg_c = argc;
00210     char ** arg_v = argv;
00211 
00212 # ifdef OS_MAC
00213     InitGraf(&qd.thePort);
00214 # endif
00215 
00216     argc--, argv++;
00217 
00218         if( ( n = getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) ) < 0 )
00219     {
00220         printf( "\nusage: jam [ options ] targets...\n\n" );
00221 
00222         printf( "-a      Build all targets, even if they are current.\n" );
00223         printf( "-dx     Set the debug level to x (0-9).\n" );
00224         printf( "-fx     Read x instead of Jambase.\n" );
00225             /* printf( "-g      Build from newest sources first.\n" ); */
00226         printf( "-jx     Run up to x shell commands concurrently.\n" );
00227         printf( "-n      Don't actually execute the updating actions.\n" );
00228         printf( "-ox     Write the updating actions to file x.\n" );
00229                 printf( "-q      Quit quickly as soon as a target fails.\n" );
00230         printf( "-sx=y   Set variable x=y, overriding environment.\n" );
00231         printf( "-tx     Rebuild x, even if it is up-to-date.\n" );
00232         printf( "-v      Print the version of jam and exit.\n" );
00233         printf( "--x     Option is ignored.\n\n" );
00234 
00235         exit( EXITBAD );
00236     }
00237 
00238     argc -= n, argv += n;
00239 
00240     /* Version info. */
00241 
00242     if( ( s = getoptval( optv, 'v', 0 ) ) )
00243     {
00244         printf( "Boost.Jam  " );
00245         printf( "Version %s. %s.\n", VERSION, OSMINOR );
00246            printf( "   Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.  \n" );
00247         printf( "   Copyright 2001 David Turner.\n" );
00248         printf( "   Copyright 2001-2002 David Abrahams.\n" );
00249 
00250         return EXITOK;
00251     }
00252 
00253     /* Pick up interesting options */
00254 
00255     if( ( s = getoptval( optv, 'n', 0 ) ) )
00256         globs.noexec++, globs.debug[2] = 1;
00257 
00258         if( ( s = getoptval( optv, 'q', 0 ) ) )
00259             globs.quitquick = 1;
00260     if( ( s = getoptval( optv, 'a', 0 ) ) )
00261         anyhow++;
00262 
00263     if( ( s = getoptval( optv, 'j', 0 ) ) )
00264         globs.jobs = atoi( s );
00265 
00266         if( ( s = getoptval( optv, 'g', 0 ) ) )
00267             globs.newestfirst = 1;
00268 
00269     /* Turn on/off debugging */
00270 
00271     for( n = 0; s = getoptval( optv, 'd', n ); n++ )
00272     {
00273         int i;
00274 
00275         /* First -d, turn off defaults. */
00276 
00277         if( !n )
00278             for( i = 0; i < DEBUG_MAX; i++ )
00279                 globs.debug[i] = 0;
00280 
00281         i = atoi( s );
00282 
00283         if( i < 0 || i >= DEBUG_MAX )
00284         {
00285             printf( "Invalid debug level '%s'.\n", s );
00286             continue;
00287         }
00288 
00289         /* n turns on levels 1-n */
00290         /* +n turns on level n */
00291 
00292         if( *s == '+' )
00293             globs.debug[i] = 1;
00294         else while( i )
00295             globs.debug[i--] = 1;
00296     }
00297 
00298 #ifndef NDEBUG
00299     run_unit_tests();
00300 #endif
00301 #if YYDEBUG != 0
00302     if ( DEBUG_PARSE )
00303         yydebug = 1;
00304 #endif
00305 
00306     /* Set JAMDATE first */
00307 
00308     {
00309         char *date;
00310         time_t clock;
00311         time( &clock );
00312         date = newstr( ctime( &clock ) );
00313 
00314         /* Trim newline from date */
00315 
00316         if( strlen( date ) == 25 )
00317             date[ 24 ] = 0;
00318 
00319         var_set( "JAMDATE", list_new( L0, newstr( date ) ), VAR_SET );
00320     }
00321 
00322     var_set( "JAM_VERSION",
00323              list_new( list_new( list_new( L0, newstr( "03" ) ), newstr( "01" ) ), 
00324                        newstr( "08" ) ),
00325              VAR_SET );
00326 
00327     /* And JAMUNAME */
00328 # ifdef unix
00329     {
00330         struct utsname u;
00331 
00332         if( uname( &u ) >= 0 )
00333         {
00334             var_set( "JAMUNAME", 
00335                      list_new( 
00336                          list_new(
00337                              list_new(
00338                                  list_new(
00339                                      list_new( L0, 
00340                                                newstr( u.sysname ) ),
00341                                      newstr( u.nodename ) ),
00342                                  newstr( u.release ) ),
00343                              newstr( u.version ) ),
00344                          newstr( u.machine ) ), VAR_SET );
00345         }
00346     }
00347 # endif /* unix */
00348 
00349         /*
00350          * Jam defined variables OS, OSPLAT
00351          */
00352 
00353     var_defines( othersyms );
00354 
00355     /* load up environment variables */
00356 
00357     var_defines( use_environ );
00358 
00359     /* Load up variables set on command line. */
00360 
00361     for( n = 0; s = getoptval( optv, 's', n ); n++ )
00362     {
00363         char *symv[2];
00364         symv[0] = s;
00365         symv[1] = 0;
00366         var_defines( symv );
00367     }
00368 
00369     /* Set the ARGV to reflect the complete list of arguments of invocation. */
00370 
00371     for ( n = 0; n < arg_c; ++n )
00372     {
00373         var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
00374     }
00375 
00376         /* Initialize built-in rules */
00377 
00378         load_builtins();
00379 
00380     /* Add the targets in the command line to update list */
00381 
00382     for ( n = 0; n < argc; ++n )
00383     {
00384         mark_target_for_updating(argv[n]);
00385     }
00386 
00387     /* Parse ruleset */
00388 
00389     {
00390         FRAME frame[1];
00391         frame_init( frame );
00392         for( n = 0; s = getoptval( optv, 'f', n ); n++ )
00393             parse_file( s, frame );
00394 
00395         if( !n )
00396             parse_file( "+", frame );
00397     }
00398 
00399     status = yyanyerrors();
00400 
00401     /* Manually touch -t targets */
00402 
00403     for( n = 0; s = getoptval( optv, 't', n ); n++ )
00404         touchtarget( s );
00405 
00406     /* If an output file is specified, set globs.cmdout to that */
00407 
00408     if( s = getoptval( optv, 'o', 0 ) )
00409     {
00410         if( !( globs.cmdout = fopen( s, "w" ) ) )
00411         {
00412             printf( "Failed to write to '%s'\n", s );
00413             exit( EXITBAD );
00414         }
00415         globs.noexec++;
00416     }
00417 
00418     /* Now make target */
00419 
00420     {
00421         LIST* targets = targets_to_update();
00422         if ( !targets )
00423         {
00424             status |= make( 1, &all, anyhow );
00425         }
00426         else 
00427         {
00428             int targets_count = list_length(targets);
00429             const char **targets2 = (const char **)malloc(targets_count * sizeof(char *));
00430             int n = 0;
00431             for ( ; targets; targets = list_next(targets) )
00432             {
00433                 targets2[n++] = targets->string;
00434             }
00435             status |= make( targets_count, targets2, anyhow );       
00436             free(targets);
00437         }
00438     }
00439 
00440 
00441     if ( DEBUG_PROFILE )
00442         profile_dump();
00443 
00444     /* Widely scattered cleanup */
00445 
00446     var_done();
00447     donerules();
00448     donestamps();
00449     donestr();
00450 
00451     /* close cmdout */
00452 
00453     if( globs.cmdout )
00454         fclose( globs.cmdout );
00455 
00456     return status ? EXITBAD : EXITOK;
00457 }

Generated on Mon Nov 8 17:07:36 2004 for MPT by  doxygen 1.3.9.1