3 * +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
6 * This file is part of jam.
8 * License is hereby granted to use this software and distribute it
9 * freely, as long as this copyright notice is retained and modifications
12 * ALL WARRANTIES ARE HEREBY DISCLAIMED.
18 * See Jam.html for usage information.
20 * These comments document the code.
22 * The top half of the code is structured such:
36 * jambase parse | rules search make1
40 * builtins timestamp command execute
47 * The support routines are called by all of the above, but themselves
64 * Roughly, the modules are:
66 * builtins.c - jam's built-in rules
67 * command.c - maintain lists of commands
68 * compile.c - compile parsed jam statements
69 * execunix.c - execute a shell script on UNIX
70 * execvms.c - execute a shell script, ala VMS
71 * expand.c - expand a buffer, given variable values
72 * file*.c - scan directories and archives on *
73 * hash.c - simple in-memory hashing routines
74 * headers.c - handle #includes in source files
75 * jambase.c - compilable copy of Jambase
76 * jamgram.y - jam grammar
77 * lists.c - maintain lists of strings
78 * make.c - bring a target up to date, once rules are in place
79 * make1.c - execute command to bring targets up to date
80 * newstr.c - string manipulation routines
81 * option.c - command line option processing
82 * parse.c - make and destroy parse trees as driven by the parser
83 * path*.c - manipulate file names on *
84 * hash.c - simple in-memory hashing routines
85 * regexp.c - Henry Spencer's regexp
86 * rules.c - access to RULEs, TARGETs, and ACTIONs
87 * scan.c - the jam yacc scanner
88 * search.c - find a target along $(SEARCH) or $(LOCATE)
89 * timestamp.c - get the timestamp of a file or archive member
90 * variable.c - handle jam multi-element variables
92 * 05/04/94 (seiwald) - async multiprocess (-j) support
93 * 02/08/95 (seiwald) - -n implies -d2.
94 * 02/22/95 (seiwald) - -v for version info.
95 * 09/11/00 (seiwald) - PATCHLEVEL folded into VERSION.
96 * 01/10/01 (seiwald) - pathsys.h split from filesys.h
97 * 01/21/02 (seiwald) - new -q to quit quickly on build failure
98 * 03/16/02 (seiwald) - support for -g (reorder builds by source time)
99 * 09/19/02 (seiwald) - new -d displays
100 * 10/22/02 (seiwald) - list_new() now does its own newstr()/copystr()
101 * 11/04/02 (seiwald) - const-ing for string literals
106 # include "patchlevel.h"
108 /* These get various function declarations. */
112 # include "variable.h"
113 # include "compile.h"
114 # include "builtins.h"
118 # include "timestamp.h"
121 /* Macintosh is "special" */
124 # include <QuickDraw.h>
127 /* And UNIX for this */
130 # include <sys/utsname.h>
134 struct globs globs
= {
140 { 0 }, /* display - suppress actions output */
142 { 0, 1 }, /* display actions */
144 0 /* output commands, not run them */
148 /* Symbols to be defined as true for use in Jambase */
149 static const char *othersyms
[] = { OSMAJOR
, OSMINOR
, OSPLAT
, JAMVERSYM
, 0 } ;
153 * mac needs arg_enviro
154 * OS2 needs extern environ
157 # define use_environ arg_environ
164 # define use_environ environ
165 # if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
166 extern char **environ
;
171 int main (int argc
, char **argv
, char **arg_environ
) {
174 struct option optv
[N_OPTS
];
175 char *targets
[N_TARGETS
];
176 const char *all
= "all";
181 InitGraf(&qd
.thePort
);
185 if ((num_targets
= getoptions(argc
, argv
, "d:j:f:gs:t:ano:qv", optv
, targets
)) < 0) {
186 printf("\nusage: jam [ options ] targets...\n\n"
187 "-a Build all targets, even if they are current.\n"
188 "-dx Display (a)actions (c)causes (d)dependencies\n"
189 " (m)make tree (x)commands (0-9) debug levels.\n"
190 "-fx Read x instead of Jambase.\n"
191 "-g Build from newest sources first.\n"
192 "-jx Run up to x shell commands concurrently.\n"
193 "-n Don't actually execute the updating actions.\n"
194 "-ox Write the updating actions to file x.\n"
195 "-q Quit quickly as soon as a target fails.\n"
196 "-sx=y Set variable x=y, overriding environment.\n"
197 "-tx Rebuild x, even if it is up-to-date.\n"
198 "-v Print the version of jam and exit.\n\n"
204 if ((s
= getoptval(optv
, 'v', 0))) {
205 printf( "K-Jam %s. %s. ", VERSION
, OSMINOR
);
206 printf( "(C) 1993-2003 Christopher Seiwald, see www.freetype.org/jam/\n" );
207 printf( "changed by Ketmar, ketmar@ua.fm\n" );
211 /* Pick up interesting options */
212 if ((s
= getoptval(optv
, 'n', 0))) globs
.noexec
++, DEBUG_MAKE
= DEBUG_MAKEQ
= DEBUG_EXEC
= 1;
213 if ((s
= getoptval(optv
, 'q', 0))) globs
.quitquick
= 1;
214 if ((s
= getoptval(optv
, 'a', 0))) anyhow
++;
215 if ((s
= getoptval(optv
, 'j', 0))) globs
.jobs
= atoi(s
);
216 if ((s
= getoptval(optv
, 'g', 0))) globs
.newestfirst
= 1;
218 /* Turn on/off debugging */
219 for (n
= 0; (s
= getoptval(optv
, 'd', n
)) != 0; n
++) {
221 /* First -d, turn off defaults. */
222 if (!n
) DEBUG_MAKE
= DEBUG_MAKEQ
= DEBUG_EXEC
= 0;
223 /* n turns on levels 1-n */
224 /* +n turns on level n */
225 /* c turns on named display c */
226 if (i
< 0 || i
>= DEBUG_MAX
) {
227 printf( "Invalid debug level '%s'.\n", s
);
228 } else if (*s
== '+') {
231 while (i
) globs
.debug
[i
--] = 1;
235 case 'a': DEBUG_MAKE
= DEBUG_MAKEQ
= 1; break;
236 case 'c': DEBUG_CAUSES
= 1; break;
237 case 'd': DEBUG_DEPENDS
= 1; break;
238 case 'm': DEBUG_MAKEPROG
= 1; break;
239 case 'x': DEBUG_EXEC
= 1; break;
241 default: printf("Invalid debug flag '%c'.\n", s
[-1]);
247 /* Set JAMDATE first */
253 strcpy(buf
, ctime(&clock
));
254 /* Trim newline from date */
255 /*if (strlen(buf) == 25) buf[24] = 0;*/
257 while (p
>= buf
&& *((unsigned char *)p
) <= ' ') p
--;
259 var_set("JAMDATE", list_new(L0
, buf
, 0), VAR_SET
);
267 if (uname( &u
) >= 0) {
269 l
= list_new(l
, u
.machine
, 0);
270 l
= list_new(l
, u
.version
, 0);
271 l
= list_new(l
, u
.release
, 0);
272 l
= list_new(l
, u
.nodename
, 0);
273 l
= list_new(l
, u
.sysname
, 0);
274 var_set("JAMUNAME", l
, VAR_SET
);
280 * Jam defined variables OS, OSPLAT
282 var_defines(othersyms
);
283 /* load up environment variables */
284 var_defines((const char **)use_environ
);
285 /* Load up variables set on command line. */
286 for (n
= 0; (s
= getoptval( optv
, 's', n
)) != 0; n
++) {
293 /* Initialize built-in rules */
297 for (n
= 0; (s
= getoptval(optv
, 'f', n
)) != 0; n
++) parse_file(s
);
298 if (!n
) parse_file("+");
300 status
= yyanyerrors();
302 /* Manually touch -t targets */
303 for (n
= 0; (s
= getoptval(optv
, 't', n
)) != 0; n
++) touchtarget(s
);
305 /* If an output file is specified, set globs.cmdout to that */
306 if ((s
= getoptval(optv
, 'o', 0)) != 0) {
307 if (!(globs
.cmdout
= fopen(s
, "w"))) {
308 printf( "Failed to write to '%s'\n", s
);
318 for (n
= 0; n
< num_targets
; n
++) l
= list_new(l
, targets
[n
], 0);
319 var_set("JAMCMDARGS", l
, VAR_SET
);
322 /* Now make target */
323 if (!num_targets
) status
|= make(1, &all
, anyhow
);
324 else status
|= make(num_targets
, (const char **)targets
, anyhow
);
326 /* Widely scattered cleanup */
333 if (globs
.cmdout
) fclose(globs
.cmdout
);
335 return status
? EXITBAD
: EXITOK
;