mirror of
https://github.com/boostorg/build.git
synced 2026-02-15 00:52:16 +00:00
merged to main trunk
[SVN r11610]
This commit is contained in:
30
historic/jam/src/Build.com
Executable file
30
historic/jam/src/Build.com
Executable file
@@ -0,0 +1,30 @@
|
||||
! Bootstrap build script for Jam
|
||||
$ cc command.c
|
||||
$ cc compile.c
|
||||
$ cc expand.c
|
||||
$ cc execvms.c
|
||||
$ cc filevms.c
|
||||
$ cc glob.c
|
||||
$ cc hash.c
|
||||
$ cc headers.c
|
||||
$ cc jambase.c
|
||||
$ cc lists.c
|
||||
$ cc make.c
|
||||
$ cc make1.c
|
||||
$ cc newstr.c
|
||||
$ cc option.c
|
||||
$ cc parse.c
|
||||
$ cc pathvms.c
|
||||
$ cc regexp.c
|
||||
$ cc rules.c
|
||||
$ cc scan.c
|
||||
$ cc search.c
|
||||
$ cc timestamp.c
|
||||
$ cc variable.c
|
||||
$ cc jam.c
|
||||
$ cc jamgram.c
|
||||
$ link/exe=jam.exe command.obj, compile.obj, execvms.obj, expand.obj, -
|
||||
filevms.obj, glob.obj, hash.obj, headers.obj, lists.obj, make.obj, -
|
||||
make1.obj, newstr.obj, option.obj, parse.obj, pathvms.obj, regexp.obj, -
|
||||
rules.obj, scan.obj, search.obj, timestamp.obj, variable.obj, jam.obj, -
|
||||
jamgram.obj, jambase.obj
|
||||
47
historic/jam/src/Build.mpw
Normal file
47
historic/jam/src/Build.mpw
Normal file
@@ -0,0 +1,47 @@
|
||||
# This line must be set manually to the CodeWarrior Pro 5 installation.
|
||||
# Good luck!
|
||||
|
||||
set CW "malyn_apps:CodeWarrior Pro 5:MetroWerks CodeWarrior"
|
||||
|
||||
set -e MWCincludes "{CW}:MacOS Support:Universal:Interfaces:CIncludes,{CW}:MacOS Support:OpenTransport:Open Tpt Client Developer:Includes:CIncludes,{CW}:MacOS Support:Headers:Apple MPW,{CW}:MSL:MSL_C:MSL_Common:Include,{CW}:MSL:MSL_C++:MSL_Common:Include,{CW}:MSL:MSL_C:MSL_MacOS:Include"
|
||||
|
||||
mwcppc -o :bin.mac:command.o -nomapcr -w off command.c
|
||||
mwcppc -o :bin.mac:compile.o -nomapcr -w off compile.c
|
||||
mwcppc -o :bin.mac:execmac.o -nomapcr -w off execmac.c
|
||||
mwcppc -o :bin.mac:filemac.o -nomapcr -w off filemac.c
|
||||
mwcppc -o :bin.mac:pathmac.o -nomapcr -w off pathmac.c
|
||||
mwcppc -o :bin.mac:jamgram.o -nomapcr -w off jamgram.c
|
||||
mwcppc -o :bin.mac:expand.o -nomapcr -w off expand.c
|
||||
mwcppc -o :bin.mac:glob.o -nomapcr -w off glob.c
|
||||
mwcppc -o :bin.mac:hash.o -nomapcr -w off hash.c
|
||||
mwcppc -o :bin.mac:headers.o -nomapcr -w off headers.c
|
||||
mwcppc -o :bin.mac:lists.o -nomapcr -w off lists.c
|
||||
mwcppc -o :bin.mac:make.o -nomapcr -w off make.c
|
||||
mwcppc -o :bin.mac:make1.o -nomapcr -w off make1.c
|
||||
mwcppc -o :bin.mac:newstr.o -nomapcr -w off newstr.c
|
||||
mwcppc -o :bin.mac:option.o -nomapcr -w off option.c
|
||||
mwcppc -o :bin.mac:parse.o -nomapcr -w off parse.c
|
||||
mwcppc -o :bin.mac:regexp.o -nomapcr -w off regexp.c
|
||||
mwcppc -o :bin.mac:rules.o -nomapcr -w off rules.c
|
||||
mwcppc -o :bin.mac:scan.o -nomapcr -w off scan.c
|
||||
mwcppc -o :bin.mac:search.o -nomapcr -w off search.c
|
||||
mwcppc -o :bin.mac:timestamp.o -nomapcr -w off timestamp.c
|
||||
mwcppc -o :bin.mac:variable.o -nomapcr -w off variable.c
|
||||
|
||||
mwlinkppc -library -o :bin.mac:libjam.lib :bin.mac:command.o :bin.mac:compile.o :bin.mac:execmac.o :bin.mac:filemac.o :bin.mac:pathmac.o :bin.mac:jamgram.o :bin.mac:expand.o :bin.mac:glob.o :bin.mac:hash.o :bin.mac:headers.o :bin.mac:lists.o :bin.mac:make.o :bin.mac:make1.o :bin.mac:newstr.o :bin.mac:option.o :bin.mac:parse.o :bin.mac:regexp.o :bin.mac:rules.o :bin.mac:scan.o :bin.mac:search.o :bin.mac:timestamp.o :bin.mac:variable.o
|
||||
mwcppc -o :bin.mac:mkjambase.o -nomapcr -w off mkjambase.c
|
||||
|
||||
mwlinkppc -o :bin.mac:mkjambase -mpwtool -warn :bin.mac:mkjambase.o "{CW}:MacOS Support:Universal:Libraries:StubLibraries:Interfacelib" "{CW}:MacOS Support:Universal:Libraries:StubLibraries:ThreadsLib" "{CW}:MacOS Support:Universal:Libraries:StubLibraries:Mathlib" "{CW}:MacOS Support:Libraries:Apple MPW PPC:PPCToolLibs.o" "{CW}:MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib" "{CW}:MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib"
|
||||
mwcppc -o :bin.mac:jam.o -nomapcr -w off jam.c
|
||||
|
||||
:bin.mac:mkjambase jambase.c Jambase
|
||||
|
||||
mwcppc -o :bin.mac:jambase.o -nomapcr -w off jambase.c
|
||||
|
||||
mwlinkppc -o :bin.mac:jam -mpwtool -warn :bin.mac:jam.o :bin.mac:jambase.o :bin.mac:libjam.lib "{CW}:MacOS Support:Universal:Libraries:StubLibraries:Interfacelib" "{CW}:MacOS Support:Universal:Libraries:StubLibraries:ThreadsLib" "{CW}:MacOS Support:Universal:Libraries:StubLibraries:Mathlib" "{CW}:MacOS Support:Libraries:Apple MPW PPC:PPCToolLibs.o" "{CW}:MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib" "{CW}:MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
120
historic/jam/src/INSTALL
Normal file
120
historic/jam/src/INSTALL
Normal file
@@ -0,0 +1,120 @@
|
||||
I. Compiling FT Jam:
|
||||
--------------------
|
||||
|
||||
1. With a previous version of Jam:
|
||||
----------------------------------
|
||||
|
||||
The easiest way to compile Jam is to use a previous version of the
|
||||
program. If you already have one installed on your system, simply
|
||||
type "jam" in this directory.
|
||||
|
||||
This will create a new executable named "jam" or "jam.exe", located
|
||||
in a new system-dependent directory, whose name can be:
|
||||
|
||||
bin.ntx86\jam.exe
|
||||
bin.linux86\jam
|
||||
etc..
|
||||
|
||||
|
||||
2. Without jam:
|
||||
---------------
|
||||
|
||||
If you don't have a jam binary installed, you can still compile the
|
||||
program using one of these methods:
|
||||
|
||||
- on Unix systems, simply type "make" to use the "Makefile" provided
|
||||
in this directory. This should work flawlessly
|
||||
|
||||
- on other systems, you can also modify the content of "Makefile"
|
||||
to adapt it to your OS. Simply uncomment the lines specific to
|
||||
your system, and invoke your make tool
|
||||
|
||||
|
||||
Note that the Makefile is used to build a boot-strap version of jam,
|
||||
called "jam0". Once it is built, the "jam0" executable is called to
|
||||
re-build itself.
|
||||
|
||||
If this second pass doesn't work, this is probably because you didn't
|
||||
set some environment variable that indicates which compiler to use to
|
||||
Jam. Read the Jam documentation for more information on this..
|
||||
|
||||
|
||||
|
||||
3. With toolset-specific makefiles:
|
||||
-----------------------------------
|
||||
|
||||
You can also use one of the Makefiles located in the "builds"
|
||||
directory. Here's what you need to type on the command line,
|
||||
depending on your system and compiler:
|
||||
|
||||
|
||||
a. Windows + Visual C++:
|
||||
|
||||
set VISUALC=/install/path/to/visual/compiler
|
||||
set JAM_TOOLSET=VISUALC
|
||||
nmake -f builds\win32-visualc.mk
|
||||
|
||||
|
||||
b. Windows + Borland C++: (be sure to use the Borland "make" tool)
|
||||
|
||||
set BORLANDC=/install/path/to/borland/compiler
|
||||
set JAM_TOOLSET=BORLANDC
|
||||
make -fbuilds\win32-visualc.mk
|
||||
|
||||
|
||||
c. Windows + Mingw (gcc):
|
||||
|
||||
set BORLANDC=/install/path/to/borland/compiler
|
||||
set JAM_TOOLSET=BORLANDC
|
||||
make -f builds\win32-visualc.mk
|
||||
|
||||
|
||||
WE DO NOT PROVIDE PROJECT FILES FOR ANY SPECIFIC COMPILER/TOOLSET
|
||||
|
||||
|
||||
|
||||
|
||||
II. Installation:
|
||||
-----------------
|
||||
|
||||
For now, we do not provide any sophisticated
|
||||
installation pass. Simply copy the new jam executable
|
||||
to any directory in your current path.. and start
|
||||
using it !!
|
||||
|
||||
|
||||
III. Default files:
|
||||
-------------------
|
||||
|
||||
All default files for Jam are compiled within the
|
||||
executable itself.
|
||||
|
||||
There are no special configuration directory to
|
||||
place global or user preferences. Until further
|
||||
notice, all defaults can only be changed by using
|
||||
command line switches and setting environment
|
||||
variables..
|
||||
|
||||
|
||||
IV. Windows and OS/2 Binary packages:
|
||||
-------------------------------------
|
||||
|
||||
It's possible to create zip files of the binaries
|
||||
on Windows and OS/2 system by following these simple
|
||||
steps (you need to have the "zip" utility in your
|
||||
path !!):
|
||||
|
||||
1. build jam
|
||||
2. strip the jam.exe executable in bin.ntx86 when
|
||||
possible
|
||||
3. call "jam package"
|
||||
|
||||
you should see a file named "ftjam-xxxxx-win32.zip"
|
||||
or "ftjam-xxxxx-os2.zip" in the current directory,
|
||||
as well as "ftjam-xxxxx.zip" (containing the sources)
|
||||
|
||||
|
||||
Good luck,
|
||||
|
||||
|
||||
- David Turner, 28 Jul 2001
|
||||
1201
historic/jam/src/Jam.html
Normal file
1201
historic/jam/src/Jam.html
Normal file
File diff suppressed because it is too large
Load Diff
2288
historic/jam/src/Jambase
Normal file
2288
historic/jam/src/Jambase
Normal file
File diff suppressed because it is too large
Load Diff
881
historic/jam/src/Jambase.html
Normal file
881
historic/jam/src/Jambase.html
Normal file
@@ -0,0 +1,881 @@
|
||||
<HTML>
|
||||
<TITLE>
|
||||
Jambase Reference
|
||||
</TITLE>
|
||||
<BODY>
|
||||
<CENTER>
|
||||
<a href=http://www.perforce.com/jam/jam.html>
|
||||
Jam/MR
|
||||
</a>
|
||||
<H1>
|
||||
<A NAME="TOP">
|
||||
Jambase Reference
|
||||
</A>
|
||||
</H1>
|
||||
</CENTER>
|
||||
<P>
|
||||
Jambase is a base set of Jam/MR rules which
|
||||
provide roughly make(1)-like functionality for
|
||||
<a href="Jam.html"><b>jam</b></A>, the Jam/MR executable program.
|
||||
This document, which started out as the Jambase(5) man page,
|
||||
is a reference guide to the
|
||||
<A href="#RULES">rules</A>,
|
||||
<A href="#PSEUDOTARGETS">pseudotargets</A>,
|
||||
and <A href="#VARS">variables</A>
|
||||
defined in Jambase for use in Jamfiles.
|
||||
<P>
|
||||
For further information see:
|
||||
<UL>
|
||||
<LI>
|
||||
<a href="Jamfile.html">Using Jamfiles and Jambase</A>
|
||||
<LI>
|
||||
<a href="Jam.html">The Jam/MR Executable Program</A>
|
||||
</UL>
|
||||
<P>
|
||||
Jam/MR documentation and source are available from the
|
||||
<A HREF=http://public.perforce.com/public/index.html>Perforce Public Depot</a>.
|
||||
For detailed information about any of the rules summarized below,
|
||||
see the
|
||||
<A HREF=http://public.perforce.com/public/jam/src/Jambase>Jambase</a>
|
||||
file itself.
|
||||
<HR>
|
||||
<H2>
|
||||
<A NAME="RULES">
|
||||
Jambase Rules
|
||||
</A>
|
||||
</H2>
|
||||
<P>
|
||||
<B>As</B> <I>obj.o</I> : <I>source.s</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Assemble the file <I>source.s.</I> Called by the Object
|
||||
rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>Bulk</B> <I>directory</I> : <I>sources</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Copies <I>sources</I> into <I>directory.</I>
|
||||
</BLOCKQUOTE>
|
||||
<B>Cc</B> <I>object</I> : <I>source</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compile the file <I>source</I> into <I>object,</I> using the C
|
||||
compiler $(CC), its flags $(CCFLAGS) and $(OPTIM),
|
||||
and the header file directories $(HDRS). Called by
|
||||
the Object rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>C++</B> <I>obj.o</I> : <I>source.cc</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compile the C++ source file <I>source.cc.</I> Called by
|
||||
the Object rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>Chmod</B> <I>target</I> ;
|
||||
<BLOCKQUOTE>
|
||||
<I>(Unix and VMS only.)</I>
|
||||
Change file permissions on <I>target</I> to
|
||||
target-specific $(MODE) value set by Link, File,
|
||||
Install*, and Shell rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<B>Clean</B> <I>clean</I> : <I>targets</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Removes existing <I>targets</I> when <I>clean</I> is built.
|
||||
clean is not a dependency of all, and must be built
|
||||
explicitly for targets to be removed.
|
||||
</BLOCKQUOTE>
|
||||
<B>File</B> <I>target</I> : <I>source</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Copies <I>source</I> into <I>target.</I>
|
||||
</BLOCKQUOTE>
|
||||
<B>Fortran</B> <I>obj.o</I> : <I>source.f</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compile the Fortran source file <I>source.f.</I> Called
|
||||
by the Object rule.
|
||||
</BLOCKQUOTE>
|
||||
<P>
|
||||
<B>GenFile</B> <I>target</I> : <I>image</I> <I>sources</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Runs the command "<I>image</I> <I>target</I> <I>sources</I>"
|
||||
to create <I>target</I> from <I>sources</I> and
|
||||
<I>image</I>. (where <I>image</I> is an
|
||||
executable built by the Main rule.)
|
||||
</BLOCKQUOTE>
|
||||
<B>HardLink</B> <I>target</I> : <I>source</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Makes <I>target</I> a hard link to <I>source,</I> if it isn't one
|
||||
already. (Unix only.)
|
||||
</BLOCKQUOTE>
|
||||
<B>HdrRule</B> <I>source</I> : <I>headers</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Arranges the proper dependencies when the file
|
||||
<I>source</I> includes the files <I>headers</I> through the
|
||||
"#include" C preprocessor directive.
|
||||
<P>
|
||||
This rule is not intended to be called explicitly.
|
||||
It is called automatically during header scanning on
|
||||
sources handled by the Object rule (e.g., sources in
|
||||
Main or Library rules).
|
||||
</BLOCKQUOTE>
|
||||
<B>InstallBin</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Copy <I>sources</I> into <I>dir</I> with mode
|
||||
$(EXEMODE).
|
||||
</BLOCKQUOTE>
|
||||
<B>InstallLib</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Copy <I>sources</I> into <I>dir</I> with mode
|
||||
$(FILEMODE).
|
||||
</BLOCKQUOTE>
|
||||
<B>InstallMan</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Copy <I>sources</I> into the appropriate subdirectory
|
||||
of <I>dir</I> with mode $(FILEMODE). The subdirectory
|
||||
is man<I>s,</I> where <I>s</I> is the suffix of
|
||||
each of sources.
|
||||
</BLOCKQUOTE>
|
||||
<B>InstallShell</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Copy <I>sources</I> into <I>dir</I> with mode
|
||||
$(SHELLMODE).
|
||||
</BLOCKQUOTE>
|
||||
<B>Lex</B> <I>source.c</I> : <I>source.l</I> ; <BLOCKQUOTE>
|
||||
Process the lex(1) source file <I>source.l</I> and
|
||||
rename the lex.yy.c to <I>source.c.</I> Called by
|
||||
the Object rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>Library</B> <I>library</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Compiles <I>sources</I> and archives them into
|
||||
<I>library.</I> The intermediate <I>objects</I>
|
||||
are deleted. Calls Objects and LibraryFromObjects.
|
||||
<P>
|
||||
If Library is invoked with no suffix on <I>library</I>,
|
||||
the $(SUFLIB) suffix is used.
|
||||
</BLOCKQUOTE>
|
||||
<B>LibraryFromObjects</B> <I>library</I> : <I>objects</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Archives <I>objects</I> into <I>library.</I> The
|
||||
<I>objects</I> are then deleted.
|
||||
<P>
|
||||
If <I>library</I> has no suffix, the $(SUFLIB) suffix is used.
|
||||
</BLOCKQUOTE>
|
||||
<B>Link</B> <I>image</I> : <I>objects</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Links <I>image</I> from <I>objects</I> and sets
|
||||
permissions on <I>image</I> to $(EXEMODE).
|
||||
<I>Image</I> must be actual filename; suffix is not
|
||||
supplied.
|
||||
Called by Main.
|
||||
|
||||
</BLOCKQUOTE>
|
||||
<B>LinkLibraries</B> <I>image</I> : <I>libraries</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Makes <I>image</I> depend on <I>libraries</I> and
|
||||
includes them during the linking.
|
||||
<P>
|
||||
<I>Image</I> may be referenced without a suffix in this
|
||||
rule invocation; LinkLibraries supplies the suffix.
|
||||
</BLOCKQUOTE>
|
||||
<B>Main</B> <I>image</I> : <I>sources</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compiles <I>sources</I> and links them into <I>image.</I>
|
||||
Calls Objects and MainFromObjects.
|
||||
<P>
|
||||
<I>Image</I> may be referenced without a suffix in this
|
||||
rule invocation; Main supplies the suffix.
|
||||
</BLOCKQUOTE>
|
||||
<B>MainFromObjects</B> <I>image</I> : <I>objects</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Links <I>objects</I> into <I>image.</I> Dependency
|
||||
of exe. MainFromObjects supplies the suffix on <I>image</I>
|
||||
filename.
|
||||
</BLOCKQUOTE>
|
||||
<B>MakeLocate</B> <I>target</I> : <I>dir</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Creates <I>dir</I> and causes <I>target</I> to be built
|
||||
into <I>dir</I>.
|
||||
</BLOCKQUOTE>
|
||||
<B>MkDir</B> <I>dir</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Creates <I>dir</I> and its parent directories.
|
||||
</BLOCKQUOTE>
|
||||
<B>Object</B> <I>object</I> : <I>source</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compiles a <I>single</I> source file source into
|
||||
<I>object.</I> The Main and Library rules use
|
||||
this rule to compile source files.
|
||||
<P>
|
||||
Causes <I>source</I> to be scanned for "#include"
|
||||
directives and calls HdrRule to make all included
|
||||
files dependedencies of <I>object</I>.
|
||||
<P>
|
||||
Calls one of the following rules to do the actual
|
||||
compiling, depending on the suffix of source:
|
||||
<PRE>
|
||||
*.c: Cc
|
||||
*.cc: C++
|
||||
*.cpp: C++
|
||||
*.C: C++
|
||||
*.l: Lex
|
||||
*.y: Yacc
|
||||
*.*: UserObject
|
||||
</PRE>
|
||||
</BLOCKQUOTE>
|
||||
<B>ObjectC++Flags</B> <I>source</I> : <I>flags</I> ;
|
||||
<BR>
|
||||
<B>ObjectCcFlags</B> <I>source</I> : <I>flags</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Add <I>flags</I> to the source-specific
|
||||
value of $(CCFLAGS) or $(C++FLAGS) when compiling <I>source.</I>
|
||||
Any file suffix on <I>source</I> is ignored.
|
||||
</BLOCKQUOTE>
|
||||
<B>ObjectHdrs</B> <I>source</I> : <I>dirs</I> ; <BLOCKQUOTE>
|
||||
Add <I>dirs</I> to the source-specific value of
|
||||
$(HDRS) when scanning and compiling <I>source.</I>
|
||||
Any file suffix on <I>source</I> is ignored.
|
||||
</BLOCKQUOTE>
|
||||
<B>Objects</B> <I>sources</I> ; <BLOCKQUOTE>
|
||||
For each source file in <I>sources,</I> calls
|
||||
Object to compile the source file into a similarly
|
||||
named object file.
|
||||
</BLOCKQUOTE>
|
||||
<B>RmTemps</B> <I>targets</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Marks <I>sources</I> as temporary with the TEMPORARY
|
||||
rule, and deletes <I>sources</I> once <I>targets</I>
|
||||
are built. Must be the last rule invoked on
|
||||
<I>targets.</I> Used internally by LibraryFromObjects rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>Setuid</B> <I>images</I> ; <BLOCKQUOTE>
|
||||
Sets the setuid bit on each of <I>images</I> after
|
||||
linking. (Unix only.)
|
||||
|
||||
</BLOCKQUOTE>
|
||||
<B>SubDir</B> <I>VAR d1 ... dn</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Sets up housekeeping for the source files located
|
||||
in <I><CODE>$(VAR)/d1/.../dn</CODE></I>:
|
||||
<UL>
|
||||
<LI>Reads in rules file associated with <I>VAR</I>,
|
||||
if it hasn't already been read.
|
||||
<LI>Initializes variables for search paths,
|
||||
output directories, compiler
|
||||
flags, and grist, using <I>d1 ... dn</I> tokens.
|
||||
</UL>
|
||||
<P>
|
||||
<I>VAR</I> is the name of a variable;
|
||||
<I>d1</I> thru <I>dn</I> are elements
|
||||
of a directory path.
|
||||
</BLOCKQUOTE>
|
||||
<B>SubDirC++Flags</B> <I>flags</I> ;
|
||||
<BR>
|
||||
<B>SubDirCcFlags</B> <I>flags</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Adds <I>flags</I> to the compiler flags for source files
|
||||
in SubDir's directory.
|
||||
</BLOCKQUOTE>
|
||||
<B>SubDirHdrs</B> <I>paths</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Adds <I>paths</I> to the header search paths for source files
|
||||
in SubDir's directory.
|
||||
</BLOCKQUOTE>
|
||||
<B>SubInclude</B> <I>VAR d1 ... dn</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Reads the Jamfile in <I><CODE>$(VAR)/d1/.../dn/</CODE></I>.
|
||||
</BLOCKQUOTE>
|
||||
<B>Shell</B> <I>image</I> : <I>source</I> ; <BLOCKQUOTE>
|
||||
Copies <I>source</I> into the executable sh(1)
|
||||
script <I>image.</I> Ensures that the first line of
|
||||
the script is $(SHELLHEADER) (default #!/bin/sh).
|
||||
</BLOCKQUOTE>
|
||||
<B>Undefines</B> <I>images</I> : <I>symbols</I> ; <BLOCKQUOTE>
|
||||
Adds flags to mark <I>symbols</I> as undefined
|
||||
on link command for <I>images</I>.
|
||||
<I>Images</I> may be referenced unsuffixed; the
|
||||
Undefines rule supplies the suffix.
|
||||
</BLOCKQUOTE>
|
||||
<B>UserObject</B> <I>object</I> : <I>source</I> ; <BLOCKQUOTE>
|
||||
This rule is called by Object for source
|
||||
files with unknown suffixes, and should be defined
|
||||
in Jamrules
|
||||
with a user-provided rule to handle the source file
|
||||
types not handled by the Object rule.
|
||||
The Jambase UserObject rule merely issues a
|
||||
complaint when it encounters <I>source</I> with
|
||||
files suffixes it does not recognize.
|
||||
</BLOCKQUOTE>
|
||||
<B>Yacc</B> <I>source.c</I> : <I>source.y</I> ; <BLOCKQUOTE>
|
||||
Process the yacc(1) file <I>source.y</I> and renamed
|
||||
the resulting y.tab.c and y.tab.h to <I>source.c.</I>
|
||||
Produces a y.tab.h and renames it to <I>source.h.</I>
|
||||
Called by the <B>Object</B> rule.
|
||||
</BLOCKQUOTE>
|
||||
<P>
|
||||
<HR>
|
||||
<A NAME="PSEUDOTARGETS">
|
||||
<H3>
|
||||
Jambase Pseudotargets
|
||||
</H3>
|
||||
</A>
|
||||
<P>
|
||||
There are two kinds of Jam targets: file targets and pseudotargets.
|
||||
File targets are objects that can be found in the filesystem.
|
||||
Pseudotargets are symbolic, and usually represent other targets.
|
||||
Most Jambase rules that define file targets also define pseudotargets
|
||||
which are dependent on types of file targets. The Jambase pseudotargets
|
||||
are:
|
||||
<CENTER>
|
||||
<TABLE CELLPADDING=5%>
|
||||
<TR><TD>exe
|
||||
<TD>Executables linked by the Main or MainFromObjects rules
|
||||
|
||||
<TR><TD>lib
|
||||
<TD>Libraries created by the Library or LibraryFromObjects rules
|
||||
|
||||
<TR><TD>obj
|
||||
<TD>Compiled objects used to create Main or Library targets
|
||||
|
||||
<TR><TD>dirs
|
||||
<TD>Directories where target files are written
|
||||
|
||||
<TR><TD>file
|
||||
<TD>Files copied by File and Bulk rules
|
||||
|
||||
<TR><TD>shell
|
||||
<TD>Files copied by Shell rule
|
||||
|
||||
<TR><TD>clean
|
||||
<TD>Removal of built targets (except files copied by Install* rules)
|
||||
|
||||
<TR><TD>install
|
||||
<TD>Files copied by Install* rules
|
||||
|
||||
<TR><TD>uninstall
|
||||
<TD>Removal of targets copied by Install* rules
|
||||
|
||||
</TABLE>
|
||||
</CENTER>
|
||||
<P>
|
||||
In addition, Jambase makes the <b>jam</b> default target "all"
|
||||
depend on "exe", "lib", "obj", "files", and "shell".
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<A NAME="VARS">
|
||||
<H3>
|
||||
Jambase Variables
|
||||
</H3>
|
||||
</A>
|
||||
<P>
|
||||
Most of the following variables have default values for
|
||||
each platform; refer to the Jambase file to see what those
|
||||
defaults are.
|
||||
<P>
|
||||
ALL_LOCATE_TARGET
|
||||
<BLOCKQUOTE>
|
||||
Alternative location of built targets. By default,
|
||||
Jambase rules locate built targets in the source
|
||||
tree. By setting $(ALL_LOCATE_TARGET)
|
||||
in Jamrules, you can cause <b>jam</b>
|
||||
to write built targets to a location outside
|
||||
the source tree.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
AR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The archive command used to update Library
|
||||
and LibraryFromObjects targets.
|
||||
</BLOCKQUOTE>
|
||||
AS
|
||||
<BLOCKQUOTE>
|
||||
The assembler for As rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
ASFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Flags handed to the assembler for As.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
AWK
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The name of awk interpreter, used when copying a
|
||||
shell script for the Shell rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
BCCROOT
|
||||
<BLOCKQUOTE>
|
||||
Selects Borland compile and link actions on NT.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
BINDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Not longer used.
|
||||
(I.e., used only for backward compatibility with the
|
||||
obsolete INSTALLBIN rule.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CC
|
||||
|
||||
<BLOCKQUOTE>
|
||||
C compiler used for Cc rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CCFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Compile flags for Cc rule targets.
|
||||
The Cc rule sets target-specific $(CCFLAGS)
|
||||
values on its targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
C++
|
||||
|
||||
<BLOCKQUOTE>
|
||||
C++ compiler used for C++ rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
C++FLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Compile flags for C++ rule targets.
|
||||
The C++ rule sets target-specific $(C++FLAGS)
|
||||
values on its targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CHMOD
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Program (usually chmod(1)) used to set file
|
||||
permissions for Chmod rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CP
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The file copy program, used by File and Install* rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CRELIB
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, causes the Library rule to invoke the CreLib
|
||||
rule on the target library before attempting to archive
|
||||
any members, so that the library can be created if
|
||||
needed.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CW
|
||||
|
||||
<BLOCKQUOTE>
|
||||
On Macintosh, the root of the Code Warrior Pro 5 directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
DOT
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The operating system-specific name for the current directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
DOTDOT
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The operating system-specific name for the parent directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
EXEMODE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Permissions for executables linked with Link, Main,
|
||||
and MainFromObjects, on platforms with a Chmod action.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
FILEMODE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Permissions for files copied by File or Bulk,
|
||||
on platforms with a Chmod action.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
FORTRAN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The Fortran compiler used by Fortran rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
FORTRANFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Fortran compiler flags for Fortran rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
GROUP
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<I>(Unix only.)</I>
|
||||
The group owner for Install* rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRGRIST
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, used by the HdrRule to distinguish header files
|
||||
with the same name in diffrent directories.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRPATTERN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
A regular expression pattern that matches
|
||||
C preprocessor "#include" directives in source files
|
||||
and returns the name of the included file.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRRULE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Name of the rule to invoke with the results of header file
|
||||
scanning. Default is "HdrRule".
|
||||
<P>
|
||||
This is a jam-special variable. If both HDRRULE and HDRSCAN
|
||||
are set on a target,
|
||||
that target will be scanned for lines
|
||||
matching $(HDRSCAN), and $(HDDRULE) will be
|
||||
invoked on included files found in the matching $(HDRSCAN) lines.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Directories to be searched for header files.
|
||||
This is used by the Object rule to:
|
||||
<UL>
|
||||
<LI>set up search paths for finding files returned
|
||||
by header scans
|
||||
<LI>add -I flags on compile commands
|
||||
</UL>
|
||||
(See STDHDRS.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRSCAN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Regular expression pattern to use for header file
|
||||
scanning. The Object rule sets this to $(HDRPATTERN).
|
||||
This is a jam-special variable; see HDRRULE.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRSEARCH
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Used by the HdrRule to fix the list of directories where
|
||||
header files can be found for a given source file.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
JAMFILE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Default is "Jamfile"; the name of the user-written
|
||||
rules file found in each source directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
JAMRULES
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Default is "Jamrules"; the name of a rule definition
|
||||
file to be read in at the first SubDir rule invocation.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
KEEPOBJS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, tells the LibraryFromObjects rule not to delete
|
||||
object files once they are archived.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LEX
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The lex(1) command and flags.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LIBDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Not longer used.
|
||||
(I.e., used only for backward compatibility with the
|
||||
obsolete INSTALLLIB rule.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LINK
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The linker. Defaults to $(CC).
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LINKFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Flags handed to the linker. Defaults to $(CCFLAGS).
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LINKLIBS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
List of external libraries to link with. The target image
|
||||
does not depend on these libraries.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The hard link command for HardLink rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LOCATE_SOURCE
|
||||
<BLOCKQUOTE>
|
||||
Used to set the location of generated source files.
|
||||
The Yacc, Lex, and GenFile rules set LOCATE on
|
||||
their targets to $(LOCATE_SOURCE).
|
||||
$(LOCATE_SOURCE) is initialized by the SubDir rule
|
||||
to the source directory itself.
|
||||
(Also, see ALL_LOCATE_TARGET.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LOCATE_TARGET
|
||||
<BLOCKQUOTE>
|
||||
Used to set the location of built binary targets.
|
||||
The Object rule, and hence the Main and Library rules,
|
||||
set LOCATE on their targets to $(LOCATE_TARGET).
|
||||
$(LOCATE_TARGET) is initialized by the
|
||||
SubDir rule to the source directory itself.
|
||||
(See ALL_LOCATE_TARGET.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
MANDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Not longer used.
|
||||
(I.e., used only for backward compatibility with the
|
||||
obsolete INSTALLMAN rule.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
MKDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The 'create directory' command used for the MkDir
|
||||
rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
MODE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The target-specific file mode (permissions) for targets
|
||||
of the Shell, Setuid, Link, and Install* rules.
|
||||
Used by the Chmod action; hence relevant to NT and VMS
|
||||
only.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
MSVC
|
||||
<BLOCKQUOTE>
|
||||
Selects Microsoft Visual C 16-bit compile & link
|
||||
actions on NT.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
MSVCNT
|
||||
<BLOCKQUOTE>
|
||||
Selects Microsoft Visual C NT compile & link
|
||||
actions on NT.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
MV
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The file rename command and options.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
NEEDLIBS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The list of libraries used when linking an executable.
|
||||
Used by the Link rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
NOARSCAN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, indicates that library members' timestamps can't
|
||||
be found, and prevents the individual objects from being
|
||||
deleted, so that their timestamps can be used instead.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
NOARUPDATE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, indicates that libraries can't be updated, but only
|
||||
created whole.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
OPTIM
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The C compiler flag for optimization, used by Cc and C++
|
||||
rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
OSFULL
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The concatenation of $(OS)$(OSVER)$(OSPLAT), used when jam
|
||||
builds itself to determine the target binary directory.
|
||||
$(OS) and $(OSPLAT) are determined by jam at its compile
|
||||
time (in jam.h). $(OSVER) can optionally be set by the user.
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
OWNER
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The owner of installed files. Used by Install* rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
RANLIB
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The name of the ranlib command. If set, causes
|
||||
the Ranlib action to be applied after the
|
||||
Archive action to targets of the Library rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
RELOCATE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, tells the Cc rule to move the output object
|
||||
file to its target directory because the cc command
|
||||
has a broken -o option.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
RM
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The command and options to remove a file.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SEARCH_SOURCE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The directory to find sources listed with Main,
|
||||
Library, Object, Bulk, File, Shell, InstallBin,
|
||||
InstallLib, and InstallMan rules. This works by
|
||||
setting the jam-special variable SEARCH to the
|
||||
value of $(SEARCH_SOURCE) for each of the rules'
|
||||
sources. The SubDir rule initializes SEARCH_SOURCE
|
||||
for each directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SHELLHEADER
|
||||
|
||||
<BLOCKQUOTE>
|
||||
A string inserted to the first line of every file
|
||||
created by the Shell rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SHELLMODE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Permissions for files installed by Shell rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SOURCE_GRIST
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Set by the SubDir to a value derived from the
|
||||
directory name, and used by Objects and related
|
||||
rules as 'grist' to perturb file names.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
STDHDRS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Directories where headers can be found without
|
||||
resorting to using the flag to the C compiler.
|
||||
The $(STDHDRS) directories are used to find
|
||||
headers during scanning, but are not passed to the
|
||||
compiler commands as -I paths.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SUBDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The path from the current directory to the directory
|
||||
last named by the SubDir rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
TOP
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The path from the current directory to the directory
|
||||
that has the Jamrules file. Used by the SubDir rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SUFEXE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The suffix for executable files, if none provided.
|
||||
Used by the Main rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SUFLIB
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The suffix for libraries. Used by the Library and
|
||||
related rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SUFOBJ
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The suffix for object files. Used by the Objects
|
||||
and related rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
UNDEFFLAG
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The flag prefixed to each symbol for the Undefines
|
||||
rule (i.e., the compiler flag for undefined symbols).
|
||||
</BLOCKQUOTE>
|
||||
|
||||
WATCOM
|
||||
<BLOCKQUOTE>
|
||||
Selects Watcom compile and link actions on OS2.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
YACC
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The yacc(1) command.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
YACCFILES
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The base filename generated by yacc(1).
|
||||
</BLOCKQUOTE>
|
||||
|
||||
YACCFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The yacc(1) command flags.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P>
|
||||
<HR>
|
||||
<A HREF="#TOP">Back to top.</A>
|
||||
<P>
|
||||
Copyright 1997, 2000 Perforce Software, Inc.
|
||||
<BR>
|
||||
Comments to <A HREF="mailto:info@perforce.com">info@perforce.com</A>
|
||||
<BR>
|
||||
Last updated: Dec 31, 2000
|
||||
<BR>
|
||||
$Id$
|
||||
</BODY>
|
||||
</HTML>
|
||||
227
historic/jam/src/Jamfile
Normal file
227
historic/jam/src/Jamfile
Normal file
@@ -0,0 +1,227 @@
|
||||
#
|
||||
# Jamfile to build Jam (a make(1)-like program)
|
||||
#
|
||||
# There are no user-serviceable parts in this file.
|
||||
#
|
||||
# Put executables in platform-specific subdirectory.
|
||||
|
||||
# compile without assertions by default
|
||||
CCFLAGS ?= -DNDEBUG ;
|
||||
|
||||
if $(VMS) { LOCATE_TARGET ?= [.binvms] ; }
|
||||
else if $(MAC) { LOCATE_TARGET ?= :bin.mac ; }
|
||||
else { LOCATE_TARGET ?= bin.$(OSFULL[1]:L) ; }
|
||||
|
||||
# Leave generated source in current directory; it would be nice to use
|
||||
# these lines below to build the source into the platform-specific
|
||||
# directory, but getting scan.c to include the right jambase.h is
|
||||
# hard: with ""'s, it always gets the bootstrap version; with <>'s,
|
||||
# it won't find the bootstrap version.
|
||||
|
||||
# SEARCH_SOURCE ?= $(LOCATE_TARGET) $(DOT) ;
|
||||
# LOCATE_SOURCE ?= $(LOCATE_TARGET) ;
|
||||
|
||||
#
|
||||
# We have some different files for UNIX, VMS, and NT.
|
||||
#
|
||||
|
||||
if $(NT) {
|
||||
code = execnt.c filent.c pathunix.c ;
|
||||
if $(OSTYPE) = cygwin
|
||||
{
|
||||
YACC ?= bison -t -d -l -v --yacc ;
|
||||
YACCFILES = y.tab ;
|
||||
}
|
||||
}
|
||||
else if $(OS2)
|
||||
{
|
||||
# special case for OS/2. When building Jam with GCC/EMX
|
||||
# we need to use the "fileunix.c" file
|
||||
#
|
||||
# when we build it with other toolsets, we use "fileos2.c"
|
||||
#
|
||||
code = execunix.c pathunix.c ;
|
||||
if $(TOOLSET) = EMX
|
||||
{
|
||||
CCFLAGS += -D__OS2__ ;
|
||||
code += fileunix.c ;
|
||||
}
|
||||
else
|
||||
{
|
||||
code += fileos2.c ;
|
||||
}
|
||||
}
|
||||
else if $(VMS) { code = execvms.c filevms.c pathvms.c ; }
|
||||
else if $(MAC) { code = execmac.c filemac.c pathmac.c ; }
|
||||
else { code = execunix.c fileunix.c pathunix.c ; }
|
||||
|
||||
# We have to signal jam.h for these
|
||||
|
||||
if $(OS) = NT
|
||||
{
|
||||
if $(TOOLSET) = MINGW || $(TOOLSET) = LCC
|
||||
{
|
||||
CCFLAGS += -DNT ;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCFLAGS += /DNT ;
|
||||
}
|
||||
}
|
||||
|
||||
# Do we know yacc?
|
||||
|
||||
if $(YACC) { code += jamgram.y ; }
|
||||
else { code += jamgram.c ; }
|
||||
|
||||
#
|
||||
# Build the jamgram.y from the jamgram.yy
|
||||
# yyacc is a slippery script that makes grammars a little
|
||||
# easier to read/maintain.
|
||||
#
|
||||
|
||||
if ( $(UNIX) || $(NT) ) && $(YACC)
|
||||
{
|
||||
local SUFEXE = ; # yyacc is a script with no suffix - this handles cygwin
|
||||
GenFile jamgram.y jamgramtab.h : ./yyacc jamgram.yy ;
|
||||
}
|
||||
|
||||
#
|
||||
# How to build the compiled in jambase.
|
||||
#
|
||||
|
||||
Main mkjambase : mkjambase.c ;
|
||||
|
||||
#
|
||||
# The guts of the Jamfile: how to build Jam
|
||||
#
|
||||
|
||||
Main jam : jam.c jambase.c ;
|
||||
LinkLibraries jam : libjam.a ;
|
||||
GenFile jambase.c : mkjambase$(SUFEXE) Jambase ;
|
||||
|
||||
Library libjam.a :
|
||||
command.c compile.c $(code) expand.c glob.c
|
||||
hash.c headers.c hdrmacro.c lists.c make.c make1.c newstr.c
|
||||
option.c parse.c regexp.c rules.c scan.c search.c subst.c
|
||||
timestamp.c variable.c modules.c strings.c filesys.c ;
|
||||
|
||||
|
||||
if $(BINDIR) { InstallBin $(BINDIR) : jam ; }
|
||||
|
||||
#
|
||||
# Distribution making from here on out.
|
||||
#
|
||||
|
||||
ALLSOURCE =
|
||||
Build.com Build.mpw Jam.html Jambase Jambase.html Jamfile
|
||||
Jamfile.html Makefile Porting README RELNOTES command.c command.h
|
||||
compile.c compile.h execcmd.h execmac.c execunix.c execnt.c execvms.c
|
||||
expand.c expand.h filemac.c filent.c fileos2.c filesys.h fileunix.c
|
||||
filevms.c glob.c hash.c hash.h hdrmacro.c hdrmacro.h headers.c
|
||||
headers.h jam.c jam.h jambase.c jambase.h jamgram.c jamgram.h
|
||||
jamgram.y jamgram.yy jamgramtab.h lists.c lists.h make.c make.h
|
||||
make1.c mkjambase.c modules.c newstr.c newstr.h option.c option.h parse.c
|
||||
parse.h patchlevel.h pathmac.c pathunix.c pathvms.c regexp.c regexp.h
|
||||
rules.c rules.h scan.c scan.h search.c search.h strings.c subst.c timestamp.c
|
||||
timestamp.h variable.c variable.h filesys.c filesys.h yyacc
|
||||
INSTALL
|
||||
common.mk
|
||||
builds/win32-visualc.mk
|
||||
builds/win32-borlandc.mk
|
||||
builds/win32-gcc.mk
|
||||
;
|
||||
|
||||
|
||||
rule Binary
|
||||
{
|
||||
NotFile package ;
|
||||
Depends package : $(<) ;
|
||||
|
||||
DEPENDS $(<) : $(>) ;
|
||||
|
||||
switch $(<)
|
||||
{
|
||||
case *-win32.zip : Zip-Exe $(<) : $(>) ;
|
||||
case *-os2.zip : Zip-Exe $(<) : $(>) ;
|
||||
case *-linux-libc6.tar : GZip-Exe $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rule Package
|
||||
{
|
||||
NotFile package ;
|
||||
Depends package : $(<) ;
|
||||
|
||||
DEPENDS $(<) : $(>) ;
|
||||
|
||||
switch $(<)
|
||||
{
|
||||
case *.tar : { Tar-Gz $(<) : $(>) ; Tar-Bz2 $(<) : $(>) ; }
|
||||
case *.zip : Zip $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
VERSION = ftjam-2.3.5 ;
|
||||
|
||||
|
||||
actions Tar-Gz
|
||||
{
|
||||
ln -s . $(VERSION)
|
||||
tar cvhf $(<) $(VERSION)/$(>)
|
||||
rm $(VERSION)
|
||||
gzip -9 $(<)
|
||||
}
|
||||
|
||||
actions Tar-Bz2
|
||||
{
|
||||
ln -s . $(VERSION)
|
||||
tar cvhf $(<) $(VERSION)/$(>)
|
||||
rm $(VERSION)
|
||||
bzip2 -9 $(<)
|
||||
}
|
||||
|
||||
|
||||
actions Zip
|
||||
{
|
||||
zip -9r $(<) $(>)
|
||||
}
|
||||
|
||||
actions Zip-Exe
|
||||
{
|
||||
zip -9j $(<) $(LOCATE_TARGET)\jam.exe
|
||||
}
|
||||
|
||||
actions GZip-Exe
|
||||
{
|
||||
ln -s $(LOCATE_TARGET)/jam jam
|
||||
strip jam
|
||||
tar chf $(<) jam
|
||||
rm -f jam
|
||||
gzip -9 $(<)
|
||||
}
|
||||
|
||||
|
||||
|
||||
if $(NT)
|
||||
{
|
||||
Binary $(VERSION)-win32.zip : $(ALLSOURCE) ;
|
||||
Package $(VERSION).zip : $(ALLSOURCE) ;
|
||||
}
|
||||
else if $(OS2)
|
||||
{
|
||||
Binary $(VERSION)-os2.zip : $(ALLSOURCE) ;
|
||||
Package $(VERSION).zip : $(ALLSOURCE) ;
|
||||
}
|
||||
else if $(OS) = LINUX
|
||||
{
|
||||
# how can we detect the C library version reliably ??
|
||||
# for now, this should only be used for convenience
|
||||
# purposes, until we add .rpm and .deb support in..
|
||||
|
||||
Binary $(VERSION)-linux-libc6.tar : jam ;
|
||||
|
||||
Package $(VERSION).tar : $(ALLSOURCE) ;
|
||||
Package $(VERSION).zip : $(ALLSOURCE) ;
|
||||
}
|
||||
1450
historic/jam/src/Jamfile.html
Normal file
1450
historic/jam/src/Jamfile.html
Normal file
File diff suppressed because it is too large
Load Diff
88
historic/jam/src/Makefile
Normal file
88
historic/jam/src/Makefile
Normal file
@@ -0,0 +1,88 @@
|
||||
# The following Makefile will build Jam on Unix systems
|
||||
# You can also modify it to compile the program on other
|
||||
# systems, or also use one of the specific Makefiles
|
||||
# located in the "builds" directory
|
||||
#
|
||||
|
||||
CC = cc
|
||||
TARGET = -o jam0
|
||||
CFLAGS =
|
||||
|
||||
# Borland C++ on Windows
|
||||
#CC = bcc32
|
||||
#TARGET = -ejam0
|
||||
#CFLAGS = /DNT -w- -q
|
||||
|
||||
# Special flavors - uncomment appropriate lines
|
||||
|
||||
# NCR seems to have a broken readdir() -- use gnu
|
||||
#CC = gcc
|
||||
|
||||
# AIX needs -lbsd, and has no identifying cpp symbol
|
||||
# Use _AIX41 if you're not on 3.2 anymore.
|
||||
#LINKLIBS = -lbsd
|
||||
#CFLAGS = -D_AIX
|
||||
|
||||
# NT (with Microsoft compiler)
|
||||
# Use FATFS if building on a DOS FAT file system
|
||||
#Lib = $(MSVCNT)/lib
|
||||
#Include = $(MSVCNT)/include
|
||||
#CC = cl /nologo
|
||||
#CFLAGS = -I $(Include) -DNT
|
||||
#TARGET = /Fejam0
|
||||
#LINKLIBS = $(Lib)/oldnames.lib $(Lib)/kernel32.lib $(Lib)/libc.lib
|
||||
|
||||
# BeOS - Metroworks CodeWarrior
|
||||
#CC = mwcc
|
||||
#Include = /NewDisk/develop/headers/posix
|
||||
#CFLAGS = -I $(Include)
|
||||
|
||||
# BeOS - gcc
|
||||
#CC = gcc
|
||||
#LINKLIBS = -lnet
|
||||
|
||||
# Interix - gcc
|
||||
#CC = gcc
|
||||
|
||||
# Cygwin - gcc & cygwin
|
||||
#CC = gcc
|
||||
#CFLAGS = -D__cygwin__
|
||||
|
||||
# MingW - gcc on Win32
|
||||
#
|
||||
#CC = gcc
|
||||
#CFLAGS = -DNT
|
||||
|
||||
# MPEIX
|
||||
#CC = gcc
|
||||
#CFLAGS = -I/usr/include -D_POSIX_SOURCE
|
||||
|
||||
# QNX rtp (neutrino)
|
||||
#CC = gcc
|
||||
|
||||
|
||||
#
|
||||
#SOURCES = \
|
||||
# command.c compile.c execnt.c execunix.c execvms.c expand.c \
|
||||
# filent.c fileos2.c fileunix.c filevms.c glob.c hash.c \
|
||||
# hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c \
|
||||
# newstr.c option.c parse.c pathunix.c pathvms.c regexp.c \
|
||||
# rules.c scan.c search.c subst.c timestamp.c variable.c
|
||||
|
||||
# for Unix systems
|
||||
#
|
||||
# we need to ensure that "jambase.c" has write permissions, since it is
|
||||
# going to be re-generated from "Jambase".
|
||||
#
|
||||
all: jam0
|
||||
chmod a+w jambase.c
|
||||
./jam0
|
||||
|
||||
# for other systems
|
||||
#all: jam0
|
||||
# jam0
|
||||
|
||||
include common.mk
|
||||
|
||||
#jam0:
|
||||
# $(CC) $(TARGET) $(CFLAGS) $(SOURCES) $(LINKLIBS)
|
||||
68
historic/jam/src/Porting
Normal file
68
historic/jam/src/Porting
Normal file
@@ -0,0 +1,68 @@
|
||||
Notes on porting Jam - revised 12/31/2000
|
||||
|
||||
1) Working out system dependencies in the Jam code.
|
||||
|
||||
Jam's OS footprint is fairly small. For OS independent work Jam
|
||||
liberally uses standard libc functions like stdio, malloc, and
|
||||
string. The OS dependent interfaces are:
|
||||
|
||||
From filesys.h:
|
||||
|
||||
file_parse() - split a file name into dir/base/suffix/member
|
||||
file_build() - build a filename given dir/base/suffix/member
|
||||
file_dirscan() - scan a directory for files
|
||||
file_archscan() - scan an archive for files
|
||||
file_time() - get the timestamp of a file, if not already
|
||||
done by file_dirscan().
|
||||
|
||||
From execcmd.h:
|
||||
|
||||
execcmd() - execute a shell script
|
||||
execwait() - wait for any outstanding execcmd()'s.
|
||||
|
||||
The current implementations are:
|
||||
|
||||
filemac.c - mac MPW
|
||||
filent.c - NT
|
||||
fileos2.c - OS/2
|
||||
fileunix.c - all UNIX
|
||||
filevms.c - VMS
|
||||
|
||||
execmac.c - mac MPW
|
||||
execunix.c - UNIX, OS/2, NT
|
||||
execvms.c - VMS
|
||||
|
||||
2) Defining OSMAJOR, OSMINOR in jam.h
|
||||
|
||||
So that the Jambase and Jamfile know their host, Jam defines $(OS)
|
||||
to be something useful for each platform. Make sure that there is
|
||||
code in jam.h to generate a useful value for $(OS), and key it off
|
||||
the platform specific C-preprocessor symbol. If the C-preprocessor
|
||||
doesn't itself defines such a symbol, add a define to the Makefile.
|
||||
|
||||
In addition to $(OS), you can also set $(OSPLAT) if the OS runs on
|
||||
multiple platforms (like Linux or NT).
|
||||
|
||||
3) Working out system dependencies in the Jambase
|
||||
|
||||
With the value of $(OS) available, the Jambase can be extended to
|
||||
support special variables or rules for new platforms. See the
|
||||
current support for VMS, NT, and Mac.
|
||||
|
||||
4) Yacc troubles
|
||||
|
||||
The generated files jamgram.h and jamgram.c are distributed for the
|
||||
poor souls without yacc.
|
||||
|
||||
5) Known problematic systems:
|
||||
|
||||
- Pyramid has no malloc.h, memory.h
|
||||
|
||||
- Encore has no stdlib.h
|
||||
|
||||
- Bull DPX has sys/file.h problems
|
||||
|
||||
6) Send the results back.
|
||||
|
||||
If you do porting work, the result can be integrated into future
|
||||
releases if you send it back to the author's address in the README.
|
||||
157
historic/jam/src/README
Normal file
157
historic/jam/src/README
Normal file
@@ -0,0 +1,157 @@
|
||||
This is the FreeType version of Jam. For more information, please see
|
||||
http://www.freetype.org/jam/index.html
|
||||
|
||||
The complete and detailed list of changes is available at:
|
||||
http://www.freetype.org/jam/changes.html
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Jam/MR (aka "jam - make(1) redux")
|
||||
|
||||
/+\
|
||||
+\ Copyright 1993, 2000 Christopher Seiwald.
|
||||
\+/
|
||||
|
||||
This is Release 2.3 of Jam/MR, a make-like program.
|
||||
|
||||
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.
|
||||
|
||||
FEATURES
|
||||
|
||||
-> Jam is a make(1) replacement that makes building simple things
|
||||
simple and building complicated things manageable.
|
||||
|
||||
-> Jam's language is expressive, making Jamfiles (c.f. Makefiles)
|
||||
compact. Here's a sample:
|
||||
|
||||
Main smail : main.c map.c resolve.c deliver.c
|
||||
misc.c parser.y alias.c pw.c headers.c
|
||||
scanner.l getpath.c str.c ;
|
||||
|
||||
This builds "smail" from a dozen source files. Jam handles
|
||||
header file dependencies automatically and on-the-fly.
|
||||
|
||||
-> Jam is very portable: it runs on UNIX, VMS, Mac, and NT.
|
||||
Most Jamfiles themselves are portable, like the sample above.
|
||||
|
||||
-> Jam is unintrusive: it is small, it has negligible CPU
|
||||
overhead, and it doesn't create any of its own funny files
|
||||
(c.f. Odin, nmake, SunOS make).
|
||||
|
||||
-> Jam can build large projects spread across many directories
|
||||
in one pass, without recursing, tracking the relationships
|
||||
among all files. Jam can do this with multiple, concurrent
|
||||
processes.
|
||||
|
||||
-> Jam isn't under the blinkin GNU copyright, so you can
|
||||
incorporate it into commercial products.
|
||||
|
||||
|
||||
INFORMATION GUIDE
|
||||
|
||||
Jam.html jam command usage
|
||||
|
||||
Jambase.html Reference for the Jambase boilerplate file.
|
||||
|
||||
Jamfile.html Easy reading on creating a Jamfile and using jam.
|
||||
|
||||
Jamlang.html The Jam language description.
|
||||
|
||||
RELNOTES Release 2.3 release notes.
|
||||
|
||||
Porting Notes on porting jam to wildcat platforms.
|
||||
|
||||
README This file. Includes installation instructions.
|
||||
|
||||
jam.c Contains the jam command's main() as well as an
|
||||
introduction to the code, for serious hackers.
|
||||
|
||||
|
||||
INSTALLING
|
||||
|
||||
The Makefile (UNIX, NT), build.com (VMS), Build.mpw (Mac MPW) are
|
||||
for bootstrapping. Once jam is built, it can rebuild itself.
|
||||
|
||||
UNIX
|
||||
|
||||
Build jam with make(1) on:
|
||||
|
||||
Platform $(OS)
|
||||
-------------------------
|
||||
AIX AIX *
|
||||
BSD/386 1.0 BSDI
|
||||
COHERENT/386 COHERENT
|
||||
DGUX 5.4 DGUX
|
||||
FreeBSD FREEBSD
|
||||
HPUX 9.0 HPUX
|
||||
IRIX 5.0 IRIX
|
||||
Linux LINUX
|
||||
NEXTSTEP 3.2 NEXT
|
||||
OSF/1 OSF
|
||||
PTX V2.1.0 PTX
|
||||
Solaris 2 SOLARIS *
|
||||
SunOS4.1 SUNOS
|
||||
Ultrix 4.2 ULTRIX
|
||||
BeOS BEOS *
|
||||
|
||||
* requires editing Makefile
|
||||
|
||||
Windows
|
||||
|
||||
Build jam with nmake on:
|
||||
|
||||
Platform $(OS)
|
||||
-------------------------
|
||||
NT NT *
|
||||
OS/2 OS2 *
|
||||
|
||||
The NT MAXLINE (command line length) is still set in jam.h to
|
||||
996, which was apparently the NT 3.5 limit. On 4.0, the limit
|
||||
is somewhere around 10K. For now, you can increase MAXLINE in
|
||||
jam.h so that a jam running on 4.0 will use the full command
|
||||
line length, but that jam.exe will fail miserably on the older OS.
|
||||
|
||||
On NT, a variable must be set before invoking jam to tell
|
||||
it where the C compiler lives. The name of this variable
|
||||
depends on which compiler you are using:
|
||||
|
||||
BCCROOT: The Borland C compiler
|
||||
MSVCNT: The Microsoft Compiler 5.0 (for NT)
|
||||
MSVC: The Microsoft Compiler 1.5 (for Windows)
|
||||
|
||||
Only MSVCNT has really been tested and is known to work.
|
||||
|
||||
Macintosh
|
||||
|
||||
Build jam with Build.mpw on:
|
||||
|
||||
Platform $(OS)
|
||||
-------------------------
|
||||
Macintosh MAC
|
||||
|
||||
You'll need to edit Build.mpw to set CW.
|
||||
|
||||
VMS
|
||||
|
||||
Build jam with @build.com on:
|
||||
|
||||
Platform $(OS)
|
||||
-------------------------
|
||||
VMS 5.4 VMS
|
||||
OPENVMS OPENVMS
|
||||
|
||||
Comments to the author!
|
||||
|
||||
November, 1993 - release 1.0
|
||||
March, 1995 - release 2.0
|
||||
February, 1996 - release 2.1
|
||||
November, 1997 - release 2.2
|
||||
December, 2000 - release 2.3
|
||||
|
||||
Christopher Seiwald
|
||||
|
||||
seiwald@perforce.com
|
||||
754
historic/jam/src/RELNOTES
Normal file
754
historic/jam/src/RELNOTES
Normal file
@@ -0,0 +1,754 @@
|
||||
Release notes for FTJam 2.3.5 (previous release was named "20010626")
|
||||
|
||||
0. Bugs fixed since 20010626:
|
||||
|
||||
DEBUG OUTPUT FORMATTING: indentation was "wrapped" when too many levels
|
||||
were reached, making debugging extremly difficult
|
||||
|
||||
1. Release info:
|
||||
|
||||
FTJam 2.3.5 (based on Jam 2.3.2)
|
||||
July 30, 2001
|
||||
VERSION 2.3.5
|
||||
PATCHLEVEL 3
|
||||
|
||||
2. Compatibility
|
||||
|
||||
FTJam 2.3.5 is upward compatible with Jam 2.3 and 2.2
|
||||
Only a few new builtin rules were added, and some small bugs fixed
|
||||
|
||||
3. Changes since 20010626:
|
||||
|
||||
Added a new builtin named FAIL_EXPECTED. It is used to invert the result
|
||||
of a given action. Used by the Boost.Build sub-system.
|
||||
|
||||
============================================================================
|
||||
============================================================================
|
||||
|
||||
|
||||
Release notes for Jam/MR 2.3
|
||||
(aka Jam - make(1) redux)
|
||||
|
||||
0. Bugs fixed since 2.3.1
|
||||
|
||||
PATCHLEVEL 2 - 3/12/2001
|
||||
|
||||
NOCARE changed back: it once again does not applies to targets
|
||||
with sources and/or actions. In 2.3 it was changed to apply to
|
||||
such targets, but that broke header file builds: files that are
|
||||
#included get marked with NOCARE, but if they have source or
|
||||
actions, they still should get built.
|
||||
|
||||
1. Release info:
|
||||
|
||||
Jam/MR 2.3
|
||||
November 16, 2000
|
||||
VERSION 2.3
|
||||
PATCHLEVEL 1
|
||||
|
||||
2. Compatibility
|
||||
|
||||
Jam 2.3 is upward compatible with Jam 2.2.
|
||||
|
||||
The Jam 2.3 language is a superset of the 2.2 language;
|
||||
Jamfiles, Jambase, and other rulesets used in 2.2 can be used
|
||||
with the 2.3 language support.
|
||||
|
||||
3. Changes since 2.2
|
||||
|
||||
3.1. Changes to Jam Language
|
||||
|
||||
Rules now can have values, which can expanded into a list with
|
||||
the new "[ rule args ... ]" syntax. A rule's value is the value
|
||||
of its last statement, though only the following statements have
|
||||
values: if (value of the leg chosen), switch (ditto), set (value
|
||||
of the resulting variable), return (its arguments). Note that
|
||||
'return' doesn't actually return. This support is EXPERIEMENTAL
|
||||
and otherwise undocumented. (2.3.1)
|
||||
|
||||
Because of the new way lists are processed, if a rule has no
|
||||
targets a warning message is no longer issued.
|
||||
|
||||
NOCARE now applies to targets with sources and/or actions,
|
||||
rather than just those without.
|
||||
|
||||
3.2. Jambase Changes
|
||||
|
||||
The HDRPATTERN variable now allows for leading blanks before
|
||||
the #include, to keep up with ANSI. By john@nanaon-sha.co.jp
|
||||
(John Belmonte) (2.2.3).
|
||||
|
||||
HDRPATTERN has been adjusted to avoid mistaking cases like:
|
||||
|
||||
# include <time.h> /* could be <sys/time.h> */
|
||||
|
||||
MkDir now NOUPDATE's $(DOT), so that there are no dependencies
|
||||
on the current directory's timestamp. By john@nanaon-sha.co.jp
|
||||
(John Belmonte).
|
||||
|
||||
The old mock functions like makeDirName, which assigned their
|
||||
results to the variable named as their first argument, have
|
||||
been replaced with real functions using the new [] synxtax.
|
||||
E.g. "makeDirName foo : bar ola" is now "foo = [ fDirName bar ]"
|
||||
|
||||
Install now always does a cp/chmod/etc, rather than using
|
||||
the system's install(1), which invariably seems broken.
|
||||
|
||||
3.3. Jam internal code changes
|
||||
|
||||
$JAMUNAME is set on UNIX. (2.2.4).
|
||||
|
||||
Jam ANSI-fied (2.3.0).
|
||||
|
||||
jam.h now defines a bunch of symbols used by the other source
|
||||
files, so as minimize compiler- and platform-specific ifdefs.
|
||||
|
||||
OSVER is no longer set by jam.h (it was only set for AIX).
|
||||
Jam does not depend on this variable at all, except to set
|
||||
$(OSFULL), which is used to determine jam's build directory.
|
||||
If the user needs to distinguish between various revs of
|
||||
OSs, he must set OSVER in the environment.
|
||||
|
||||
4. Fixed bugs
|
||||
|
||||
Redefining a rule while it was executing could cause jam to
|
||||
crash. Reference counts are now used to prevent that, thanks
|
||||
to Matt Armstrong.
|
||||
|
||||
Logic for computing chunk size when executing PIECEMEAL rules
|
||||
has been reworked to be a little more accurate, without danger
|
||||
of overflow, at the cost of being a little more compute intensive.
|
||||
Instead of computing an estimate chunksize in the (now gone)
|
||||
make1chunk(), make1cmds() now just goes full bore and tries to
|
||||
use all args. When that fails, it backs off by 10% of the source
|
||||
args until the command fits. It takes a little bit more compute
|
||||
time compared to the old logic, but when you're executing actions
|
||||
to build all of Shinola it's still pretty small in the scheme
|
||||
of things.
|
||||
|
||||
The NT handle leak in execunix.c has been fixed, thanks to
|
||||
Gurusamy Sarathy. (2.2.1).
|
||||
|
||||
5. Porting
|
||||
|
||||
Platforms newly supported or updated:
|
||||
|
||||
AmigaOS (with gcc), courtesy of Alain Penders (2.2.2).
|
||||
|
||||
Beos
|
||||
|
||||
CYGWIN 1.1.4, courtesy of John Belmonte <john@nanaon-sha.co.jp>.
|
||||
|
||||
IBM AS400 via Visual Age on NT (primitive)
|
||||
|
||||
IBM OS/390 Unix System Services
|
||||
|
||||
Linux SuSE on OS390
|
||||
|
||||
Linux Mips, ARM
|
||||
|
||||
Lynx
|
||||
|
||||
HPUX 11, IA64
|
||||
|
||||
Mac OS X Server, courtesy of Jeff_Sickel@sickel.com (2.2.5).
|
||||
|
||||
Mac Rhapsody
|
||||
|
||||
MPE IX 6.0
|
||||
|
||||
NetBSD
|
||||
|
||||
QNX RTP (QNX 6.0)
|
||||
|
||||
Siemens Sinix
|
||||
|
||||
UNICOS
|
||||
|
||||
VMS 6.2, 7.1
|
||||
|
||||
Windows NT IA64
|
||||
|
||||
5.1. NT Porting Notes
|
||||
|
||||
Always create tmp .bat file for actions if JAMSHELL is set.
|
||||
That way, if JAMSHELL is a .bat file itself, it can handle
|
||||
single-command actions with more than 9 cmd line args.
|
||||
|
||||
COMSPEC is no longer examined: cmd.exe is always used
|
||||
instead. Only cmd.exe can execute the Jambase rules anyhow.
|
||||
|
||||
Jam can be built with Borland C++ 5.5.
|
||||
|
||||
OS2 fixes: InstallBin now works. Filenames are now downshifted,
|
||||
so mixed case works better there, too. file_dirscan() can now scan
|
||||
the root ("c:\" or "\") directory, which it couldn't handle before.
|
||||
|
||||
var_defines now ignores OS=Windows_NT, because it conflicts
|
||||
with Jam's setting of OS (to NT).
|
||||
|
||||
5.2. Mac OS 8/9 Notes
|
||||
|
||||
The support for Mac is curious at best. It runs under MPW.
|
||||
|
||||
It requires CodeWarrior Pro 5, but no longer requires GUSI.
|
||||
|
||||
Use Build.mpw to bootstrap the build.
|
||||
|
||||
The Mac specific definitions in the Jambase are not intended
|
||||
to be of general purpose, but are sufficient to have Jam build
|
||||
itself.
|
||||
|
||||
===============================================================================
|
||||
===============================================================================
|
||||
|
||||
|
||||
Release Notes for Jam 2.2
|
||||
|
||||
1. Release info:
|
||||
|
||||
Jam 2.2
|
||||
October 22, 1997
|
||||
VERSION 2.2
|
||||
PATCHLEVEL 1
|
||||
|
||||
2. Compatibility
|
||||
|
||||
Jam 2.2 is a roll-up of 'Jam - make(1) redux' release 2.1+.
|
||||
Most of the changes described below were available before this,
|
||||
in the jam.2.1.plus.tar ball.
|
||||
|
||||
The Jam 2.2 language is a superset of the 2.1 language;
|
||||
Jamfiles, Jambase, and other rulesets used in 2.1 can be used
|
||||
with the 2.2 language support.
|
||||
|
||||
See 'Jambase Changes', below, to see if your Jamfiles need any
|
||||
changes to work with the 2.2 Jambase.
|
||||
|
||||
|
||||
3. Changes Since 2.1
|
||||
|
||||
New product name: Jam. (Executable program is still named 'jam'.)
|
||||
|
||||
Documentation rewritten; HTML versions supplied.
|
||||
|
||||
|
||||
3.1 Changes to Jam Language (See Jamlang.html)
|
||||
|
||||
Rules may now have more fields than just $(<) and $(>).
|
||||
|
||||
Local variables are now supported.
|
||||
|
||||
The expression 'if $(A) in $(B)' is now supported.
|
||||
|
||||
New variable modifiers :U and :L result in uppercased or lowercased
|
||||
values.
|
||||
|
||||
New variable modifier :P reliably results in parent directory
|
||||
of either a file or directory. (Previously, :D was used, but on VMS
|
||||
:D of a directory name is just the directory name.)
|
||||
|
||||
The :S variable modifier now results in the _last_ suffix if a
|
||||
filename has more than one dot (.) in it.
|
||||
|
||||
New predefined $(JAMDATE) variable is initialized at runtime for
|
||||
simple date stamping.
|
||||
|
||||
New predefined variables $(OSVER) and $(OSPLAT) are used to
|
||||
distinguish among operating system versions and hardware platforms,
|
||||
when possible.
|
||||
|
||||
New 'bind' qualifier on action definitions allows variables
|
||||
other than $(<) and $(>) to be bound with SEARCH and LOCATE paths.
|
||||
|
||||
Action buffer size is no longer limited by MAXCMD. Instead, each
|
||||
line in an action is limited by MAXLINE, defined for each OS, and
|
||||
the entire action size is limited by CMDBUF.
|
||||
|
||||
|
||||
3.2 Jambase Changes (See Jamfile.html)
|
||||
|
||||
Jambase has been reworked to incorporate new language features.
|
||||
|
||||
A handful of new utility rules has been added: makeString,
|
||||
makeDirName, etc.
|
||||
|
||||
New HDRGRIST variable in Jambase allows for headers with the same
|
||||
name to be distinguished.
|
||||
|
||||
LOCATE_TARGET now has a new flavor, LOCATE_SOURCE, that is used by
|
||||
rules that generate source files (e.g., Yacc and Lex).
|
||||
|
||||
Header file includes now happen in the proper order. The limit of
|
||||
10 include files has been eliminated.
|
||||
|
||||
The old "Install" rule is no longer available. Use InstallBin,
|
||||
InstallFile, InstallLib, InstallMan, or InstallShell instead.
|
||||
|
||||
|
||||
3.3 'jam' Changes (See Jam.html)
|
||||
|
||||
'jam' can now be built as a stand-alone program, with Jambase
|
||||
compiled into the executable. An external or alternate Jambase can
|
||||
still be referenced explicitly with -f.
|
||||
|
||||
On command failure, 'jam' now emits the text of the command that
|
||||
failed. This is a compromise between the normal -d1 behavior (where
|
||||
commands were never seen) and -d2 (where commands are always seen).
|
||||
|
||||
'jam' now exits non-zero if it doesn't have a total success. A parse
|
||||
error, sources that can't be found, and targets that can't be built
|
||||
all generate non-zero exit status.
|
||||
|
||||
The debugging levels (-d flags) have been slightly redefined.
|
||||
|
||||
The supplied Jamfile now builds 'jam' into a platform specific
|
||||
subdirectory. This lets you use the same source directory to
|
||||
build 'jam' for more than one platform.
|
||||
|
||||
The supplied Jamfile does not rebuild generated source files by
|
||||
default. (They are supplied with the distribution.) See Jamfile
|
||||
for more information.
|
||||
|
||||
|
||||
4. Fixed Bugs
|
||||
|
||||
The 'include' bug has finally been fixed, so that include
|
||||
statements take effect exactly when they are executed,
|
||||
rather than after the current statement block. This also
|
||||
corrects the problem where an 'include' within an 'if'
|
||||
block would wind up including the file one token after the
|
||||
'if' block's closing brace. Credit goes to Thomas Woods
|
||||
for suggesting that the parse tree generation and parse
|
||||
tree execution be paired in their own loop, rather than
|
||||
having the parser execute the tree directly.
|
||||
|
||||
The setting and extracting of grist has been regularized:
|
||||
normally, if you set a component of a filename (using the
|
||||
:DBSMG= modifiers), you are supposed to include the delimiters
|
||||
that set off the component: that is, you say "$(x:S=.suffix)",
|
||||
including the ".". But with grist it was inconsistent
|
||||
between setting and getting: setting grist required no
|
||||
<>'s, while getting grist included them. Getting grist
|
||||
continues to return the <>'s, but now setting grist can
|
||||
either include them (the new way) or not (the old way).
|
||||
|
||||
'actions together' now suppresses duplicate sources from
|
||||
showing up in $(>).
|
||||
|
||||
Accessing variables whose names contained ['s (as happens with
|
||||
MkDir on VMS) wasn't working, because it treated the [ as an
|
||||
array subscript. Now [ and ] are, like :, handled specially so
|
||||
that they can appear in variable values.
|
||||
|
||||
The 'if' statement now compares all elements in expressions;
|
||||
previously, it only compared the first element of each list.
|
||||
|
||||
If a command line in an action is longer than MAXLINE (formerly
|
||||
MAXCMD), 'jam' now issues an error and exits rather than dumping
|
||||
core.
|
||||
|
||||
If a Jamfile ended without a trailing newline, jam dumped core.
|
||||
This has been fixed.
|
||||
|
||||
|
||||
5. Porting
|
||||
|
||||
See jam.h for the definitive list of supported platforms.
|
||||
Since 2.1, support has been added for:
|
||||
|
||||
Macintosh MPW
|
||||
Alpha VMS
|
||||
Alpha NT
|
||||
NT PowerPC
|
||||
BeOS
|
||||
MVS OE
|
||||
UNIXWARE
|
||||
QNX
|
||||
SINIX (Nixdorf)
|
||||
OS/2
|
||||
Interactive UNIX (ISC), courtesy of Matthew Newhook
|
||||
|
||||
|
||||
5.1 NT Support Fixes
|
||||
|
||||
The NT command executor now handles multiple line actions, by writing
|
||||
multi-line actions to a batch file and executing that.
|
||||
|
||||
Targets are universally lowercased on NT. (Matthew Newhook)
|
||||
|
||||
Concurrent process support is fully enabled for NT.
|
||||
(Gurusamy Sarathy <gsar@engin.umich.edu>)
|
||||
|
||||
Path handling: Jam now knows that the directory component of "D:\"
|
||||
is "D:\", just as on unix it knows that the directory component of
|
||||
"/" is "/". It also now successfully gets the timestamp for "D:\"
|
||||
or just plain "\".
|
||||
|
||||
|
||||
5.2 VMS Support Fixes
|
||||
|
||||
VMS support is much, much better now. The path name manipulation
|
||||
routines (in pathvms.c) were more or less rewritten, and they now
|
||||
handle the vagaries of combining directory and file names properly.
|
||||
|
||||
Targets are universally lowercased on VMS.
|
||||
|
||||
Multi-line command blocks on VMS are now executed in a single system()
|
||||
call rather than separate ones for each line, so that actions can
|
||||
be DCL scripts.
|
||||
|
||||
===============================================================================
|
||||
===============================================================================
|
||||
|
||||
|
||||
Release notes for Jam 2.1.
|
||||
|
||||
1. Release info:
|
||||
Jam 2.1
|
||||
February 1, 1996
|
||||
VERSION 2.1
|
||||
PATCHLEVEL 0
|
||||
|
||||
2. Porting
|
||||
|
||||
Linux is now supported.
|
||||
|
||||
FREEBSD is now supported.
|
||||
|
||||
SCO ("M_XENIX") now supported.
|
||||
|
||||
NCR now supported.
|
||||
|
||||
NEXT support from karthy@dannug.dk (Karsten Thygesen)
|
||||
|
||||
DECC support from zinser@axp614.gsi.de (Martin P.J. Zinser)
|
||||
|
||||
I have changes for OS/2, but no way to test them. Volunteers?
|
||||
I have VMS multiprocess support, but no way to test it. Volunteers?
|
||||
|
||||
2.1. NT Support fixes.
|
||||
|
||||
The NT support is considerably more real than it was in 2.0.
|
||||
Filent.c had its syntax error corrected, it no longer skips the
|
||||
first entry when scanning directories, and it handles string
|
||||
tables in archives (for long object file names).
|
||||
|
||||
The Jambase was changed a bit to support the various C/C++
|
||||
compilers on NT, although it has only been thorougly tested
|
||||
with MSVC20.
|
||||
|
||||
You still need to set MSVCNT or BCCROOT to the root of the
|
||||
the compiler's directory tree, and you'll get an error if you
|
||||
don't set it (rather than getting a pile of mysterious errors).
|
||||
|
||||
2.2. Other porting fixes.
|
||||
|
||||
SPLITPATH now set up for UNIX (:), NT (;), VMS (,)
|
||||
|
||||
Jambase support for Solaris works better now: the location of
|
||||
AR is hardwired to /usr/ccs/bin/ar and it knowns "install"
|
||||
doesn't take -c. Solaris -- how the mighty have fallen.
|
||||
|
||||
To handle Linux's wacko yacc, jamgram.h is now included after
|
||||
scan.h so that YYSTYPE is define.
|
||||
|
||||
3. Jambase Changes (see Jamfile.html)
|
||||
|
||||
SubDir now computes the root directory for the source tree, if
|
||||
the variable naming the root directory isn't set in the environment.
|
||||
It counts the number of directory elements leading from the root
|
||||
to the current directory (as passed to SubDir) and uses that many
|
||||
"../"'s to identify the root. This means that to use SubDir you
|
||||
no longer have to have anything special set in the environment.
|
||||
|
||||
InstallFile is now an alias for InstallLib.
|
||||
|
||||
'first' is now dependency of all pseudo-targets (all, files,
|
||||
exe, lib, shell), so that jamming any of these pseudo-targets
|
||||
also builds any dependencies of 'first'.
|
||||
|
||||
The File rule definition in the Jambase was missing an &.
|
||||
|
||||
The File rule now calls the Clean rule, so that installed files
|
||||
get cleaned.
|
||||
|
||||
4. Jam changes (see Jam.html)
|
||||
|
||||
Variables may now be set on the command line with -svar=value.
|
||||
|
||||
Targets marked with NOUPDATE are now immune to the -a (anyhow)
|
||||
flag. Previously, the MkDir rule would try to recreate directories
|
||||
that already exist when jam was invoked with -a.
|
||||
|
||||
A new variable, $(JAMVERSION), joins the small list of built-in
|
||||
variables. It it set to the release of jam, currently "2.1".
|
||||
|
||||
If an actions fails, jam now deletes the target(s). It won't
|
||||
delete libraries or other targets that are composites. This is
|
||||
now consistent with jam's behavior on interrupts (it deletes the
|
||||
targets).
|
||||
|
||||
Jam had a nasty bug when setting multiple variables to the same
|
||||
value: if the first two variable names were the same, the variable
|
||||
value got trashed. This also affected "on target" variables if
|
||||
the first two targets were the same. For example:
|
||||
|
||||
FOO on bar.c bar.c foo.c = a b c ;
|
||||
|
||||
This would mangle the value of FOO for bar.c and foo.c. This has
|
||||
been fixed.
|
||||
|
||||
Jam would generate bogus numbers when reporting the number of
|
||||
targets updated after an interrupt. It now is more careful about
|
||||
counting.
|
||||
|
||||
The debugging flag -d has been extended. In addition to supporting
|
||||
-dx (turn on debugging for all levels up to x) there is also now
|
||||
-d+x (turn on debugging at only level x). The default output
|
||||
level is -d1 (-or d2 if -n is given); this can be turned off with
|
||||
-d0. The debug levels are listed in jam.1 and jam.h.
|
||||
|
||||
The parsing debug output now uses indenting to indicate when
|
||||
one rule invokes another.
|
||||
|
||||
===============================================================================
|
||||
===============================================================================
|
||||
|
||||
|
||||
Release notes for Jam 2.0.
|
||||
|
||||
1. Release info:
|
||||
Jam 2.0
|
||||
March 10, 1994
|
||||
VERSION 2.0
|
||||
PATCHLEVEL 5
|
||||
|
||||
2. Porting
|
||||
|
||||
Windows/NT is now (crudely) supported, courtesy of Brett Taylor
|
||||
and Laura Wingerd.
|
||||
|
||||
COHERENT/386 is now supported, courtesy of Fred Smith.
|
||||
|
||||
Solaris archive string table for long archive names is now
|
||||
supported, thanks to Mike Matrigali.
|
||||
|
||||
3. Compatibility
|
||||
|
||||
Jam 2.0 syntax is a superset of Jam 1.0 syntax, and thus it can
|
||||
interpret a Jam 1.0 Jambase.
|
||||
|
||||
The Jam 2.0 Jambase is a superset of the Jam 1.0 Jambase, and
|
||||
thus it can include a Jamfile written for Jam 1.0.
|
||||
|
||||
4. Changes from Jam 1.0 to Jam 2.0
|
||||
|
||||
4.1. Documentation changes
|
||||
|
||||
New Jamfile.5 manual page, with lots of examples and easy
|
||||
reading. It replaces both the old "Examples" file as well as
|
||||
the old Jambase.5 manual page.
|
||||
|
||||
jam.1 edited by Stephen W. Liddle and Diane Holt.
|
||||
|
||||
4.2. Jambase Changes (see Jamfile.5)
|
||||
|
||||
4.2.1. New rules:
|
||||
|
||||
There are new rules to make handling subdirectories easier:
|
||||
SubDir, SubInclude, SubDirCcFlags, SubDirHdrs.
|
||||
|
||||
There are new rules to handle file-specific CCFLAGS and HDRS:
|
||||
ObjectCcFlags and ObjectHdrs.
|
||||
|
||||
Misc new rules: HardLink, InstallShell, MkDir.
|
||||
|
||||
New rule "clean" that deletes exactly what jam has built, and
|
||||
"uninstall" that deletes exactly what was installed.
|
||||
|
||||
New rules for handling suffixes .s, .f, .cc, .cpp, .C.
|
||||
|
||||
4.2.2. Old rules:
|
||||
|
||||
The InstallBin, Lib, Man, and the new Shell rules now take the
|
||||
destination directory as the target and the files to be copied
|
||||
as sources. These rules formerly took the files to be copied
|
||||
as targets, and used built-in destination directories of
|
||||
$(BINDIR), $(LIBDIR), $(MANDIR), and $(BINDIR).
|
||||
|
||||
The InstallBin, Lib, Man, and Shell rules use the install(1)
|
||||
program now, instead of doing their own copying.
|
||||
|
||||
The Cc rule now uses -o when possible, rather than moving the
|
||||
result. Some platforms (Pyramid?) have a broken -o.
|
||||
|
||||
Jambase rules taking libraries, objects, and executables now
|
||||
all ignore the suffixes provided and use the one defined in the
|
||||
Jambase for the platform.
|
||||
|
||||
Stupid yyacc support moved out of Jambase, as jam is its only
|
||||
likely user.
|
||||
|
||||
Jambase now purturbs library sources with a "grist" of
|
||||
SOURCE_GRIST.
|
||||
|
||||
4.2.3. Misc:
|
||||
|
||||
The names of the default rules defined in Jambase have been
|
||||
lowercased and un-abbreviated, to be more imake(1) like.
|
||||
|
||||
The Jambase has been reorganized and sorted, with VMS and NT
|
||||
support moved in from their own files.
|
||||
|
||||
The Jambase has been relocated on UNIX from /usr/local/lib/jam
|
||||
to /usr/local/lib.
|
||||
|
||||
4.3. Jam changes (see jam.1)
|
||||
|
||||
4.3.1. Flags:
|
||||
|
||||
New -a (anyhow) flag: means build everything.
|
||||
|
||||
New -j<x> flag: run jobs in parallel.
|
||||
|
||||
Old -t now rebuilds the touched target, rather that just the
|
||||
target's parents.
|
||||
|
||||
-n now implies -d2, so that you see what's happening. The
|
||||
debug level can be subsequently overridden.
|
||||
|
||||
New -v to dump version.
|
||||
|
||||
4.3.2. Rules:
|
||||
|
||||
New ALWAYS rule behaves like -t: always builds target.
|
||||
|
||||
New EXIT rule makes it possible to raise a fatal error.
|
||||
|
||||
New LEAVES rule which say target depends only on the update
|
||||
times of the leaf sources.
|
||||
|
||||
New NOUPDATE rule says built targets only if they don't exist.
|
||||
|
||||
NOTIME has been renamed NOTFILE, to more accurately reflect its
|
||||
meaning (it says a target is not to be bound to a file).
|
||||
|
||||
4.3.3. Variables:
|
||||
|
||||
New special variable JAMSHELL: argv template for command execution
|
||||
shell.
|
||||
|
||||
Variables, both normal and target-specific, can have their
|
||||
value appended with the syntax "var += value" or "var on target
|
||||
+= value".
|
||||
|
||||
"?=" is now synonymous with "default =".
|
||||
|
||||
Imported enviroment variable values are now split at blanks
|
||||
(:'s if the variable name ends in PATH), so that they become
|
||||
proper list values.
|
||||
|
||||
4.3.4. Misc:
|
||||
|
||||
Files to be sourced with "include" are now bound first, so
|
||||
$(SEARCH) and $(LOCATE) affect them. They still can't be
|
||||
built, though.
|
||||
|
||||
New modifier on "actions": "existing" causes $(>) to expand
|
||||
only those files that currently exist.
|
||||
|
||||
4.3.5. Bug fixes:
|
||||
|
||||
When scanning tokens known to be argument lists (such as the
|
||||
arguments to rule invocations and variable assignment), the
|
||||
parser now tells the scanner to ignore alphabetic keywords, as
|
||||
all such lists terminate with punctuation keywords (like : or
|
||||
;). This way, alphabetic keywords don't need to be quoted when
|
||||
they appear as arguments.
|
||||
|
||||
The scanner has been fixed to handle oversized tokens,
|
||||
unterminated quotes, unterminated action blocks, and tokens
|
||||
abutting EOF (i.e. a token with no white space before EOF).
|
||||
|
||||
The progress report "...on xth target..." used to count all
|
||||
targets, rather than just those with updating actions. Since
|
||||
the original pronouncement of targets to be udpated included
|
||||
only those with updating actions, the progress report has been
|
||||
changed to match.
|
||||
|
||||
'If' conditionals now must be single arguments. Previously,
|
||||
they could be zero or more arguments, which didn't make much
|
||||
sense, and made things like 'foo == bar' true. The comparison
|
||||
operator is '=', and '==' just looked like the second of three
|
||||
arguments in the unary "non-empty argument list" conditional.
|
||||
|
||||
Header files indirectly including themselves were mistakenly
|
||||
reported as being dependent on themselves. Recursing through
|
||||
header file dependencies is now done after determining the fate
|
||||
of the target.
|
||||
|
||||
The variable expansion support was expanding $(X)$(UNDEF) as if
|
||||
it were $(X). It now expands to an empty list, like it
|
||||
should.
|
||||
|
||||
The UNIX version of file_build() didn't handle "dir/.suffix"
|
||||
right. Now it does.
|
||||
|
||||
The VMS command buffer was assumed to be as large as 1024 bytes,
|
||||
which isn't the case everywhere as it is related to some weird
|
||||
quota. It has been lowered to 256.
|
||||
|
||||
$(>) and $(<) wouldn't expand in action blocks if the targets
|
||||
were marked with NOTIME. Now they expand properly.
|
||||
|
||||
Malloc() return values are now checked.
|
||||
|
||||
The variable expansion routine var_expand() is now a little
|
||||
faster, by taking a few often needed shortcuts.
|
||||
|
||||
The VMS version of file_build() used the wrong length when
|
||||
re-rooting file names that already had directory compoents.
|
||||
This was fixed.
|
||||
|
||||
Various tracing adjustments were made.
|
||||
|
||||
5. Limitations/Known Bugs
|
||||
|
||||
The new Windows/NT support has only been marginally tested. It
|
||||
is dependent on certain variables being set depending on which
|
||||
compiler you are using. You'll need to look in the file
|
||||
Jambase and see what variables are expected to be set.
|
||||
|
||||
The VMS support has been tested, courtesy of the DEC guest
|
||||
machine, but has not been hammered fully in release 2.0. It
|
||||
was used quite a bit in Jam 1.0.
|
||||
|
||||
Jam clean when there is nothing to clean claims it is updating
|
||||
a target.
|
||||
|
||||
Because the include statement works by pushing a new file in
|
||||
the input stream of the scanner rather than recursively
|
||||
invoking the parser on the new file, multiple include
|
||||
statements in a rule's procedure causes the files to be
|
||||
included in reverse order.
|
||||
|
||||
If the include statement appears inside an if block, the
|
||||
parser's attempt to find the else will cause the text of the
|
||||
included file to appear after the first token following the
|
||||
statement block. This is rarely what is intended.
|
||||
|
||||
In a rule's actions, only $(<) and $(>) refer to the bound file
|
||||
names: all other variable references get the unbound names.
|
||||
This is a pain for $(NEEDLIBS), because it means that library
|
||||
path can't be bound using $(SEARCH) and $(LOCATE).
|
||||
|
||||
With the -j flag, errors from failed commands can get
|
||||
staggeringly mixed up. Also, because targets tend to get built
|
||||
in a quickest-first ordering, dependency information must be
|
||||
quite exact. Finally, beware of parallelizing commands that
|
||||
drop fixed-named files into the current directory, like yacc(1)
|
||||
does.
|
||||
|
||||
A poorly set $(JAMSHELL) is likely to result in silent
|
||||
failure.
|
||||
84
historic/jam/src/command.c
Normal file
84
historic/jam/src/command.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* command.c - maintain lists of commands
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "variable.h"
|
||||
# include "rules.h"
|
||||
|
||||
# include "command.h"
|
||||
# include <limits.h>
|
||||
|
||||
/*
|
||||
* cmd_new() - return a new CMD or 0 if too many args
|
||||
*/
|
||||
|
||||
CMD *
|
||||
cmd_new(
|
||||
RULE *rule,
|
||||
LIST *targets,
|
||||
LIST *sources,
|
||||
LIST *shell )
|
||||
{
|
||||
CMD *cmd = (CMD *)malloc( sizeof( CMD ) );
|
||||
/* lift line-length limitation entirely when JAMSHELL is just "%" */
|
||||
int expand_line = ( shell && !strcmp(shell->string,"%") && !list_next(shell) );
|
||||
int max_line = MAXLINE;
|
||||
int allocated = -1;
|
||||
|
||||
cmd->rule = rule;
|
||||
cmd->shell = shell;
|
||||
cmd->next = 0;
|
||||
|
||||
lol_init( &cmd->args );
|
||||
lol_add( &cmd->args, targets );
|
||||
lol_add( &cmd->args, sources );
|
||||
cmd->buf = 0;
|
||||
|
||||
do
|
||||
{
|
||||
free(cmd->buf); /* free any buffer from previous iteration */
|
||||
|
||||
cmd->buf = (char*)malloc(max_line + 1);
|
||||
|
||||
if (cmd->buf == 0)
|
||||
break;
|
||||
|
||||
allocated = var_string( rule->actions->command, cmd->buf, max_line, &cmd->args );
|
||||
|
||||
max_line = max_line * 2;
|
||||
}
|
||||
while( expand_line && allocated < 0 && max_line < INT_MAX / 2 );
|
||||
|
||||
/* Bail if the result won't fit in MAXLINE */
|
||||
/* We don't free targets/sources/shell if bailing. */
|
||||
if( allocated < 0 )
|
||||
{
|
||||
cmd_free( cmd );
|
||||
cmd = 0;
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* cmd_free() - free a CMD
|
||||
*/
|
||||
|
||||
void
|
||||
cmd_free( CMD *cmd )
|
||||
{
|
||||
lol_free( &cmd->args );
|
||||
list_free( cmd->shell );
|
||||
free( cmd->buf );
|
||||
free( (char *)cmd );
|
||||
}
|
||||
58
historic/jam/src/command.h
Normal file
58
historic/jam/src/command.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 1994 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* command.h - the CMD structure and routines to manipulate them
|
||||
*
|
||||
* Both ACTION and CMD contain a rule, targets, and sources. An
|
||||
* ACTION describes a rule to be applied to the given targets and
|
||||
* sources; a CMD is what actually gets executed by the shell. The
|
||||
* differences are due to:
|
||||
*
|
||||
* ACTIONS must be combined if 'actions together' is given.
|
||||
* ACTIONS must be split if 'actions piecemeal' is given.
|
||||
* ACTIONS must have current sources omitted for 'actions updated'.
|
||||
*
|
||||
* The CMD datatype holds a single command that is to be executed
|
||||
* against a target, and they can chain together to represent the
|
||||
* full collection of commands used to update a target.
|
||||
*
|
||||
* Structures:
|
||||
*
|
||||
* CMD - an action, ready to be formatted into a buffer and executed
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* cmd_new() - return a new CMD or 0 if too many args
|
||||
* cmd_free() - delete CMD and its parts
|
||||
* cmd_next() - walk the CMD chain
|
||||
*/
|
||||
|
||||
/*
|
||||
* CMD - an action, ready to be formatted into a buffer and executed
|
||||
*/
|
||||
|
||||
typedef struct _cmd CMD;
|
||||
|
||||
struct _cmd
|
||||
{
|
||||
CMD *next;
|
||||
CMD *tail; /* valid on in head */
|
||||
RULE *rule; /* rule->actions contains shell script */
|
||||
LIST *shell; /* $(SHELL) value */
|
||||
LOL args; /* LISTs for $(<), $(>) */
|
||||
char* buf; /* actual commands */
|
||||
} ;
|
||||
|
||||
CMD *cmd_new(
|
||||
RULE *rule, /* rule (referenced) */
|
||||
LIST *targets, /* $(<) (freed) */
|
||||
LIST *sources, /* $(>) (freed) */
|
||||
LIST *shell ); /* $(SHELL) (freed) */
|
||||
|
||||
void cmd_free( CMD *cmd );
|
||||
|
||||
# define cmd_next( c ) ((c)->next)
|
||||
17
historic/jam/src/common.mk
Normal file
17
historic/jam/src/common.mk
Normal file
@@ -0,0 +1,17 @@
|
||||
# Common Makefile rules
|
||||
#
|
||||
|
||||
# the Jam sources needed to build "jam0"
|
||||
#
|
||||
SOURCES = \
|
||||
command.c compile.c execnt.c execunix.c execvms.c expand.c \
|
||||
filent.c fileos2.c fileunix.c filevms.c glob.c hash.c \
|
||||
hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c \
|
||||
newstr.c option.c parse.c pathunix.c pathvms.c regexp.c \
|
||||
rules.c scan.c search.c subst.c timestamp.c variable.c modules.c \
|
||||
strings.c filesys.c
|
||||
|
||||
# the bootstrap "jam0" build tool
|
||||
#
|
||||
jam0:
|
||||
$(CC) $(TARGET) $(CFLAGS) $(SOURCES) $(LINKLIBS)
|
||||
1390
historic/jam/src/compile.c
Normal file
1390
historic/jam/src/compile.c
Normal file
File diff suppressed because it is too large
Load Diff
74
historic/jam/src/compile.h
Normal file
74
historic/jam/src/compile.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
#ifndef COMPILE_DWA20011022_H
|
||||
# define COMPILE_DWA20011022_H
|
||||
|
||||
# include "frames.h"
|
||||
# include "parse.h"
|
||||
# include "regexp.h"
|
||||
|
||||
/*
|
||||
* compile.h - compile parsed jam statements
|
||||
*/
|
||||
|
||||
void compile_builtins();
|
||||
|
||||
LIST *compile_append( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_foreach( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_if( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_include( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_list( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_local( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_module( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_null( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_rule( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_rules( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_set( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_set_module( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_setcomp( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_setexec( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_settings( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_switch( PARSE *parse, FRAME *frame );
|
||||
LIST *compile_while( PARSE *parse, FRAME *frame );
|
||||
|
||||
LIST *evaluate_rule( char *rulename, FRAME *frame );
|
||||
|
||||
regexp* regex_compile( const char* pattern );
|
||||
|
||||
void profile_dump();
|
||||
|
||||
/* Flags for compile_set(), etc */
|
||||
|
||||
# define ASSIGN_SET 0x00 /* = assign variable */
|
||||
# define ASSIGN_APPEND 0x01 /* += append variable */
|
||||
# define ASSIGN_DEFAULT 0x02 /* set only if unset */
|
||||
|
||||
/* Flags for compile_setexec() */
|
||||
|
||||
# define EXEC_UPDATED 0x01 /* executes updated */
|
||||
# define EXEC_TOGETHER 0x02 /* executes together */
|
||||
# define EXEC_IGNORE 0x04 /* executes ignore */
|
||||
# define EXEC_QUIETLY 0x08 /* executes quietly */
|
||||
# define EXEC_PIECEMEAL 0x10 /* executes piecemeal */
|
||||
# define EXEC_EXISTING 0x20 /* executes existing */
|
||||
|
||||
/* Conditions for compile_if() */
|
||||
|
||||
# define COND_NOT 0 /* ! cond */
|
||||
# define COND_AND 1 /* cond && cond */
|
||||
# define COND_OR 2 /* cond || cond */
|
||||
|
||||
# define COND_EXISTS 3 /* arg */
|
||||
# define COND_EQUALS 4 /* arg = arg */
|
||||
# define COND_NOTEQ 5 /* arg != arg */
|
||||
# define COND_LESS 6 /* arg < arg */
|
||||
# define COND_LESSEQ 7 /* arg <= arg */
|
||||
# define COND_MORE 8 /* arg > arg */
|
||||
# define COND_MOREEQ 9 /* arg >= arg */
|
||||
# define COND_IN 10 /* arg in arg */
|
||||
|
||||
#endif // COMPILE_DWA20011022_H
|
||||
10
historic/jam/src/debugjam0.bat
Executable file
10
historic/jam/src/debugjam0.bat
Executable file
@@ -0,0 +1,10 @@
|
||||
bash .\yyacc jamgram.y jamgramtab.h jamgram.yy
|
||||
set VISUALC=c:\tools\msvc6\vc98
|
||||
set JAM_TOOLSET=VISUALC
|
||||
set YACC="bison -t -d -l -v --debug --yacc"
|
||||
set YACCFILES=y.tab
|
||||
set CFLAGS="/GZ /Zi /MLd -DNT" CCFLAGS="/GZ /Zi /MLd"
|
||||
set LINKLIBS="%VISUALC%\lib\advapi32.lib %VISUALC%\lib\oldnames.lib c:\tools\msvc6\vc98\lib\gdi32.lib %VISUALC%\lib\user32.lib %VISUALC%\lib\kernel32.lib"
|
||||
set LINKFLAGS="/DEBUG"
|
||||
rm -rf bin.ntx86
|
||||
jam0 %*
|
||||
7
historic/jam/src/debugjam0.sh
Normal file
7
historic/jam/src/debugjam0.sh
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
# This script can be used to recover from aborted builds in which Jam has
|
||||
# removed some of its products (e.g. jamgramtab.h) upon failing some action
|
||||
./yyacc jamgram.y jamgramtab.h jamgram.yy
|
||||
export VISUALC=c:\tools\msvc6\vc98
|
||||
export JAM_TOOLSET=VISUALC
|
||||
jam0 -sCCFLAGS="/GZ /Zi /MLd" -sYACC="bison -t -d -l -v --yacc" -sLINKLIBS="c:\tools\msvc6\vc98\lib\advapi32.lib c:\tools\msvc6\vc98\lib\oldnames.lib c:\tools\msvc6\vc98\lib\gdi32.lib c:\tools\msvc6\vc98\lib\user32.lib c:\tools\msvc6\vc98\lib\kernel32.lib" -sLINKFLAGS="/DEBUG"
|
||||
23
historic/jam/src/execcmd.h
Normal file
23
historic/jam/src/execcmd.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* execcmd.h - execute a shell script
|
||||
*
|
||||
* 05/04/94 (seiwald) - async multiprocess interface
|
||||
*/
|
||||
|
||||
void execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status ),
|
||||
void *closure,
|
||||
LIST *shell );
|
||||
|
||||
int execwait();
|
||||
|
||||
# define EXEC_CMD_OK 0
|
||||
# define EXEC_CMD_FAIL 1
|
||||
# define EXEC_CMD_INTR 2
|
||||
69
historic/jam/src/execmac.c
Normal file
69
historic/jam/src/execmac.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "execcmd.h"
|
||||
# include <errno.h>
|
||||
|
||||
# ifdef OS_MAC
|
||||
|
||||
/*
|
||||
* execunix.c - execute a shell script on UNIX
|
||||
*
|
||||
* If $(JAMSHELL) is defined, uses that to formulate execvp().
|
||||
* The default is:
|
||||
*
|
||||
* /bin/sh -c %
|
||||
*
|
||||
* Each word must be an individual element in a jam variable value.
|
||||
*
|
||||
* In $(JAMSHELL), % expands to the command string and ! expands to
|
||||
* the slot number (starting at 1) for multiprocess (-j) invocations.
|
||||
* If $(JAMSHELL) doesn't include a %, it is tacked on as the last
|
||||
* argument.
|
||||
*
|
||||
* Don't just set JAMSHELL to /bin/sh - it won't work!
|
||||
*
|
||||
* External routines:
|
||||
* execcmd() - launch an async command execution
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
*
|
||||
* Internal routines:
|
||||
* onintr() - bump intr to note command interruption
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 05/04/94 (seiwald) - async multiprocess interface
|
||||
* 01/22/95 (seiwald) - $(JAMSHELL) support
|
||||
*/
|
||||
|
||||
/*
|
||||
* execcmd() - launch an async command execution
|
||||
*/
|
||||
|
||||
void
|
||||
execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status ),
|
||||
void *closure,
|
||||
LIST *shell )
|
||||
{
|
||||
|
||||
printf( "%s", string );
|
||||
(*func)( closure, EXEC_CMD_OK );
|
||||
}
|
||||
|
||||
/*
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
*/
|
||||
|
||||
int
|
||||
execwait()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
# endif /* OS_MAC */
|
||||
651
historic/jam/src/execnt.c
Normal file
651
historic/jam/src/execnt.c
Normal file
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "execcmd.h"
|
||||
# include <errno.h>
|
||||
|
||||
# ifdef USE_EXECNT
|
||||
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h> /* do the ugly deed */
|
||||
# include <process.h>
|
||||
|
||||
# if !defined( __BORLANDC__ ) && !defined( OS_OS2 )
|
||||
# define wait my_wait
|
||||
static int my_wait( int *status );
|
||||
# endif
|
||||
|
||||
/*
|
||||
* execnt.c - execute a shell command on Windows NT and Windows 95/98
|
||||
*
|
||||
* If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp().
|
||||
* The default is:
|
||||
*
|
||||
* /bin/sh -c % [ on UNIX/AmigaOS ]
|
||||
* cmd.exe /c % [ on Windows NT ]
|
||||
*
|
||||
* Each word must be an individual element in a jam variable value.
|
||||
*
|
||||
* In $(JAMSHELL), % expands to the command string and ! expands to
|
||||
* the slot number (starting at 1) for multiprocess (-j) invocations.
|
||||
* If $(JAMSHELL) doesn't include a %, it is tacked on as the last
|
||||
* argument.
|
||||
*
|
||||
* Don't just set JAMSHELL to /bin/sh or cmd.exe - it won't work!
|
||||
*
|
||||
* External routines:
|
||||
* execcmd() - launch an async command execution
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
*
|
||||
* Internal routines:
|
||||
* onintr() - bump intr to note command interruption
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 05/04/94 (seiwald) - async multiprocess interface
|
||||
* 01/22/95 (seiwald) - $(JAMSHELL) support
|
||||
* 06/02/97 (gsar) - full async multiprocess support for Win32
|
||||
*/
|
||||
|
||||
static int intr = 0;
|
||||
static int cmdsrunning = 0;
|
||||
static void (*istat)( int );
|
||||
|
||||
static int is_nt_351 = 0;
|
||||
static int is_win95 = 1;
|
||||
static int is_win95_defined = 0;
|
||||
|
||||
|
||||
static struct
|
||||
{
|
||||
int pid; /* on win32, a real process handle */
|
||||
void (*func)( void *closure, int status );
|
||||
void *closure;
|
||||
char *tempfile;
|
||||
|
||||
} cmdtab[ MAXJOBS ] = {{0}};
|
||||
|
||||
|
||||
static void
|
||||
set_is_win95( void )
|
||||
{
|
||||
OSVERSIONINFO os_info;
|
||||
|
||||
os_info.dwOSVersionInfoSize = sizeof(os_info);
|
||||
os_info.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
|
||||
GetVersionEx( &os_info );
|
||||
|
||||
is_win95 = (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
|
||||
is_win95_defined = 1;
|
||||
|
||||
/* now, test wether we're running Windows 3.51 */
|
||||
/* this is later used to limit the system call command length */
|
||||
if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||||
is_nt_351 = os_info.dwMajorVersion == 3;
|
||||
}
|
||||
|
||||
|
||||
static char**
|
||||
string_to_args( const char* string, int* pcount )
|
||||
{
|
||||
int total = strlen( string );
|
||||
int in_quote = 0,
|
||||
num_args = 0; /* was uninitialized -- dwa */
|
||||
char* line;
|
||||
char* p;
|
||||
char** arg;
|
||||
char** args;
|
||||
|
||||
*pcount = 0;
|
||||
|
||||
/* do not copy trailing newlines, if any */
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = total-1; i > 0; i-- )
|
||||
{
|
||||
if ( string[i] != '\n' && string[i] != '\r' )
|
||||
break;
|
||||
total --;
|
||||
}
|
||||
}
|
||||
|
||||
/* first of all, copy the input string */
|
||||
line = (char*)malloc( total+2 );
|
||||
if (!line)
|
||||
return 0;
|
||||
|
||||
memcpy( line+1, string, total );
|
||||
line[0] = 0;
|
||||
line[total+1] = 0;
|
||||
|
||||
in_quote = 0;
|
||||
for ( p = line+1; p[0]; p++ )
|
||||
{
|
||||
switch (p[0])
|
||||
{
|
||||
case '"':
|
||||
in_quote = !in_quote;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (!in_quote)
|
||||
p[0] = 0;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/* now count the arguments.. */
|
||||
for ( p = line; p < line+total+1; p++ )
|
||||
if ( !p[0] && p[1] )
|
||||
num_args++;
|
||||
|
||||
/* allocate the args array */
|
||||
/* dwa -- did you really mean to allocate only 2 additional bytes? */
|
||||
#if 0 /* was like this */
|
||||
args = (char**)malloc( num_args*sizeof(char*)+2 );
|
||||
#endif
|
||||
args = (char**)malloc( (num_args + 2) * sizeof(char*) );
|
||||
if (!args)
|
||||
{
|
||||
free( line );
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg = args+1;
|
||||
for ( p = line; p < line+total+1; p++ )
|
||||
if ( !p[0] && p[1] )
|
||||
{
|
||||
arg[0] = p+1;
|
||||
arg++;
|
||||
}
|
||||
arg[0] = 0;
|
||||
*pcount = num_args;
|
||||
args[0] = line;
|
||||
return args+1;
|
||||
}
|
||||
|
||||
static void
|
||||
free_args( char** args )
|
||||
{
|
||||
free( args[-1] );
|
||||
free( args-1 );
|
||||
}
|
||||
|
||||
|
||||
/* process a "del" or "erase" command under Windows 95/98 */
|
||||
static int
|
||||
process_del( char* command )
|
||||
{
|
||||
char** arg;
|
||||
char* p = command, *q;
|
||||
int wildcard = 0, result = 0;
|
||||
|
||||
/* first of all, skip the command itself */
|
||||
if ( p[0] == 'd' )
|
||||
p += 3; /* assumes "del..;" */
|
||||
else if ( p[0] == 'e' )
|
||||
p += 5; /* assumes "erase.." */
|
||||
else
|
||||
return 1; /* invalid command */
|
||||
|
||||
/* process all targets independently */
|
||||
for (;;)
|
||||
{
|
||||
/* skip leading spaces */
|
||||
while ( *p && isspace(*p) )
|
||||
p++;
|
||||
|
||||
/* exit if we encounter an end of string */
|
||||
if (!*p)
|
||||
return 0;
|
||||
|
||||
/* ignore toggles/flags */
|
||||
if (*p == '/')
|
||||
{
|
||||
p++;
|
||||
while ( *p && isalnum(*p) )
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int in_quote = 0;
|
||||
int wildcard = 0;
|
||||
int go_on = 1;
|
||||
|
||||
q = p;
|
||||
while (go_on)
|
||||
{
|
||||
switch (*p)
|
||||
{
|
||||
case '"':
|
||||
in_quote = !in_quote;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case '*':
|
||||
if (!in_quote)
|
||||
wildcard = 1;
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
if (in_quote)
|
||||
return 1;
|
||||
/* fall-through */
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
if (!in_quote)
|
||||
{
|
||||
int len = p - q;
|
||||
int result;
|
||||
char* line;
|
||||
|
||||
/* q..p-1 contains the delete argument */
|
||||
if ( len <= 0 )
|
||||
return 1;
|
||||
|
||||
line = (char*)malloc( len+4+1 );
|
||||
if (!line)
|
||||
return 1;
|
||||
|
||||
strncpy( line, "del ", 4 );
|
||||
strncpy( line+4, q, len );
|
||||
line[len+4] = '\0';
|
||||
|
||||
if ( wildcard )
|
||||
result = system( line );
|
||||
else
|
||||
result = !DeleteFile( line+4 );
|
||||
|
||||
free( line );
|
||||
if (result)
|
||||
return 1;
|
||||
|
||||
go_on = 0;
|
||||
}
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
p++;
|
||||
} /* while (go_on) */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* onintr() - bump intr to note command interruption
|
||||
*/
|
||||
|
||||
void
|
||||
onintr( int disp )
|
||||
{
|
||||
intr++;
|
||||
printf( "...interrupted\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
* execcmd() - launch an async command execution
|
||||
*/
|
||||
|
||||
void
|
||||
execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status ),
|
||||
void *closure,
|
||||
LIST *shell )
|
||||
{
|
||||
int pid;
|
||||
int slot;
|
||||
int max_line;
|
||||
int raw_cmd = 0 ;
|
||||
char *argv_static[ MAXARGC + 1 ]; /* +1 for NULL */
|
||||
char **argv = argv_static;
|
||||
char *p;
|
||||
|
||||
/* Check to see if we need to hack around the line-length limitation. */
|
||||
/* Look for a JAMSHELL setting of "%", indicating that the command
|
||||
* should be invoked directly */
|
||||
if ( shell && !strcmp(shell->string,"%") && !list_next(shell) )
|
||||
{
|
||||
raw_cmd = 1;
|
||||
shell = 0;
|
||||
}
|
||||
|
||||
if ( !is_win95_defined )
|
||||
set_is_win95();
|
||||
|
||||
/* Find a slot in the running commands table for this one. */
|
||||
if ( is_win95 )
|
||||
{
|
||||
/* only synchronous spans are supported on Windows 95/98 */
|
||||
slot = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( slot = 0; slot < MAXJOBS; slot++ )
|
||||
if( !cmdtab[ slot ].pid )
|
||||
break;
|
||||
}
|
||||
if( slot == MAXJOBS )
|
||||
{
|
||||
printf( "no slots for child!\n" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
if( !cmdtab[ slot ].tempfile )
|
||||
{
|
||||
char *tempdir;
|
||||
|
||||
if( !( tempdir = getenv( "TEMP" ) ) &&
|
||||
!( tempdir = getenv( "TMP" ) ) )
|
||||
tempdir = "\\temp";
|
||||
|
||||
cmdtab[ slot ].tempfile = malloc( strlen( tempdir ) + 14 );
|
||||
|
||||
sprintf( cmdtab[ slot ].tempfile, "%s\\jamtmp%02d.bat",
|
||||
tempdir, slot );
|
||||
}
|
||||
|
||||
/* Trim leading, ending white space */
|
||||
|
||||
while( isspace( *string ) )
|
||||
++string;
|
||||
|
||||
p = strchr( string, '\n' );
|
||||
|
||||
while( p && isspace( *p ) )
|
||||
++p;
|
||||
|
||||
/* on Windows NT 3.51, the maximul line length is 996 bytes !! */
|
||||
/* while it's much bigger NT 4 and 2k */
|
||||
max_line = is_nt_351 ? 996 : MAXLINE;
|
||||
|
||||
/* If multi line, or too long, or JAMSHELL is set, write to bat file. */
|
||||
/* Otherwise, exec directly. */
|
||||
/* Frankly, if it is a single long line I don't think the */
|
||||
/* command interpreter will do any better -- it will fail. */
|
||||
|
||||
if( p && *p || !raw_cmd && strlen( string ) > max_line || shell )
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
/* Write command to bat file. */
|
||||
|
||||
f = fopen( cmdtab[ slot ].tempfile, "w" );
|
||||
fputs( string, f );
|
||||
fclose( f );
|
||||
|
||||
string = cmdtab[ slot ].tempfile;
|
||||
}
|
||||
|
||||
/* Forumulate argv */
|
||||
/* If shell was defined, be prepared for % and ! subs. */
|
||||
/* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */
|
||||
|
||||
if( shell )
|
||||
{
|
||||
int i;
|
||||
char jobno[4];
|
||||
int gotpercent = 0;
|
||||
|
||||
sprintf( jobno, "%d", slot + 1 );
|
||||
|
||||
for( i = 0; shell && i < MAXARGC; i++, shell = list_next( shell ) )
|
||||
{
|
||||
switch( shell->string[0] )
|
||||
{
|
||||
case '%': argv[i] = string; gotpercent++; break;
|
||||
case '!': argv[i] = jobno; break;
|
||||
default: argv[i] = shell->string;
|
||||
}
|
||||
if( DEBUG_EXECCMD )
|
||||
printf( "argv[%d] = '%s'\n", i, argv[i] );
|
||||
}
|
||||
|
||||
if( !gotpercent )
|
||||
argv[i++] = string;
|
||||
|
||||
argv[i] = 0;
|
||||
}
|
||||
else if (raw_cmd)
|
||||
{
|
||||
int ignored;
|
||||
argv = string_to_args(string, &ignored);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* don't worry, this is ignored on Win95/98, see later.. */
|
||||
argv[0] = "cmd.exe";
|
||||
argv[1] = "/Q/C"; /* anything more is non-portable */
|
||||
argv[2] = string;
|
||||
argv[3] = 0;
|
||||
}
|
||||
|
||||
/* Catch interrupts whenever commands are running. */
|
||||
|
||||
if( !cmdsrunning++ )
|
||||
istat = signal( SIGINT, onintr );
|
||||
|
||||
/* Start the command */
|
||||
|
||||
/* on Win95, we only do a synchronous call */
|
||||
if ( is_win95 )
|
||||
{
|
||||
static const char* hard_coded[] =
|
||||
{
|
||||
"del", "erase", "copy", "mkdir", "rmdir", "cls", "dir",
|
||||
"ren", "rename", "move", 0
|
||||
};
|
||||
|
||||
const char** keyword;
|
||||
int len, spawn = 1;
|
||||
int result;
|
||||
|
||||
for ( keyword = hard_coded; keyword[0]; keyword++ )
|
||||
{
|
||||
len = strlen( keyword[0] );
|
||||
if ( strnicmp( string, keyword[0], len ) == 0 &&
|
||||
!isalnum(string[len]) )
|
||||
{
|
||||
/* this is one of the hard coded symbols, use 'system' to run */
|
||||
/* them.. except for "del"/"erase" */
|
||||
if ( keyword - hard_coded < 2 )
|
||||
result = process_del( string );
|
||||
else
|
||||
result = system( string );
|
||||
|
||||
spawn = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (spawn)
|
||||
{
|
||||
char** args;
|
||||
int num_args;
|
||||
|
||||
/* convert the string into an array of arguments */
|
||||
/* we need to take care of double quotes !! */
|
||||
args = string_to_args( string, &num_args );
|
||||
if ( args )
|
||||
{
|
||||
#if 0
|
||||
char** arg;
|
||||
fprintf( stderr, "%s: ", args[0] );
|
||||
arg = args+1;
|
||||
while ( arg[0] )
|
||||
{
|
||||
fprintf( stderr, " {%s}", arg[0] );
|
||||
arg++;
|
||||
}
|
||||
fprintf( stderr, "\n" );
|
||||
#endif
|
||||
result = spawnvp( P_WAIT, args[0], args );
|
||||
free_args( args );
|
||||
}
|
||||
else
|
||||
result = 1;
|
||||
}
|
||||
func( closure, result ? EXEC_CMD_FAIL : EXEC_CMD_OK );
|
||||
return;
|
||||
}
|
||||
|
||||
/* the rest is for Windows NT only */
|
||||
if( ( pid = spawnvp( P_NOWAIT, argv[0], argv ) ) == -1 )
|
||||
{
|
||||
perror( "spawn" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
/* Save the operation for execwait() to find. */
|
||||
|
||||
cmdtab[ slot ].pid = pid;
|
||||
cmdtab[ slot ].func = func;
|
||||
cmdtab[ slot ].closure = closure;
|
||||
|
||||
/* Wait until we're under the limit of concurrent commands. */
|
||||
/* Don't trust globs.jobs alone. */
|
||||
|
||||
while( cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs )
|
||||
if( !execwait() )
|
||||
break;
|
||||
|
||||
if (argv != argv_static)
|
||||
{
|
||||
free_args(argv);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
*/
|
||||
|
||||
int
|
||||
execwait()
|
||||
{
|
||||
int i;
|
||||
int status, w;
|
||||
int rstat;
|
||||
|
||||
/* Handle naive make1() which doesn't know if cmds are running. */
|
||||
|
||||
if( !cmdsrunning )
|
||||
return 0;
|
||||
|
||||
if ( is_win95 )
|
||||
return 0;
|
||||
|
||||
/* Pick up process pid and status */
|
||||
|
||||
while( ( w = wait( &status ) ) == -1 && errno == EINTR )
|
||||
;
|
||||
|
||||
if( w == -1 )
|
||||
{
|
||||
printf( "child process(es) lost!\n" );
|
||||
perror("wait");
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
/* Find the process in the cmdtab. */
|
||||
|
||||
for( i = 0; i < MAXJOBS; i++ )
|
||||
if( w == cmdtab[ i ].pid )
|
||||
break;
|
||||
|
||||
if( i == MAXJOBS )
|
||||
{
|
||||
printf( "waif child found!\n" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
/* Drive the completion */
|
||||
|
||||
if( !--cmdsrunning )
|
||||
signal( SIGINT, istat );
|
||||
|
||||
if( intr )
|
||||
rstat = EXEC_CMD_INTR;
|
||||
else if( w == -1 || status != 0 )
|
||||
rstat = EXEC_CMD_FAIL;
|
||||
else
|
||||
rstat = EXEC_CMD_OK;
|
||||
|
||||
cmdtab[ i ].pid = 0;
|
||||
|
||||
(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# if !defined( __BORLANDC__ )
|
||||
|
||||
static int
|
||||
my_wait( int *status )
|
||||
{
|
||||
int i, num_active = 0;
|
||||
DWORD exitcode, waitcode;
|
||||
static HANDLE *active_handles = 0;
|
||||
|
||||
if (!active_handles)
|
||||
active_handles = (HANDLE *)malloc(globs.jobs * sizeof(HANDLE) );
|
||||
|
||||
/* first see if any non-waited-for processes are dead,
|
||||
* and return if so.
|
||||
*/
|
||||
for ( i = 0; i < globs.jobs; i++ ) {
|
||||
if ( cmdtab[i].pid ) {
|
||||
if ( GetExitCodeProcess((HANDLE)cmdtab[i].pid, &exitcode) ) {
|
||||
if ( exitcode == STILL_ACTIVE )
|
||||
active_handles[num_active++] = (HANDLE)cmdtab[i].pid;
|
||||
else {
|
||||
CloseHandle((HANDLE)cmdtab[i].pid);
|
||||
*status = (int)((exitcode & 0xff) << 8);
|
||||
return cmdtab[i].pid;
|
||||
}
|
||||
}
|
||||
else
|
||||
goto FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* if a child exists, wait for it to die */
|
||||
if ( !num_active ) {
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
waitcode = WaitForMultipleObjects( num_active,
|
||||
active_handles,
|
||||
FALSE,
|
||||
INFINITE );
|
||||
if ( waitcode != WAIT_FAILED ) {
|
||||
if ( waitcode >= WAIT_ABANDONED_0
|
||||
&& waitcode < WAIT_ABANDONED_0 + num_active )
|
||||
i = waitcode - WAIT_ABANDONED_0;
|
||||
else
|
||||
i = waitcode - WAIT_OBJECT_0;
|
||||
if ( GetExitCodeProcess(active_handles[i], &exitcode) ) {
|
||||
CloseHandle(active_handles[i]);
|
||||
*status = (int)((exitcode & 0xff) << 8);
|
||||
return (int)active_handles[i];
|
||||
}
|
||||
}
|
||||
|
||||
FAILED:
|
||||
errno = GetLastError();
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
# endif /* !__BORLANDC__ */
|
||||
|
||||
# endif /* USE_EXECNT */
|
||||
370
historic/jam/src/execunix.c
Normal file
370
historic/jam/src/execunix.c
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "execcmd.h"
|
||||
# include <errno.h>
|
||||
|
||||
# ifdef USE_EXECUNIX
|
||||
|
||||
# ifdef NO_VFORK
|
||||
# define vfork() fork()
|
||||
# endif
|
||||
|
||||
# if defined( OS_NT ) || defined( OS_OS2 )
|
||||
|
||||
# define USE_EXECNT
|
||||
|
||||
# include <process.h>
|
||||
|
||||
# if !defined( __BORLANDC__ ) && !defined( OS_OS2 )
|
||||
# define wait my_wait
|
||||
static int my_wait( int *status );
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
/*
|
||||
* execunix.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS
|
||||
*
|
||||
* If $(JAMSHELL) is defined, uses that to formulate execvp()/spawnvp().
|
||||
* The default is:
|
||||
*
|
||||
* /bin/sh -c % [ on UNIX/AmigaOS ]
|
||||
* cmd.exe /c % [ on OS2/WinNT ]
|
||||
*
|
||||
* Each word must be an individual element in a jam variable value.
|
||||
*
|
||||
* In $(JAMSHELL), % expands to the command string and ! expands to
|
||||
* the slot number (starting at 1) for multiprocess (-j) invocations.
|
||||
* If $(JAMSHELL) doesn't include a %, it is tacked on as the last
|
||||
* argument.
|
||||
*
|
||||
* Don't just set JAMSHELL to /bin/sh or cmd.exe - it won't work!
|
||||
*
|
||||
* External routines:
|
||||
* execcmd() - launch an async command execution
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
*
|
||||
* Internal routines:
|
||||
* onintr() - bump intr to note command interruption
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 05/04/94 (seiwald) - async multiprocess interface
|
||||
* 01/22/95 (seiwald) - $(JAMSHELL) support
|
||||
* 06/02/97 (gsar) - full async multiprocess support for Win32
|
||||
*/
|
||||
|
||||
static int intr = 0;
|
||||
static int cmdsrunning = 0;
|
||||
static void (*istat)( int );
|
||||
|
||||
static struct
|
||||
{
|
||||
int pid; /* on win32, a real process handle */
|
||||
void (*func)( void *closure, int status );
|
||||
void *closure;
|
||||
|
||||
# ifdef USE_EXECNT
|
||||
char *tempfile;
|
||||
# endif
|
||||
|
||||
} cmdtab[ MAXJOBS ] = {{0}};
|
||||
|
||||
/*
|
||||
* onintr() - bump intr to note command interruption
|
||||
*/
|
||||
|
||||
void
|
||||
onintr( int disp )
|
||||
{
|
||||
intr++;
|
||||
printf( "...interrupted\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
* execcmd() - launch an async command execution
|
||||
*/
|
||||
|
||||
void
|
||||
execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status ),
|
||||
void *closure,
|
||||
LIST *shell )
|
||||
{
|
||||
int pid;
|
||||
int slot;
|
||||
char *argv[ MAXARGC + 1 ]; /* +1 for NULL */
|
||||
|
||||
# ifdef USE_EXECNT
|
||||
char *p;
|
||||
# endif
|
||||
|
||||
/* Find a slot in the running commands table for this one. */
|
||||
|
||||
for( slot = 0; slot < MAXJOBS; slot++ )
|
||||
if( !cmdtab[ slot ].pid )
|
||||
break;
|
||||
|
||||
if( slot == MAXJOBS )
|
||||
{
|
||||
printf( "no slots for child!\n" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
# ifdef USE_EXECNT
|
||||
if( !cmdtab[ slot ].tempfile )
|
||||
{
|
||||
char *tempdir;
|
||||
|
||||
if( !( tempdir = getenv( "TEMP" ) ) &&
|
||||
!( tempdir = getenv( "TMP" ) ) )
|
||||
tempdir = "\\temp";
|
||||
|
||||
cmdtab[ slot ].tempfile = malloc( strlen( tempdir ) + 14 );
|
||||
|
||||
sprintf( cmdtab[ slot ].tempfile, "%s\\jamtmp%02d.bat",
|
||||
tempdir, slot );
|
||||
}
|
||||
|
||||
/* Trim leading, ending white space */
|
||||
|
||||
while( isspace( *string ) )
|
||||
++string;
|
||||
|
||||
p = strchr( string, '\n' );
|
||||
|
||||
while( p && isspace( *p ) )
|
||||
++p;
|
||||
|
||||
/* If multi line, or too long, or JAMSHELL is set, write to bat file. */
|
||||
/* Otherwise, exec directly. */
|
||||
/* Frankly, if it is a single long line I don't think the */
|
||||
/* command interpreter will do any better -- it will fail. */
|
||||
|
||||
if( p && *p || strlen( string ) > MAXLINE || shell )
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
/* Write command to bat file. */
|
||||
|
||||
f = fopen( cmdtab[ slot ].tempfile, "w" );
|
||||
fputs( string, f );
|
||||
fclose( f );
|
||||
|
||||
string = cmdtab[ slot ].tempfile;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Forumulate argv */
|
||||
/* If shell was defined, be prepared for % and ! subs. */
|
||||
/* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */
|
||||
|
||||
if( shell )
|
||||
{
|
||||
int i;
|
||||
char jobno[4];
|
||||
int gotpercent = 0;
|
||||
|
||||
sprintf( jobno, "%d", slot + 1 );
|
||||
|
||||
for( i = 0; shell && i < MAXARGC; i++, shell = list_next( shell ) )
|
||||
{
|
||||
switch( shell->string[0] )
|
||||
{
|
||||
case '%': argv[i] = string; gotpercent++; break;
|
||||
case '!': argv[i] = jobno; break;
|
||||
default: argv[i] = shell->string;
|
||||
}
|
||||
if( DEBUG_EXECCMD )
|
||||
printf( "argv[%d] = '%s'\n", i, argv[i] );
|
||||
}
|
||||
|
||||
if( !gotpercent )
|
||||
argv[i++] = string;
|
||||
|
||||
argv[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
# ifdef USE_EXECNT
|
||||
argv[0] = "cmd.exe";
|
||||
argv[1] = "/Q/C"; /* anything more is non-portable */
|
||||
# else
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
# endif
|
||||
argv[2] = string;
|
||||
argv[3] = 0;
|
||||
}
|
||||
|
||||
/* Catch interrupts whenever commands are running. */
|
||||
|
||||
if( !cmdsrunning++ )
|
||||
istat = signal( SIGINT, onintr );
|
||||
|
||||
/* Start the command */
|
||||
|
||||
# ifdef USE_EXECNT
|
||||
if( ( pid = spawnvp( P_NOWAIT, argv[0], argv ) ) == -1 )
|
||||
{
|
||||
perror( "spawn" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
# else
|
||||
if ((pid = vfork()) == 0)
|
||||
{
|
||||
execvp( argv[0], argv );
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
if( pid == -1 )
|
||||
{
|
||||
perror( "vfork" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
# endif
|
||||
/* Save the operation for execwait() to find. */
|
||||
|
||||
cmdtab[ slot ].pid = pid;
|
||||
cmdtab[ slot ].func = func;
|
||||
cmdtab[ slot ].closure = closure;
|
||||
|
||||
/* Wait until we're under the limit of concurrent commands. */
|
||||
/* Don't trust globs.jobs alone. */
|
||||
|
||||
while( cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs )
|
||||
if( !execwait() )
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
*/
|
||||
|
||||
int
|
||||
execwait()
|
||||
{
|
||||
int i;
|
||||
int status, w;
|
||||
int rstat;
|
||||
|
||||
/* Handle naive make1() which doesn't know if cmds are running. */
|
||||
|
||||
if( !cmdsrunning )
|
||||
return 0;
|
||||
|
||||
/* Pick up process pid and status */
|
||||
|
||||
while( ( w = wait( &status ) ) == -1 && errno == EINTR )
|
||||
;
|
||||
|
||||
if( w == -1 )
|
||||
{
|
||||
printf( "child process(es) lost!\n" );
|
||||
perror("wait");
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
/* Find the process in the cmdtab. */
|
||||
|
||||
for( i = 0; i < MAXJOBS; i++ )
|
||||
if( w == cmdtab[ i ].pid )
|
||||
break;
|
||||
|
||||
if( i == MAXJOBS )
|
||||
{
|
||||
printf( "waif child found!\n" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
/* Drive the completion */
|
||||
|
||||
if( !--cmdsrunning )
|
||||
signal( SIGINT, istat );
|
||||
|
||||
if( intr )
|
||||
rstat = EXEC_CMD_INTR;
|
||||
else if( w == -1 || status != 0 )
|
||||
rstat = EXEC_CMD_FAIL;
|
||||
else
|
||||
rstat = EXEC_CMD_OK;
|
||||
|
||||
cmdtab[ i ].pid = 0;
|
||||
|
||||
(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# if defined( OS_NT ) && !defined( __BORLANDC__ )
|
||||
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
|
||||
# include <windows.h> /* do the ugly deed */
|
||||
|
||||
static int
|
||||
my_wait( int *status )
|
||||
{
|
||||
int i, num_active = 0;
|
||||
DWORD exitcode, waitcode;
|
||||
static HANDLE *active_handles = 0;
|
||||
|
||||
if (!active_handles)
|
||||
active_handles = (HANDLE *)malloc(globs.jobs * sizeof(HANDLE) );
|
||||
|
||||
/* first see if any non-waited-for processes are dead,
|
||||
* and return if so.
|
||||
*/
|
||||
for ( i = 0; i < globs.jobs; i++ ) {
|
||||
if ( cmdtab[i].pid ) {
|
||||
if ( GetExitCodeProcess((HANDLE)cmdtab[i].pid, &exitcode) ) {
|
||||
if ( exitcode == STILL_ACTIVE )
|
||||
active_handles[num_active++] = (HANDLE)cmdtab[i].pid;
|
||||
else {
|
||||
CloseHandle((HANDLE)cmdtab[i].pid);
|
||||
*status = (int)((exitcode & 0xff) << 8);
|
||||
return cmdtab[i].pid;
|
||||
}
|
||||
}
|
||||
else
|
||||
goto FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* if a child exists, wait for it to die */
|
||||
if ( !num_active ) {
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
waitcode = WaitForMultipleObjects( num_active,
|
||||
active_handles,
|
||||
FALSE,
|
||||
INFINITE );
|
||||
if ( waitcode != WAIT_FAILED ) {
|
||||
if ( waitcode >= WAIT_ABANDONED_0
|
||||
&& waitcode < WAIT_ABANDONED_0 + num_active )
|
||||
i = waitcode - WAIT_ABANDONED_0;
|
||||
else
|
||||
i = waitcode - WAIT_OBJECT_0;
|
||||
if ( GetExitCodeProcess(active_handles[i], &exitcode) ) {
|
||||
CloseHandle(active_handles[i]);
|
||||
*status = (int)((exitcode & 0xff) << 8);
|
||||
return (int)active_handles[i];
|
||||
}
|
||||
}
|
||||
|
||||
FAILED:
|
||||
errno = GetLastError();
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
# endif /* NT && !__BORLANDC__ */
|
||||
|
||||
# endif /* USE_EXECUNIX */
|
||||
167
historic/jam/src/execvms.c
Normal file
167
historic/jam/src/execvms.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "execcmd.h"
|
||||
|
||||
# ifdef OS_VMS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <iodef.h>
|
||||
#include <ssdef.h>
|
||||
#include <descrip.h>
|
||||
#include <dvidef.h>
|
||||
#include <clidef.h>
|
||||
|
||||
/*
|
||||
* execvms.c - execute a shell script, ala VMS
|
||||
*
|
||||
* The approach is this:
|
||||
*
|
||||
* If the command is a single line, and shorter than WRTLEN (what we
|
||||
* believe to be the maximum line length), we just system() it.
|
||||
*
|
||||
* If the command is multi-line, or longer than WRTLEN, we write the
|
||||
* command block to a temp file, splitting long lines (using "-" at
|
||||
* the end of the line to indicate contiuation), and then source that
|
||||
* temp file. We use special logic to make sure we don't continue in
|
||||
* the middle of a quoted string.
|
||||
*
|
||||
* 05/04/94 (seiwald) - async multiprocess interface; noop on VMS
|
||||
* 12/20/96 (seiwald) - rewritten to handle multi-line commands well
|
||||
* 01/14/96 (seiwald) - don't put -'s between "'s
|
||||
*/
|
||||
|
||||
#define WRTLEN 240
|
||||
|
||||
#define MIN( a, b ) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/* 1 for the @ and 4 for the .com */
|
||||
|
||||
char tempnambuf[ L_tmpnam + 1 + 4 ] = {0};
|
||||
|
||||
void
|
||||
execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status ),
|
||||
void *closure,
|
||||
LIST *shell )
|
||||
{
|
||||
char *s, *e, *p;
|
||||
int rstat = EXEC_CMD_OK;
|
||||
int status;
|
||||
|
||||
/* See if string is more than one line */
|
||||
/* discounting leading/trailing white space */
|
||||
|
||||
for( s = string; *s && isspace( *s ); s++ )
|
||||
;
|
||||
|
||||
e = p = strchr( s, '\n' );
|
||||
|
||||
while( p && isspace( *p ) )
|
||||
++p;
|
||||
|
||||
/* If multi line or long, write to com file. */
|
||||
/* Otherwise, exec directly. */
|
||||
|
||||
if( p && *p || e - s > WRTLEN )
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
/* Create temp file invocation "@sys$scratch:tempfile.com" */
|
||||
|
||||
if( !*tempnambuf )
|
||||
{
|
||||
tempnambuf[0] = '@';
|
||||
(void)tmpnam( tempnambuf + 1 );
|
||||
strcat( tempnambuf, ".com" );
|
||||
}
|
||||
|
||||
/* Open tempfile */
|
||||
|
||||
if( !( f = fopen( tempnambuf + 1, "w" ) ) )
|
||||
{
|
||||
printf( "can't open command file\n" );
|
||||
(*func)( closure, EXEC_CMD_FAIL );
|
||||
return;
|
||||
}
|
||||
|
||||
/* For each line of the string */
|
||||
|
||||
while( *string )
|
||||
{
|
||||
char *s = strchr( string, '\n' );
|
||||
int len = s ? s + 1 - string : strlen( string );
|
||||
|
||||
fputc( '$', f );
|
||||
|
||||
/* For each chunk of a line that needs to be split */
|
||||
|
||||
while( len > 0 )
|
||||
{
|
||||
char *q = string;
|
||||
char *qe = string + MIN( len, WRTLEN );
|
||||
char *qq = q;
|
||||
int quote = 0;
|
||||
|
||||
/* Look for matching "'s */
|
||||
|
||||
for( ; q < qe; q++ )
|
||||
if( *q == '"' && ( quote = !quote ) )
|
||||
qq = q;
|
||||
|
||||
/* Back up to opening quote, if in one */
|
||||
|
||||
if( quote )
|
||||
q = qq;
|
||||
|
||||
fwrite( string, ( q - string ), 1, f );
|
||||
|
||||
len -= ( q - string );
|
||||
string = q;
|
||||
|
||||
if( len )
|
||||
{
|
||||
fputc( '-', f );
|
||||
fputc( '\n', f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
|
||||
status = system( tempnambuf ) & 0x07;
|
||||
|
||||
unlink( tempnambuf + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Execute single line command */
|
||||
/* Strip trailing newline before execing */
|
||||
if( e ) *e = 0;
|
||||
status = system( s ) & 0x07;
|
||||
}
|
||||
|
||||
/* Fail for error or fatal error */
|
||||
/* OK on OK, warning, or info exit */
|
||||
|
||||
if( status == 2 || status == 4 )
|
||||
rstat = EXEC_CMD_FAIL;
|
||||
|
||||
(*func)( closure, rstat );
|
||||
}
|
||||
|
||||
int
|
||||
execwait()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
# endif /* VMS */
|
||||
591
historic/jam/src/expand.c
Normal file
591
historic/jam/src/expand.c
Normal file
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "variable.h"
|
||||
# include "expand.h"
|
||||
# include "filesys.h"
|
||||
# include "newstr.h"
|
||||
# include "strings.h"
|
||||
|
||||
# include <assert.h>
|
||||
# include <string.h>
|
||||
/*
|
||||
* expand.c - expand a buffer, given variable values
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* var_expand() - variable-expand input string into list of strings
|
||||
*
|
||||
* Internal routines:
|
||||
*
|
||||
* var_edit() - copy input target name to output, performing : modifiers
|
||||
* var_mods() - parse : modifiers into FILENAME structure
|
||||
*
|
||||
* 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X)
|
||||
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char downshift; /* :L -- downshift result */
|
||||
char upshift; /* :U -- upshift result */
|
||||
char parent; /* :P -- go to parent directory */
|
||||
char to_slashes; /* :T -- convert "\" to "/" */
|
||||
} VAR_ACTS ;
|
||||
|
||||
static void var_edit( char *in, char *mods, string *out );
|
||||
static void var_mods( char *mods, FILENAME *f, VAR_ACTS *acts );
|
||||
|
||||
static int adjust_index( int index, int length );
|
||||
|
||||
# define MAGIC_COLON '\001'
|
||||
# define MAGIC_LEFT '\002'
|
||||
# define MAGIC_RIGHT '\003'
|
||||
|
||||
/*
|
||||
* var_expand() - variable-expand input string into list of strings
|
||||
*
|
||||
* Would just copy input to output, performing variable expansion,
|
||||
* except that since variables can contain multiple values the result
|
||||
* of variable expansion may contain multiple values (a list). Properly
|
||||
* performs "product" operations that occur in "$(var1)xxx$(var2)" or
|
||||
* even "$($(var2))".
|
||||
*
|
||||
* Returns a newly created list.
|
||||
*/
|
||||
|
||||
LIST *
|
||||
var_expand(
|
||||
LIST *l,
|
||||
char *in,
|
||||
char *end,
|
||||
LOL *lol,
|
||||
int cancopyin )
|
||||
{
|
||||
string buf[1];
|
||||
size_t prefix_length;
|
||||
char *out;
|
||||
char *inp = in;
|
||||
char *ov; /* for temp copy of variable in outbuf */
|
||||
int depth;
|
||||
|
||||
if( DEBUG_VAREXP )
|
||||
printf( "expand '%.*s'\n", end - in, in );
|
||||
|
||||
/* This gets alot of cases: $(<) and $(>) */
|
||||
|
||||
if( in[0] == '$' && in[1] == '(' && in[3] == ')' && !in[4] )
|
||||
{
|
||||
switch( in[2] )
|
||||
{
|
||||
case '1':
|
||||
case '<':
|
||||
return list_copy( l, lol_get( lol, 0 ) );
|
||||
|
||||
case '2':
|
||||
case '>':
|
||||
return list_copy( l, lol_get( lol, 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we can use a simple copy of in to out. */
|
||||
|
||||
while ( in < end )
|
||||
if ( *in++ == '$' && *in == '(' )
|
||||
goto expand;
|
||||
|
||||
/* No variables expanded - just add copy of input string to list. */
|
||||
|
||||
/* Cancopyin is an optimization: if the input was already a list */
|
||||
/* item, we can use the copystr() to put it on the new list. */
|
||||
/* Otherwise, we use the slower newstr(). */
|
||||
|
||||
if ( cancopyin )
|
||||
{
|
||||
return list_new( l, copystr( inp ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST* r;
|
||||
string_new( buf );
|
||||
string_append_range( buf, inp, in );
|
||||
|
||||
r = list_new( l, newstr( buf->value ) );
|
||||
string_free( buf );
|
||||
return r;
|
||||
}
|
||||
|
||||
expand:
|
||||
string_new( buf );
|
||||
string_append_range( buf, inp, in - 1 ); /* copy in initial stuff */
|
||||
/*
|
||||
* Input so far (ignore blanks):
|
||||
*
|
||||
* stuff-in-outbuf $(variable) remainder
|
||||
* ^ ^
|
||||
* in end
|
||||
* Output so far:
|
||||
*
|
||||
* stuff-in-outbuf $
|
||||
* ^ ^
|
||||
* out_buf out
|
||||
*
|
||||
*
|
||||
* We just copied the $ of $(...), so back up one on the output.
|
||||
* We now find the matching close paren, copying the variable and
|
||||
* modifiers between the $( and ) temporarily into out_buf, so that
|
||||
* we can replace :'s with MAGIC_COLON. This is necessary to avoid
|
||||
* being confused by modifier values that are variables containing
|
||||
* :'s. Ugly.
|
||||
*/
|
||||
|
||||
depth = 1;
|
||||
inp = ++in; /* skip over the '(' */
|
||||
|
||||
while( in < end && depth )
|
||||
{
|
||||
switch( *in++ )
|
||||
{
|
||||
case '(': depth++; break;
|
||||
case ')': depth--; break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Input so far (ignore blanks):
|
||||
*
|
||||
* stuff-in-outbuf $(variable) remainder
|
||||
* ^ ^ ^
|
||||
* inp in end
|
||||
*/
|
||||
prefix_length = buf->size;
|
||||
string_append_range( buf, inp, in - 1 );
|
||||
|
||||
out = buf->value + prefix_length;
|
||||
for ( ov = out; ov < buf->value + buf->size; ++ov )
|
||||
{
|
||||
switch( *ov )
|
||||
{
|
||||
case ':': *ov = MAGIC_COLON; break;
|
||||
case '[': *ov = MAGIC_LEFT; break;
|
||||
case ']': *ov = MAGIC_RIGHT; break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Input so far (ignore blanks):
|
||||
*
|
||||
* stuff-in-outbuf $(variable) remainder
|
||||
* ^ ^
|
||||
* in end
|
||||
* Output so far:
|
||||
*
|
||||
* stuff-in-outbuf variable
|
||||
* ^ ^ ^
|
||||
* out_buf out ov
|
||||
*
|
||||
* Later we will overwrite 'variable' in out_buf, but we'll be
|
||||
* done with it by then. 'variable' may be a multi-element list,
|
||||
* so may each value for '$(variable element)', and so may 'remainder'.
|
||||
* Thus we produce a product of three lists.
|
||||
*/
|
||||
|
||||
{
|
||||
LIST *variables = 0;
|
||||
LIST *remainder = 0;
|
||||
LIST *vars;
|
||||
|
||||
/* Recursively expand variable name & rest of input */
|
||||
|
||||
if( out < ov )
|
||||
variables = var_expand( L0, out, ov, lol, 0 );
|
||||
if( in < end )
|
||||
remainder = var_expand( L0, in, end, lol, 0 );
|
||||
|
||||
/* Now produce the result chain */
|
||||
|
||||
/* For each variable name */
|
||||
|
||||
for( vars = variables; vars; vars = list_next( vars ) )
|
||||
{
|
||||
LIST *value;
|
||||
char *colon;
|
||||
char *bracket;
|
||||
int i, sub1, sub2;
|
||||
string variable;
|
||||
char *varname;
|
||||
|
||||
/* Look for a : modifier in the variable name */
|
||||
/* Must copy into varname so we can modify it */
|
||||
|
||||
string_copy( &variable, vars->string );
|
||||
varname = variable.value;
|
||||
|
||||
if( colon = strchr( varname, MAGIC_COLON ) )
|
||||
{
|
||||
string_truncate( &variable, colon - varname );
|
||||
}
|
||||
|
||||
if( bracket = strchr( varname, MAGIC_LEFT ) )
|
||||
{
|
||||
char *dash = 0;
|
||||
|
||||
if( bracket[1] && ( dash = strchr( bracket + 2, '-' ) ) )
|
||||
{
|
||||
string_truncate( &variable, dash - varname );
|
||||
sub1 = atoi( bracket + 1 );
|
||||
sub2 = atoi( dash + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
sub1 = sub2 = atoi( bracket + 1 );
|
||||
}
|
||||
|
||||
string_truncate( &variable, bracket - varname );
|
||||
}
|
||||
else
|
||||
{
|
||||
sub1 = sub2 = 0; /* not needed */
|
||||
}
|
||||
|
||||
/* Get variable value, specially handling $(<), $(>), $(n) */
|
||||
|
||||
if( varname[0] == '<' && !varname[1] )
|
||||
{
|
||||
value = lol_get( lol, 0 );
|
||||
}
|
||||
else if( varname[0] == '>' && !varname[1] )
|
||||
{
|
||||
value = lol_get( lol, 1 );
|
||||
}
|
||||
else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] )
|
||||
{
|
||||
value = lol_get( lol, varname[0] - '1' );
|
||||
}
|
||||
else
|
||||
{
|
||||
value = var_get( varname );
|
||||
}
|
||||
|
||||
/* The fast path: $(x) - just copy the variable value. */
|
||||
|
||||
if( out == buf->value && !bracket && !colon && in == end )
|
||||
{
|
||||
string_free( &variable );
|
||||
l = list_copy( l, value );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Adjust negative indices */
|
||||
if ( sub1 < 0 || sub2 < 0 )
|
||||
{
|
||||
int length = list_length( value );
|
||||
sub1 = adjust_index( sub1, length );
|
||||
sub2 = adjust_index( sub2, length );
|
||||
}
|
||||
|
||||
/* For each variable value */
|
||||
for( i = 1; value; i++, value = list_next( value ) )
|
||||
{
|
||||
LIST *rem;
|
||||
size_t postfix_start;
|
||||
|
||||
/* Skip members not in subscript */
|
||||
|
||||
if( bracket && ( i < sub1 || sub2 && i > sub2 ) )
|
||||
continue;
|
||||
|
||||
string_truncate( buf, prefix_length );
|
||||
|
||||
/* Apply : mods, if present */
|
||||
|
||||
if( colon )
|
||||
var_edit( value->string, colon + 1, buf );
|
||||
else
|
||||
string_append( buf, value->string );
|
||||
|
||||
/* If no remainder, append result to output chain. */
|
||||
|
||||
if( in == end )
|
||||
{
|
||||
l = list_new( l, newstr( buf->value ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remember the end of the variable expansion so */
|
||||
/* we can just tack on each instance of 'remainder' */
|
||||
|
||||
postfix_start = buf->size;
|
||||
|
||||
/* For each remainder, or just once if no remainder, */
|
||||
/* append the complete string to the output chain */
|
||||
|
||||
for( rem = remainder; rem; rem = list_next( rem ) )
|
||||
{
|
||||
string_truncate( buf, postfix_start );
|
||||
string_append( buf, rem->string );
|
||||
l = list_new( l, newstr( buf->value ) );
|
||||
}
|
||||
}
|
||||
string_free( &variable );
|
||||
}
|
||||
|
||||
/* variables & remainder were gifts from var_expand */
|
||||
/* and must be freed */
|
||||
|
||||
if( variables )
|
||||
list_free( variables );
|
||||
if( remainder)
|
||||
list_free( remainder );
|
||||
|
||||
if( DEBUG_VAREXP )
|
||||
{
|
||||
printf( "expanded to " );
|
||||
list_print( l );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
string_free( buf );
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* var_edit() - copy input target name to output, performing : modifiers
|
||||
*/
|
||||
|
||||
static void
|
||||
var_edit(
|
||||
char *in,
|
||||
char *mods,
|
||||
string *out)
|
||||
{
|
||||
FILENAME oldf, newf;
|
||||
VAR_ACTS acts;
|
||||
|
||||
/* Parse apart original filename, putting parts into "oldf" */
|
||||
|
||||
file_parse( in, &oldf );
|
||||
|
||||
/* Parse apart modifiers, putting them into "newf" */
|
||||
|
||||
var_mods( mods, &newf, &acts );
|
||||
|
||||
/* Replace any oldf with newf */
|
||||
|
||||
if( newf.f_grist.ptr )
|
||||
oldf.f_grist = newf.f_grist;
|
||||
|
||||
if( newf.f_root.ptr )
|
||||
oldf.f_root = newf.f_root;
|
||||
|
||||
if( newf.f_dir.ptr )
|
||||
oldf.f_dir = newf.f_dir;
|
||||
|
||||
if( newf.f_base.ptr )
|
||||
oldf.f_base = newf.f_base;
|
||||
|
||||
if( newf.f_suffix.ptr )
|
||||
oldf.f_suffix = newf.f_suffix;
|
||||
|
||||
if( newf.f_member.ptr )
|
||||
oldf.f_member = newf.f_member;
|
||||
|
||||
/* If requested, modify oldf to point to parent */
|
||||
|
||||
if( acts.parent )
|
||||
file_parent( &oldf );
|
||||
|
||||
/* Put filename back together */
|
||||
|
||||
file_build( &oldf, out, 0 );
|
||||
|
||||
/* Handle upshifting, downshifting now */
|
||||
/* Handle conversion of "\" to "/" */
|
||||
{
|
||||
char* p;
|
||||
for ( p = out->value; *p; ++p)
|
||||
{
|
||||
if( acts.upshift )
|
||||
{
|
||||
*p = toupper( *p );
|
||||
}
|
||||
else if( acts.downshift )
|
||||
{
|
||||
*p = tolower( *p );
|
||||
}
|
||||
if ( acts.to_slashes )
|
||||
{
|
||||
if ( *p == '\\' )
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
out->size = p - out->value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* var_mods() - parse : modifiers into FILENAME structure
|
||||
*
|
||||
* The : modifiers in a $(varname:modifier) currently support replacing
|
||||
* or omitting elements of a filename, and so they are parsed into a
|
||||
* FILENAME structure (which contains pointers into the original string).
|
||||
*
|
||||
* Modifiers of the form "X=value" replace the component X with
|
||||
* the given value. Modifiers without the "=value" cause everything
|
||||
* but the component X to be omitted. X is one of:
|
||||
*
|
||||
* G <grist>
|
||||
* D directory name
|
||||
* B base name
|
||||
* S .suffix
|
||||
* M (member)
|
||||
* R root directory - prepended to whole path
|
||||
*
|
||||
* This routine sets:
|
||||
*
|
||||
* f->f_xxx.ptr = 0
|
||||
* f->f_xxx.len = 0
|
||||
* -> leave the original component xxx
|
||||
*
|
||||
* f->f_xxx.ptr = string
|
||||
* f->f_xxx.len = strlen( string )
|
||||
* -> replace component xxx with string
|
||||
*
|
||||
* f->f_xxx.ptr = ""
|
||||
* f->f_xxx.len = 0
|
||||
* -> omit component xxx
|
||||
*
|
||||
* var_edit() above and file_build() obligingly follow this convention.
|
||||
*/
|
||||
|
||||
static void
|
||||
var_mods(
|
||||
char *mods,
|
||||
FILENAME *f,
|
||||
VAR_ACTS *acts )
|
||||
{
|
||||
char *flags = "GRDBSMT";
|
||||
int havezeroed = 0;
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
memset( (char *)acts, 0, sizeof( *acts ) );
|
||||
|
||||
while( *mods )
|
||||
{
|
||||
char *fl;
|
||||
FILEPART *fp;
|
||||
|
||||
/* First take care of :U or :L (upshift, downshift) */
|
||||
|
||||
if( *mods == 'L' )
|
||||
{
|
||||
acts->downshift = 1;
|
||||
++mods;
|
||||
continue;
|
||||
}
|
||||
else if( *mods == 'U' )
|
||||
{
|
||||
acts->upshift = 1;
|
||||
++mods;
|
||||
continue;
|
||||
}
|
||||
else if( *mods == 'P' )
|
||||
{
|
||||
acts->parent = 1;
|
||||
++mods;
|
||||
continue;
|
||||
}
|
||||
else if ( *mods == 'T' )
|
||||
{
|
||||
acts->to_slashes = 1;
|
||||
++mods;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now handle the file component flags */
|
||||
|
||||
if( !( fl = strchr( flags, *mods++ ) ) )
|
||||
break; /* should complain, but so what... */
|
||||
|
||||
fp = &f->part[ fl - flags ];
|
||||
|
||||
if( *mods++ != '=' )
|
||||
{
|
||||
/* :X - turn everything but X off */
|
||||
|
||||
int i;
|
||||
|
||||
mods--;
|
||||
|
||||
if( !havezeroed++ )
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
f->part[ i ].len = 0;
|
||||
f->part[ i ].ptr = "";
|
||||
}
|
||||
|
||||
fp->ptr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* :X=value - set X to value */
|
||||
|
||||
char *p;
|
||||
|
||||
if( p = strchr( mods, MAGIC_COLON ) )
|
||||
{
|
||||
fp->ptr = mods;
|
||||
fp->len = p - mods;
|
||||
mods = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fp->ptr = mods;
|
||||
fp->len = strlen( mods );
|
||||
mods += fp->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int adjust_index( int index, int length )
|
||||
{
|
||||
if ( index < 0 )
|
||||
index = length + 1 + index;
|
||||
if ( index < 0 )
|
||||
index = 0;
|
||||
return index;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void var_expand_unit_test()
|
||||
{
|
||||
LOL lol[1];
|
||||
LIST* l, *l2;
|
||||
LIST *expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) );
|
||||
LIST *e2;
|
||||
char axyb[] = "a$(xy)b";
|
||||
char azb[] = "a$($(z))b";
|
||||
|
||||
lol_init(lol);
|
||||
var_set("xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET );
|
||||
var_set("z", list_new( L0, newstr( "xy" ) ), VAR_SET );
|
||||
|
||||
l = var_expand( 0, axyb, axyb + sizeof(axyb) - 1, lol, 0 );
|
||||
for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) )
|
||||
assert( !strcmp( e2->string, l2->string ) );
|
||||
list_free(l);
|
||||
|
||||
l = var_expand( 0, azb, azb + sizeof(azb) - 1, lol, 0 );
|
||||
for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) )
|
||||
assert( !strcmp( e2->string, l2->string ) );
|
||||
list_free(l);
|
||||
|
||||
lol_free(lol);
|
||||
}
|
||||
#endif
|
||||
12
historic/jam/src/expand.h
Normal file
12
historic/jam/src/expand.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* expand.h - expand a buffer, given variable values
|
||||
*/
|
||||
|
||||
LIST *var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin );
|
||||
void var_expand_unit_test();
|
||||
165
historic/jam/src/filemac.c
Normal file
165
historic/jam/src/filemac.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
|
||||
# ifdef OS_MAC
|
||||
|
||||
#include <Files.h>
|
||||
#include <Folders.h>
|
||||
|
||||
# include <:sys:stat.h>
|
||||
|
||||
/*
|
||||
* filemac.c - manipulate file names and scan directories on macintosh
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* file_dirscan() - scan a directory for files
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
* file_archscan() - scan an archive for files
|
||||
*
|
||||
* File_dirscan() and file_archscan() call back a caller provided function
|
||||
* for each file found. A flag to this callback function lets file_dirscan()
|
||||
* and file_archscan() indicate that a timestamp is being provided with the
|
||||
* file. If file_dirscan() or file_archscan() do not provide the file's
|
||||
* timestamp, interested parties may later call file_time().
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 12/19/94 (mikem) - solaris string table insanity support
|
||||
* 02/14/95 (seiwald) - parse and build /xxx properly
|
||||
* 05/03/96 (seiwald) - split into pathunix.c
|
||||
* 11/21/96 (peterk) - BEOS does not have Unix-style archives
|
||||
*/
|
||||
|
||||
void CopyC2PStr(const char * cstr, StringPtr pstr)
|
||||
{
|
||||
int len;
|
||||
|
||||
for (len = 0; *cstr && len<255; pstr[++len] = *cstr++)
|
||||
;
|
||||
|
||||
pstr[0] = len;
|
||||
}
|
||||
|
||||
/*
|
||||
* file_dirscan() - scan a directory for files
|
||||
*/
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
void (*func)( char *file, int s, time_t t ) )
|
||||
{
|
||||
FILENAME f;
|
||||
string filename[1];
|
||||
unsigned char fullPath[ 512 ];
|
||||
|
||||
FSSpec spec;
|
||||
WDPBRec vol;
|
||||
Str63 volName;
|
||||
CInfoPBRec lastInfo;
|
||||
int index = 1;
|
||||
|
||||
/* First enter directory itself */
|
||||
|
||||
memset( (char *)&f, '\0', sizeof( f ) );
|
||||
|
||||
f.f_dir.ptr = dir;
|
||||
f.f_dir.len = strlen(dir);
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan directory %s\n", dir );
|
||||
|
||||
/* Special case ":" - enter it */
|
||||
|
||||
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == ':' )
|
||||
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
|
||||
/* Now enter contents of directory */
|
||||
|
||||
vol.ioNamePtr = volName;
|
||||
|
||||
if( PBHGetVolSync( &vol ) )
|
||||
return;
|
||||
|
||||
CopyC2PStr( dir, fullPath );
|
||||
|
||||
if( FSMakeFSSpec( vol.ioWDVRefNum, vol.ioWDDirID, fullPath, &spec ) )
|
||||
return;
|
||||
|
||||
lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
|
||||
lastInfo.dirInfo.ioDrDirID = spec.parID;
|
||||
lastInfo.dirInfo.ioNamePtr = spec.name;
|
||||
lastInfo.dirInfo.ioFDirIndex = 0;
|
||||
lastInfo.dirInfo.ioACUser = 0;
|
||||
|
||||
if( PBGetCatInfoSync(&lastInfo) )
|
||||
return;
|
||||
|
||||
if (!(lastInfo.dirInfo.ioFlAttrib & 0x10))
|
||||
return;
|
||||
|
||||
// ioDrDirID must be reset each time.
|
||||
|
||||
spec.parID = lastInfo.dirInfo.ioDrDirID;
|
||||
|
||||
string_new( filename );
|
||||
for( ;; )
|
||||
{
|
||||
lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
|
||||
lastInfo.dirInfo.ioDrDirID = spec.parID;
|
||||
lastInfo.dirInfo.ioNamePtr = fullPath;
|
||||
lastInfo.dirInfo.ioFDirIndex = index++;
|
||||
|
||||
if( PBGetCatInfoSync(&lastInfo) )
|
||||
return;
|
||||
|
||||
f.f_base.ptr = (char *)fullPath + 1;
|
||||
f.f_base.len = *fullPath;
|
||||
|
||||
string_truncate( filename, 0 );
|
||||
file_build( &f, filename, 0 );
|
||||
(*func)( filename->value, 0 /* not stat()'ed */, (time_t)0 );
|
||||
}
|
||||
string_free( filename );
|
||||
}
|
||||
|
||||
/*
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
*/
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
|
||||
*time = statbuf.st_mtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* file_archscan() - scan an archive for files
|
||||
*/
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
void (*func)( char *file, int s, time_t t ) )
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
# endif /* macintosh */
|
||||
|
||||
275
historic/jam/src/filent.c
Normal file
275
historic/jam/src/filent.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
# include "strings.h"
|
||||
|
||||
# ifdef OS_NT
|
||||
|
||||
# ifdef __BORLANDC__
|
||||
# if __BORLANDC__ < 0x550
|
||||
# include <dir.h>
|
||||
# include <dos.h>
|
||||
# endif
|
||||
# undef FILENAME /* cpp namespace collision */
|
||||
# define _finddata_t ffblk
|
||||
# endif
|
||||
|
||||
# include <io.h>
|
||||
# include <sys/stat.h>
|
||||
|
||||
/*
|
||||
* filent.c - scan directories and archives on NT
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* file_dirscan() - scan a directory for files
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
* file_archscan() - scan an archive for files
|
||||
*
|
||||
* File_dirscan() and file_archscan() call back a caller provided function
|
||||
* for each file found. A flag to this callback function lets file_dirscan()
|
||||
* and file_archscan() indicate that a timestamp is being provided with the
|
||||
* file. If file_dirscan() or file_archscan() do not provide the file's
|
||||
* timestamp, interested parties may later call file_time().
|
||||
*
|
||||
* 07/10/95 (taylor) Findfirst() returns the first file on NT.
|
||||
* 05/03/96 (seiwald) split apart into pathnt.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* file_dirscan() - scan a directory for files
|
||||
*/
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
FILENAME f;
|
||||
string filespec[1];
|
||||
string filename[1];
|
||||
long handle;
|
||||
int ret;
|
||||
struct _finddata_t finfo[1];
|
||||
|
||||
/* First enter directory itself */
|
||||
|
||||
memset( (char *)&f, '\0', sizeof( f ) );
|
||||
|
||||
f.f_dir.ptr = dir;
|
||||
f.f_dir.len = strlen(dir);
|
||||
|
||||
dir = *dir ? dir : ".";
|
||||
|
||||
/* Special case \ or d:\ : enter it */
|
||||
|
||||
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
|
||||
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
|
||||
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
|
||||
/* Now enter contents of directory */
|
||||
|
||||
string_copy( filespec, dir );
|
||||
string_append( filespec, "/*" );
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan directory %s\n", dir );
|
||||
|
||||
# if defined(__BORLANDC__) && __BORLANDC__ < 0x550
|
||||
if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
|
||||
{
|
||||
string_free( filespec );
|
||||
return;
|
||||
}
|
||||
|
||||
string_new( filename );
|
||||
while( !ret )
|
||||
{
|
||||
time_t time_write = finfo->ff_fdate;
|
||||
|
||||
time_write = (time_write << 16) | finfo->ff_ftime;
|
||||
f.f_base.ptr = finfo->ff_name;
|
||||
f.f_base.len = strlen( finfo->ff_name );
|
||||
|
||||
string_truncate( filename, 0 );
|
||||
file_build( &f, filename );
|
||||
|
||||
(*func)( filename->value, 1 /* stat()'ed */, time_write );
|
||||
|
||||
ret = findnext( finfo );
|
||||
}
|
||||
# else
|
||||
handle = _findfirst( filespec->value, finfo );
|
||||
|
||||
if( ret = ( handle < 0L ) )
|
||||
{
|
||||
string_free( filespec );
|
||||
return;
|
||||
}
|
||||
|
||||
string_new( filename );
|
||||
while( !ret )
|
||||
{
|
||||
f.f_base.ptr = finfo->name;
|
||||
f.f_base.len = strlen( finfo->name );
|
||||
|
||||
string_truncate( filename, 0 );
|
||||
file_build( &f, filename, 0 );
|
||||
|
||||
(*func)( filename->value, 1 /* stat()'ed */, finfo->time_write );
|
||||
|
||||
ret = _findnext( handle, finfo );
|
||||
}
|
||||
|
||||
_findclose( handle );
|
||||
# endif
|
||||
string_free( filename );
|
||||
string_free( filespec );
|
||||
}
|
||||
|
||||
/*
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
*/
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
/* On NT this is called only for C:/ */
|
||||
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
|
||||
*time = statbuf.st_mtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* file_archscan() - scan an archive for files
|
||||
*/
|
||||
|
||||
/* Straight from SunOS */
|
||||
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
|
||||
#define ARFMAG "`\n"
|
||||
|
||||
struct ar_hdr {
|
||||
char ar_name[16];
|
||||
char ar_date[12];
|
||||
char ar_uid[6];
|
||||
char ar_gid[6];
|
||||
char ar_mode[8];
|
||||
char ar_size[10];
|
||||
char ar_fmag[2];
|
||||
};
|
||||
|
||||
# define SARFMAG 2
|
||||
# define SARHDR sizeof( struct ar_hdr )
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
struct ar_hdr ar_hdr;
|
||||
char *string_table = 0;
|
||||
char buf[ MAXJPATH ];
|
||||
long offset;
|
||||
int fd;
|
||||
|
||||
if( ( fd = open( archive, O_RDONLY | O_BINARY, 0 ) ) < 0 )
|
||||
return;
|
||||
|
||||
if( read( fd, buf, SARMAG ) != SARMAG ||
|
||||
strncmp( ARMAG, buf, SARMAG ) )
|
||||
{
|
||||
close( fd );
|
||||
return;
|
||||
}
|
||||
|
||||
offset = SARMAG;
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan archive %s\n", archive );
|
||||
|
||||
while( read( fd, &ar_hdr, SARHDR ) == SARHDR &&
|
||||
!memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
|
||||
{
|
||||
long lar_date;
|
||||
long lar_size;
|
||||
char *name = 0;
|
||||
char *endname;
|
||||
char *c;
|
||||
|
||||
sscanf( ar_hdr.ar_date, "%ld", &lar_date );
|
||||
sscanf( ar_hdr.ar_size, "%ld", &lar_size );
|
||||
|
||||
lar_size = ( lar_size + 1 ) & ~1;
|
||||
|
||||
if (ar_hdr.ar_name[0] == '/' && ar_hdr.ar_name[1] == '/' )
|
||||
{
|
||||
/* this is the "string table" entry of the symbol table,
|
||||
** which holds strings of filenames that are longer than
|
||||
** 15 characters (ie. don't fit into a ar_name
|
||||
*/
|
||||
|
||||
string_table = malloc(lar_size);
|
||||
if (read(fd, string_table, lar_size) != lar_size)
|
||||
printf("error reading string table\n");
|
||||
offset += SARHDR + lar_size;
|
||||
continue;
|
||||
}
|
||||
else if (ar_hdr.ar_name[0] == '/' && ar_hdr.ar_name[1] != ' ')
|
||||
{
|
||||
/* Long filenames are recognized by "/nnnn" where nnnn is
|
||||
** the offset of the string in the string table represented
|
||||
** in ASCII decimals.
|
||||
*/
|
||||
|
||||
name = string_table + atoi( ar_hdr.ar_name + 1 );
|
||||
endname = name + strlen( name );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* normal name */
|
||||
name = ar_hdr.ar_name;
|
||||
endname = name + sizeof( ar_hdr.ar_name );
|
||||
}
|
||||
|
||||
/* strip trailing space, slashes, and backslashes */
|
||||
|
||||
while( endname-- > name )
|
||||
if( *endname != ' ' && *endname != '\\' && *endname != '/' )
|
||||
break;
|
||||
*++endname = 0;
|
||||
|
||||
/* strip leading directory names, an NT specialty */
|
||||
|
||||
if( c = strrchr( name, '/' ) )
|
||||
name = c + 1;
|
||||
if( c = strrchr( name, '\\' ) )
|
||||
name = c + 1;
|
||||
|
||||
sprintf( buf, "%s(%.*s)", archive, endname - name, name );
|
||||
(*func)( buf, 1 /* time valid */, (time_t)lar_date );
|
||||
|
||||
offset += SARHDR + lar_size;
|
||||
lseek( fd, offset, 0 );
|
||||
}
|
||||
|
||||
close( fd );
|
||||
}
|
||||
|
||||
# endif /* NT */
|
||||
130
historic/jam/src/fileos2.c
Normal file
130
historic/jam/src/fileos2.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
|
||||
/* note that we use "fileunix.c" when compiling with EMX on OS/2 */
|
||||
# if defined(OS_OS2) && !defined(__EMX__)
|
||||
|
||||
# include <io.h>
|
||||
# include <dos.h>
|
||||
|
||||
/*
|
||||
* fileos2.c - scan directories and archives on NT
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* file_dirscan() - scan a directory for files
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
* file_archscan() - scan an archive for files
|
||||
*
|
||||
* File_dirscan() and file_archscan() call back a caller provided function
|
||||
* for each file found. A flag to this callback function lets file_dirscan()
|
||||
* and file_archscan() indicate that a timestamp is being provided with the
|
||||
* file. If file_dirscan() or file_archscan() do not provide the file's
|
||||
* timestamp, interested parties may later call file_time().
|
||||
*
|
||||
* 07/10/95 (taylor) Findfirst() returns the first file on NT.
|
||||
* 05/03/96 (seiwald) split apart into pathnt.c
|
||||
* 09/22/00 (seiwald) handle \ and c:\ specially: don't add extra /
|
||||
*/
|
||||
|
||||
/*
|
||||
* file_dirscan() - scan a directory for files
|
||||
*/
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
FILENAME f;
|
||||
string filespec[1];
|
||||
long handle;
|
||||
int ret;
|
||||
struct _find_t finfo[1];
|
||||
|
||||
/* First enter directory itself */
|
||||
|
||||
memset( (char *)&f, '\0', sizeof( f ) );
|
||||
|
||||
f.f_dir.ptr = dir;
|
||||
f.f_dir.len = strlen(dir);
|
||||
|
||||
dir = *dir ? dir : ".";
|
||||
|
||||
/* Special case \ or d:\ : enter it */
|
||||
string_copy( filespec, dir );
|
||||
|
||||
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
|
||||
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
|
||||
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
else
|
||||
string_push_back( filespec, '/' );
|
||||
|
||||
string_push_back( filespec, '*' );
|
||||
|
||||
/* Now enter contents of directory */
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan directory %s\n", filespec->value );
|
||||
|
||||
/* Time info in dos find_t is not very useful. It consists */
|
||||
/* of a separate date and time, and putting them together is */
|
||||
/* not easy. So we leave that to a later stat() call. */
|
||||
|
||||
if( !_dos_findfirst( filespec->value, _A_NORMAL|_A_RDONLY|_A_SUBDIR, finfo ) )
|
||||
{
|
||||
string filename[1];
|
||||
string_new( filename );
|
||||
do
|
||||
{
|
||||
|
||||
f.f_base.ptr = finfo->name;
|
||||
f.f_base.len = strlen( finfo->name );
|
||||
|
||||
string_truncate( filename, 0 );
|
||||
file_build( &f, filename, 0 );
|
||||
(*func)( filename->value, 0 /* not stat()'ed */, (time_t)0 );
|
||||
}
|
||||
while( !_dos_findnext( finfo ) );
|
||||
string_free( filename );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
*/
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
/* This is called on OS2, not NT. */
|
||||
/* NT fills in the time in the dirscan. */
|
||||
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
|
||||
*time = statbuf.st_mtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
}
|
||||
|
||||
# endif /* OS2 && !__EMX__ */
|
||||
|
||||
33
historic/jam/src/filesys.c
Normal file
33
historic/jam/src/filesys.c
Normal file
@@ -0,0 +1,33 @@
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
# include "strings.h"
|
||||
|
||||
void
|
||||
file_build1(
|
||||
FILENAME *f,
|
||||
string* file)
|
||||
{
|
||||
if( DEBUG_SEARCH )
|
||||
{
|
||||
printf("build file: ");
|
||||
if( f->f_root.len )
|
||||
printf( "root = '%.*s' ", f->f_root.len, f->f_root.ptr );
|
||||
if( f->f_dir.len )
|
||||
printf( "dir = '%.*s' ", f->f_dir.len, f->f_dir.ptr );
|
||||
if( f->f_base.len )
|
||||
printf( "base = '%.*s' ", f->f_base.len, f->f_base.ptr );
|
||||
}
|
||||
|
||||
/* Start with the grist. If the current grist isn't */
|
||||
/* surrounded by <>'s, add them. */
|
||||
|
||||
if( f->f_grist.len )
|
||||
{
|
||||
if( f->f_grist.ptr[0] != '<' )
|
||||
string_push_back( file, '<' );
|
||||
string_append_range(
|
||||
file, f->f_grist.ptr, f->f_grist.ptr + f->f_grist.len );
|
||||
if( file->value[file->size - 1] != '>' )
|
||||
string_push_back( file, '>' );
|
||||
}
|
||||
}
|
||||
62
historic/jam/src/filesys.h
Normal file
62
historic/jam/src/filesys.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* filesys.h - FILENAME struct and OS specific file routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* FILENAME - a name of a file, broken into <grist>dir/base/suffix(member)
|
||||
*
|
||||
* <grist> is salt to distinguish between targets that otherwise would
|
||||
* have the same name: it never appears in the bound name of a target.
|
||||
* (member) is an archive member name: the syntax is arbitrary, but must
|
||||
* agree in file_parse(), file_build() and the Jambase.
|
||||
*
|
||||
* On VMS, we keep track of whether the original path was a directory
|
||||
* (without a file), so that $(VAR:D) can climb to the parent.
|
||||
*/
|
||||
|
||||
#ifndef FILESYS_DWA20011025_H
|
||||
# define FILESYS_DWA20011025_H
|
||||
|
||||
# include "strings.h"
|
||||
|
||||
typedef struct _filename FILENAME;
|
||||
typedef struct _filepart FILEPART;
|
||||
|
||||
struct _filepart {
|
||||
char *ptr;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct _filename {
|
||||
FILEPART part[6];
|
||||
# ifdef OS_VMS
|
||||
int parent;
|
||||
# endif
|
||||
|
||||
# define f_grist part[0]
|
||||
# define f_root part[1]
|
||||
# define f_dir part[2]
|
||||
# define f_base part[3]
|
||||
# define f_suffix part[4]
|
||||
# define f_member part[5]
|
||||
|
||||
} ;
|
||||
|
||||
void file_build( FILENAME *f, string *file, int binding );
|
||||
void file_build1( FILENAME *f, string *file );
|
||||
|
||||
void file_parse( char *file, FILENAME *f );
|
||||
void file_parent( FILENAME *f );
|
||||
|
||||
void file_dirscan( char *dir, void (*func)( char *f, int s, time_t t ) );
|
||||
void file_archscan( char *arch, void (*func)( char *f, int s, time_t t ) );
|
||||
|
||||
int file_time( char *filename, time_t *time );
|
||||
|
||||
#endif // FILESYS_DWA20011025_H
|
||||
336
historic/jam/src/fileunix.c
Normal file
336
historic/jam/src/fileunix.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
# include "strings.h"
|
||||
|
||||
# ifdef USE_FILEUNIX
|
||||
|
||||
# if defined( OS_SEQUENT ) || \
|
||||
defined( OS_DGUX ) || \
|
||||
defined( OS_SCO ) || \
|
||||
defined( OS_ISC )
|
||||
# define PORTAR 1
|
||||
# endif
|
||||
|
||||
# ifdef __EMX__
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# endif
|
||||
|
||||
# if defined( OS_RHAPSODY ) || \
|
||||
defined( OS_MACOSX ) || \
|
||||
defined( OS_NEXT )
|
||||
/* need unistd for rhapsody's proper lseek */
|
||||
# include <sys/dir.h>
|
||||
# include <unistd.h>
|
||||
# define STRUCT_DIRENT struct direct
|
||||
# else
|
||||
# include <dirent.h>
|
||||
# define STRUCT_DIRENT struct dirent
|
||||
# endif
|
||||
|
||||
# ifdef OS_COHERENT
|
||||
# include <arcoff.h>
|
||||
# define HAVE_AR
|
||||
# endif
|
||||
|
||||
# if defined( OS_MVS ) || \
|
||||
defined( OS_INTERIX )
|
||||
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\n"
|
||||
|
||||
struct ar_hdr /* archive file member header - printable ascii */
|
||||
{
|
||||
char ar_name[16]; /* file member name - `/' terminated */
|
||||
char ar_date[12]; /* file member date - decimal */
|
||||
char ar_uid[6]; /* file member user id - decimal */
|
||||
char ar_gid[6]; /* file member group id - decimal */
|
||||
char ar_mode[8]; /* file member mode - octal */
|
||||
char ar_size[10]; /* file member size - decimal */
|
||||
char ar_fmag[2]; /* ARFMAG - string to end header */
|
||||
};
|
||||
|
||||
# define HAVE_AR
|
||||
# endif
|
||||
|
||||
# if defined( OS_QNX ) || \
|
||||
defined( OS_BEOS ) || \
|
||||
defined( OS_MPEIX )
|
||||
# define NO_AR
|
||||
# define HAVE_AR
|
||||
# endif
|
||||
|
||||
# ifndef HAVE_AR
|
||||
# include <ar.h>
|
||||
# endif
|
||||
|
||||
/*
|
||||
* fileunix.c - manipulate file names and scan directories on UNIX/AmigaOS
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* file_dirscan() - scan a directory for files
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
* file_archscan() - scan an archive for files
|
||||
*
|
||||
* File_dirscan() and file_archscan() call back a caller provided function
|
||||
* for each file found. A flag to this callback function lets file_dirscan()
|
||||
* and file_archscan() indicate that a timestamp is being provided with the
|
||||
* file. If file_dirscan() or file_archscan() do not provide the file's
|
||||
* timestamp, interested parties may later call file_time().
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 12/19/94 (mikem) - solaris string table insanity support
|
||||
* 02/14/95 (seiwald) - parse and build /xxx properly
|
||||
* 05/03/96 (seiwald) - split into pathunix.c
|
||||
* 11/21/96 (peterk) - BEOS does not have Unix-style archives
|
||||
*/
|
||||
|
||||
/*
|
||||
* file_dirscan() - scan a directory for files
|
||||
*/
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
FILENAME f;
|
||||
DIR *d;
|
||||
STRUCT_DIRENT *dirent;
|
||||
string filename[1];
|
||||
|
||||
/* First enter directory itself */
|
||||
|
||||
memset( (char *)&f, '\0', sizeof( f ) );
|
||||
|
||||
f.f_dir.ptr = dir;
|
||||
f.f_dir.len = strlen(dir);
|
||||
|
||||
dir = *dir ? dir : ".";
|
||||
|
||||
/* Special case / : enter it */
|
||||
|
||||
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '/' )
|
||||
(*func)( dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
|
||||
/* Now enter contents of directory */
|
||||
|
||||
if( !( d = opendir( dir ) ) )
|
||||
return;
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan directory %s\n", dir );
|
||||
|
||||
string_new( filename );
|
||||
while( dirent = readdir( d ) )
|
||||
{
|
||||
# ifdef old_sinix
|
||||
/* Broken structure definition on sinix. */
|
||||
f.f_base.ptr = dirent->d_name - 2;
|
||||
# else
|
||||
f.f_base.ptr = dirent->d_name;
|
||||
# endif
|
||||
f.f_base.len = strlen( f.f_base.ptr );
|
||||
|
||||
string_truncate( filename, 0 );
|
||||
file_build( &f, filename, 0 );
|
||||
|
||||
(*func)( filename->value, 0 /* not stat()'ed */, (time_t)0 );
|
||||
}
|
||||
string_free( filename );
|
||||
|
||||
closedir( d );
|
||||
}
|
||||
|
||||
/*
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
*/
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
|
||||
*time = statbuf.st_mtime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* file_archscan() - scan an archive for files
|
||||
*/
|
||||
|
||||
# ifndef AIAMAG /* God-fearing UNIX */
|
||||
|
||||
# define SARFMAG 2
|
||||
# define SARHDR sizeof( struct ar_hdr )
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
# ifndef NO_AR
|
||||
struct ar_hdr ar_hdr;
|
||||
char buf[ MAXJPATH ];
|
||||
long offset;
|
||||
char *string_table = 0;
|
||||
int fd;
|
||||
|
||||
if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
|
||||
return;
|
||||
|
||||
if( read( fd, buf, SARMAG ) != SARMAG ||
|
||||
strncmp( ARMAG, buf, SARMAG ) )
|
||||
{
|
||||
close( fd );
|
||||
return;
|
||||
}
|
||||
|
||||
offset = SARMAG;
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan archive %s\n", archive );
|
||||
|
||||
while( read( fd, &ar_hdr, SARHDR ) == SARHDR &&
|
||||
!memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG ) )
|
||||
{
|
||||
char lar_name[256];
|
||||
long lar_date;
|
||||
long lar_size;
|
||||
long lar_offset;
|
||||
char *c;
|
||||
char *src, *dest;
|
||||
|
||||
strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
|
||||
|
||||
sscanf( ar_hdr.ar_date, "%ld", &lar_date );
|
||||
sscanf( ar_hdr.ar_size, "%ld", &lar_size );
|
||||
|
||||
if (ar_hdr.ar_name[0] == '/')
|
||||
{
|
||||
if (ar_hdr.ar_name[1] == '/')
|
||||
{
|
||||
/* this is the "string table" entry of the symbol table,
|
||||
** which holds strings of filenames that are longer than
|
||||
** 15 characters (ie. don't fit into a ar_name
|
||||
*/
|
||||
|
||||
string_table = (char *)malloc(lar_size);
|
||||
lseek(fd, offset + SARHDR, 0);
|
||||
if (read(fd, string_table, lar_size) != lar_size)
|
||||
printf("error reading string table\n");
|
||||
}
|
||||
else if (string_table && ar_hdr.ar_name[1] != ' ')
|
||||
{
|
||||
/* Long filenames are recognized by "/nnnn" where nnnn is
|
||||
** the offset of the string in the string table represented
|
||||
** in ASCII decimals.
|
||||
*/
|
||||
dest = lar_name;
|
||||
lar_offset = atoi(lar_name + 1);
|
||||
src = &string_table[lar_offset];
|
||||
while (*src != '/')
|
||||
*dest++ = *src++;
|
||||
*dest = '/';
|
||||
}
|
||||
}
|
||||
|
||||
c = lar_name - 1;
|
||||
while( *++c != ' ' && *c != '/' )
|
||||
;
|
||||
*c = '\0';
|
||||
|
||||
if ( DEBUG_BINDSCAN )
|
||||
printf( "archive name %s found\n", lar_name );
|
||||
|
||||
sprintf( buf, "%s(%s)", archive, lar_name );
|
||||
|
||||
(*func)( buf, 1 /* time valid */, (time_t)lar_date );
|
||||
|
||||
offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
|
||||
lseek( fd, offset, 0 );
|
||||
}
|
||||
|
||||
if (string_table)
|
||||
free(string_table);
|
||||
|
||||
close( fd );
|
||||
|
||||
# endif /* NO_AR */
|
||||
|
||||
}
|
||||
|
||||
# else /* AIAMAG - RS6000 AIX */
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
struct fl_hdr fl_hdr;
|
||||
|
||||
struct {
|
||||
struct ar_hdr hdr;
|
||||
char pad[ 256 ];
|
||||
} ar_hdr ;
|
||||
|
||||
char buf[ MAXJPATH ];
|
||||
long offset;
|
||||
int fd;
|
||||
|
||||
if( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
|
||||
return;
|
||||
|
||||
if( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ ||
|
||||
strncmp( AIAMAG, fl_hdr.fl_magic, SAIAMAG ) )
|
||||
{
|
||||
close( fd );
|
||||
return;
|
||||
}
|
||||
|
||||
sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan archive %s\n", archive );
|
||||
|
||||
while( offset > 0 &&
|
||||
lseek( fd, offset, 0 ) >= 0 &&
|
||||
read( fd, &ar_hdr, sizeof( ar_hdr ) ) >= sizeof( ar_hdr.hdr ) )
|
||||
{
|
||||
long lar_date;
|
||||
int lar_namlen;
|
||||
|
||||
sscanf( ar_hdr.hdr.ar_namlen, "%d", &lar_namlen );
|
||||
sscanf( ar_hdr.hdr.ar_date, "%ld", &lar_date );
|
||||
sscanf( ar_hdr.hdr.ar_nxtmem, "%ld", &offset );
|
||||
|
||||
if( !lar_namlen )
|
||||
continue;
|
||||
|
||||
ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
|
||||
|
||||
sprintf( buf, "%s(%s)", archive, ar_hdr.hdr._ar_name.ar_name );
|
||||
|
||||
(*func)( buf, 1 /* time valid */, (time_t)lar_date );
|
||||
}
|
||||
|
||||
close( fd );
|
||||
}
|
||||
|
||||
# endif /* AIAMAG - RS6000 AIX */
|
||||
|
||||
# endif /* USE_FILEUNIX */
|
||||
|
||||
302
historic/jam/src/filevms.c
Normal file
302
historic/jam/src/filevms.c
Normal file
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
|
||||
# ifdef OS_VMS
|
||||
|
||||
/*
|
||||
* filevms.c - scan directories and libaries on VMS
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* file_dirscan() - scan a directory for files
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
* file_archscan() - scan an archive for files
|
||||
*
|
||||
* File_dirscan() and file_archscan() call back a caller provided function
|
||||
* for each file found. A flag to this callback function lets file_dirscan()
|
||||
* and file_archscan() indicate that a timestamp is being provided with the
|
||||
* file. If file_dirscan() or file_archscan() do not provide the file's
|
||||
* timestamp, interested parties may later call file_time().
|
||||
*
|
||||
* 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
|
||||
* 05/03/96 (seiwald) - split into pathvms.c
|
||||
*/
|
||||
|
||||
# include <rms.h>
|
||||
# include <iodef.h>
|
||||
# include <ssdef.h>
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <descrip.h>
|
||||
|
||||
#include <lbrdef.h>
|
||||
#include <credef.h>
|
||||
#include <mhddef.h>
|
||||
#include <lhidef.h>
|
||||
#include <lib$routines.h>
|
||||
#include <starlet.h>
|
||||
|
||||
/* Supply missing prototypes for lbr$-routines*/
|
||||
int lbr$close();
|
||||
int lbr$get_index();
|
||||
int lbr$ini_control();
|
||||
int lbr$open();
|
||||
int lbr$set_module();
|
||||
|
||||
/*
|
||||
* unlink() - remove a file
|
||||
*/
|
||||
|
||||
#if __CRTL_VER < 70000000
|
||||
|
||||
unlink( char *f )
|
||||
{
|
||||
remove( f );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
file_cvttime(
|
||||
unsigned int *curtime,
|
||||
time_t *unixtime )
|
||||
{
|
||||
static const size_t divisor = 10000000;
|
||||
static unsigned int bastim[2] = { 0x4BEB4000, 0x007C9567 }; /* 1/1/1970 */
|
||||
int delta[2], remainder;
|
||||
|
||||
lib$subx( curtime, bastim, delta );
|
||||
lib$ediv( &divisor, delta, unixtime, &remainder );
|
||||
}
|
||||
|
||||
# define DEFAULT_FILE_SPECIFICATION "[]*.*;0"
|
||||
|
||||
# define min( a,b ) ((a)<(b)?(a):(b))
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
|
||||
struct FAB xfab;
|
||||
struct NAM xnam;
|
||||
struct XABDAT xab;
|
||||
char esa[256];
|
||||
char filename[256];
|
||||
string filename2[1];
|
||||
char dirname[256];
|
||||
register int status;
|
||||
FILENAME f;
|
||||
|
||||
memset( (char *)&f, '\0', sizeof( f ) );
|
||||
|
||||
f.f_root.ptr = dir;
|
||||
f.f_root.len = strlen( dir );
|
||||
|
||||
/* get the input file specification
|
||||
*/
|
||||
xnam = cc$rms_nam;
|
||||
xnam.nam$l_esa = esa;
|
||||
xnam.nam$b_ess = sizeof( esa ) - 1;
|
||||
xnam.nam$l_rsa = filename;
|
||||
xnam.nam$b_rss = min( sizeof( filename ) - 1, NAM$C_MAXRSS );
|
||||
|
||||
xab = cc$rms_xabdat; /* initialize extended attributes */
|
||||
xab.xab$b_cod = XAB$C_DAT; /* ask for date */
|
||||
xab.xab$l_nxt = NULL; /* terminate XAB chain */
|
||||
|
||||
xfab = cc$rms_fab;
|
||||
xfab.fab$l_dna = DEFAULT_FILE_SPECIFICATION;
|
||||
xfab.fab$b_dns = sizeof( DEFAULT_FILE_SPECIFICATION ) - 1;
|
||||
xfab.fab$l_fop = FAB$M_NAM;
|
||||
xfab.fab$l_fna = dir; /* address of file name */
|
||||
xfab.fab$b_fns = strlen( dir ); /* length of file name */
|
||||
xfab.fab$l_nam = &xnam; /* address of NAB block */
|
||||
xfab.fab$l_xab = (char *)&xab; /* address of XAB block */
|
||||
|
||||
|
||||
status = sys$parse( &xfab );
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan directory %s\n", dir );
|
||||
|
||||
if ( !( status & 1 ) )
|
||||
return;
|
||||
|
||||
|
||||
|
||||
/* Add bogus directory for [000000] */
|
||||
|
||||
if( !strcmp( dir, "[000000]" ) )
|
||||
{
|
||||
(*func)( "[000000]", 1 /* time valid */, 1 /* old but true */ );
|
||||
}
|
||||
|
||||
/* Add bogus directory for [] */
|
||||
|
||||
if( !strcmp( dir, "[]" ) )
|
||||
{
|
||||
(*func)( "[]", 1 /* time valid */, 1 /* old but true */ );
|
||||
(*func)( "[-]", 1 /* time valid */, 1 /* old but true */ );
|
||||
}
|
||||
|
||||
string_new( filename2 );
|
||||
while ( (status = sys$search( &xfab )) & 1 )
|
||||
{
|
||||
char *s;
|
||||
time_t time;
|
||||
|
||||
/* "I think that might work" - eml */
|
||||
|
||||
sys$open( &xfab );
|
||||
sys$close( &xfab );
|
||||
|
||||
file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
|
||||
|
||||
filename[xnam.nam$b_rsl] = '\0';
|
||||
|
||||
/* What we do with the name depends on the suffix: */
|
||||
/* .dir is a directory */
|
||||
/* .xxx is a file with a suffix */
|
||||
/* . is no suffix at all */
|
||||
|
||||
if( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
|
||||
{
|
||||
/* directory */
|
||||
sprintf( dirname, "[.%.*s]", xnam.nam$b_name, xnam.nam$l_name );
|
||||
f.f_dir.ptr = dirname;
|
||||
f.f_dir.len = strlen( dirname );
|
||||
f.f_base.ptr = 0;
|
||||
f.f_base.len = 0;
|
||||
f.f_suffix.ptr = 0;
|
||||
f.f_suffix.len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* normal file with a suffix */
|
||||
f.f_dir.ptr = 0;
|
||||
f.f_dir.len = 0;
|
||||
f.f_base.ptr = xnam.nam$l_name;
|
||||
f.f_base.len = xnam.nam$b_name;
|
||||
f.f_suffix.ptr = xnam.nam$l_type;
|
||||
f.f_suffix.len = xnam.nam$b_type;
|
||||
}
|
||||
|
||||
string_truncate( filename2, 0 );
|
||||
file_build( &f, filename2, 0 );
|
||||
|
||||
/*
|
||||
if( DEBUG_SEARCH )
|
||||
printf("root '%s' base %.*s suf %.*s = %s\n",
|
||||
dir,
|
||||
xnam.nam$b_name, xnam.nam$l_name,
|
||||
xnam.nam$b_type, xnam.nam$l_type,
|
||||
filename2);
|
||||
*/
|
||||
|
||||
(*func)( filename2->value, 1 /* time valid */, time );
|
||||
}
|
||||
string_free( filename2 );
|
||||
|
||||
if ( status != RMS$_NMF && status != RMS$_FNF )
|
||||
lib$signal( xfab.fab$l_sts, xfab.fab$l_stv );
|
||||
}
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
/* This should never be called, as all files are */
|
||||
/* timestampped in file_dirscan() and file_archscan() */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *VMS_archive = 0;
|
||||
static void (*VMS_func)( char *file, int status, time_t t ) = 0;
|
||||
static void *context;
|
||||
|
||||
static int
|
||||
file_archmember(
|
||||
struct dsc$descriptor_s *module,
|
||||
unsigned long *rfa )
|
||||
{
|
||||
static struct dsc$descriptor_s bufdsc =
|
||||
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
|
||||
|
||||
struct mhddef *mhd;
|
||||
char filename[128];
|
||||
char buf[ MAXJPATH ];
|
||||
|
||||
int status;
|
||||
time_t library_date;
|
||||
|
||||
register int i;
|
||||
register char *p;
|
||||
|
||||
bufdsc.dsc$a_pointer = filename;
|
||||
bufdsc.dsc$w_length = sizeof( filename );
|
||||
status = lbr$set_module( &context, rfa, &bufdsc,
|
||||
&bufdsc.dsc$w_length, NULL );
|
||||
if ( !(status & 1) )
|
||||
return ( 1 );
|
||||
|
||||
mhd = (struct mhddef *)filename;
|
||||
|
||||
file_cvttime( &mhd->mhd$l_datim, &library_date );
|
||||
|
||||
for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; i++, p++ )
|
||||
filename[i] = *p;
|
||||
|
||||
filename[i] = '\0';
|
||||
|
||||
sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
|
||||
|
||||
(*VMS_func)( buf, 1 /* time valid */, (time_t)library_date );
|
||||
|
||||
return ( 1 );
|
||||
}
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
void (*func)( char *file, int status, time_t t ) )
|
||||
{
|
||||
static struct dsc$descriptor_s library =
|
||||
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
|
||||
|
||||
unsigned long lfunc = LBR$C_READ;
|
||||
unsigned long typ = LBR$C_TYP_UNK;
|
||||
unsigned long index = 1;
|
||||
|
||||
register int status;
|
||||
|
||||
VMS_archive = archive;
|
||||
VMS_func = func;
|
||||
|
||||
status = lbr$ini_control( &context, &lfunc, &typ, NULL );
|
||||
if ( !( status & 1 ) )
|
||||
return;
|
||||
|
||||
library.dsc$a_pointer = archive;
|
||||
library.dsc$w_length = strlen( archive );
|
||||
|
||||
status = lbr$open( &context, &library, NULL, NULL, NULL, NULL, NULL );
|
||||
if ( !( status & 1 ) )
|
||||
return;
|
||||
|
||||
(void) lbr$get_index( &context, &index, file_archmember, NULL );
|
||||
|
||||
(void) lbr$close( &context );
|
||||
}
|
||||
|
||||
# endif /* VMS */
|
||||
|
||||
19
historic/jam/src/frames.h
Normal file
19
historic/jam/src/frames.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef FRAMES_DWA20011021_H
|
||||
# define FRAMES_DWA20011021_H
|
||||
|
||||
# include "lists.h"
|
||||
# include "modules.h"
|
||||
|
||||
typedef struct frame FRAME;
|
||||
|
||||
struct frame
|
||||
{
|
||||
FRAME* prev;
|
||||
LOL args[1];
|
||||
module* module;
|
||||
};
|
||||
|
||||
void frame_init( FRAME* ); /* implemented in compile.c */
|
||||
void frame_free( FRAME* ); /* implemented in compile.c */
|
||||
|
||||
#endif // FRAMES_DWA20011021_H
|
||||
157
historic/jam/src/glob.c
Normal file
157
historic/jam/src/glob.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 1994 Christopher Seiwald. All rights reserved.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* glob.c - match a string against a simple pattern
|
||||
*
|
||||
* Understands the following patterns:
|
||||
*
|
||||
* * any number of characters
|
||||
* ? any single character
|
||||
* [a-z] any single character in the range a-z
|
||||
* [^a-z] any single character not in the range a-z
|
||||
* \x match x
|
||||
*
|
||||
* External functions:
|
||||
*
|
||||
* glob() - match a string against a simple pattern
|
||||
*
|
||||
* Internal functions:
|
||||
*
|
||||
* globchars() - build a bitlist to check for character group match
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
|
||||
# define CHECK_BIT( tab, bit ) ( tab[ (bit)/8 ] & (1<<( (bit)%8 )) )
|
||||
# define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
|
||||
|
||||
static void globchars( char *s, char *e, char *b );
|
||||
|
||||
/*
|
||||
* glob() - match a string against a simple pattern
|
||||
*/
|
||||
|
||||
int
|
||||
glob(
|
||||
register char *c,
|
||||
register char *s )
|
||||
{
|
||||
char bitlist[ BITLISTSIZE ];
|
||||
char *here;
|
||||
|
||||
for( ;; )
|
||||
switch( *c++ )
|
||||
{
|
||||
case '\0':
|
||||
return *s ? -1 : 0;
|
||||
|
||||
case '?':
|
||||
if( !*s++ )
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
/* scan for matching ] */
|
||||
|
||||
here = c;
|
||||
do if( !*c++ )
|
||||
return 1;
|
||||
while( here == c || *c != ']' );
|
||||
c++;
|
||||
|
||||
/* build character class bitlist */
|
||||
|
||||
globchars( here, c, bitlist );
|
||||
|
||||
if( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
|
||||
return 1;
|
||||
s++;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
here = s;
|
||||
|
||||
while( *s )
|
||||
s++;
|
||||
|
||||
/* Try to match the rest of the pattern in a recursive */
|
||||
/* call. If the match fails we'll back up chars, retrying. */
|
||||
|
||||
while( s != here )
|
||||
{
|
||||
int r;
|
||||
|
||||
/* A fast path for the last token in a pattern */
|
||||
|
||||
r = *c ? glob( c, s ) : *s ? -1 : 0;
|
||||
|
||||
if( !r )
|
||||
return 0;
|
||||
else if( r < 0 )
|
||||
return 1;
|
||||
|
||||
--s;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
/* Force literal match of next char. */
|
||||
|
||||
if( !*c || *s++ != *c++ )
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if( *s++ != c[-1] )
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* globchars() - build a bitlist to check for character group match
|
||||
*/
|
||||
|
||||
static void
|
||||
globchars(
|
||||
char *s,
|
||||
char *e,
|
||||
char *b )
|
||||
{
|
||||
int neg = 0;
|
||||
|
||||
memset( b, '\0', BITLISTSIZE );
|
||||
|
||||
if( *s == '^')
|
||||
neg++, s++;
|
||||
|
||||
while( s < e )
|
||||
{
|
||||
int c;
|
||||
|
||||
if( s+2 < e && s[1] == '-' )
|
||||
{
|
||||
for( c = s[0]; c <= s[2]; c++ )
|
||||
b[ c/8 ] |= (1<<(c%8));
|
||||
s += 3;
|
||||
} else {
|
||||
c = *s++;
|
||||
b[ c/8 ] |= (1<<(c%8));
|
||||
}
|
||||
}
|
||||
|
||||
if( neg )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < BITLISTSIZE; i++ )
|
||||
b[ i ] ^= 0377;
|
||||
}
|
||||
|
||||
/* Don't include \0 in either $[chars] or $[^chars] */
|
||||
|
||||
b[0] &= 0376;
|
||||
}
|
||||
277
historic/jam/src/hash.c
Normal file
277
historic/jam/src/hash.c
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "hash.h"
|
||||
|
||||
/*
|
||||
* hash.c - simple in-memory hashing routines
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* hashinit() - initialize a hash table, returning a handle
|
||||
* hashitem() - find a record in the table, and optionally enter a new one
|
||||
* hashdone() - free a hash table, given its handle
|
||||
*
|
||||
* Internal routines:
|
||||
*
|
||||
* hashrehash() - resize and rebuild hp->tab, the hash table
|
||||
*
|
||||
* 4/29/93 - ensure ITEM's are aligned
|
||||
*/
|
||||
|
||||
char *hashsccssid="@(#)hash.c 1.14 () 6/20/88";
|
||||
|
||||
/* Header attached to all data items entered into a hash table. */
|
||||
|
||||
struct hashhdr {
|
||||
struct item *next;
|
||||
int keyval; /* for quick comparisons */
|
||||
} ;
|
||||
|
||||
/* This structure overlays the one handed to hashenter(). */
|
||||
/* It's actual size is given to hashinit(). */
|
||||
|
||||
struct hashdata {
|
||||
char *key;
|
||||
/* rest of user data */
|
||||
} ;
|
||||
|
||||
typedef struct item {
|
||||
struct hashhdr hdr;
|
||||
struct hashdata data;
|
||||
} ITEM ;
|
||||
|
||||
# define MAX_LISTS 32
|
||||
|
||||
struct hash
|
||||
{
|
||||
/*
|
||||
* the hash table, just an array of item pointers
|
||||
*/
|
||||
struct {
|
||||
int nel;
|
||||
ITEM **base;
|
||||
} tab;
|
||||
|
||||
int bloat; /* tab.nel / items.nel */
|
||||
int inel; /* initial number of elements */
|
||||
|
||||
/*
|
||||
* the array of records, maintained by these routines
|
||||
* essentially a microallocator
|
||||
*/
|
||||
struct {
|
||||
int more; /* how many more ITEMs fit in lists[ list ] */
|
||||
char *next; /* where to put more ITEMs in lists[ list ] */
|
||||
int datalen; /* length of records in this hash table */
|
||||
int size; /* sizeof( ITEM ) + aligned datalen */
|
||||
int nel; /* total ITEMs held by all lists[] */
|
||||
int list; /* index into lists[] */
|
||||
|
||||
struct {
|
||||
int nel; /* total ITEMs held by this list */
|
||||
char *base; /* base of ITEMs array */
|
||||
} lists[ MAX_LISTS ];
|
||||
} items;
|
||||
|
||||
char *name; /* just for hashstats() */
|
||||
} ;
|
||||
|
||||
static void hashrehash( struct hash *hp );
|
||||
static void hashstat( struct hash *hp );
|
||||
|
||||
/*
|
||||
* hashitem() - find a record in the table, and optionally enter a new one
|
||||
*/
|
||||
|
||||
int
|
||||
hashitem(
|
||||
register struct hash *hp,
|
||||
HASHDATA **data,
|
||||
int enter )
|
||||
{
|
||||
ITEM **base;
|
||||
register ITEM *i;
|
||||
char *b = (*data)->key;
|
||||
int keyval;
|
||||
|
||||
if( enter && !hp->items.more )
|
||||
hashrehash( hp );
|
||||
|
||||
if( !enter && !hp->items.nel )
|
||||
return 0;
|
||||
|
||||
keyval = *b;
|
||||
|
||||
while( *b )
|
||||
keyval = keyval * 2147059363 + *b++;
|
||||
|
||||
keyval &= 0x7FFFFFFF;
|
||||
|
||||
base = hp->tab.base + ( keyval % hp->tab.nel );
|
||||
|
||||
for( i = *base; i; i = i->hdr.next )
|
||||
if( keyval == i->hdr.keyval &&
|
||||
!strcmp( i->data.key, (*data)->key ) )
|
||||
{
|
||||
*data = &i->data;
|
||||
return !0;
|
||||
}
|
||||
|
||||
if( enter )
|
||||
{
|
||||
i = (ITEM *)hp->items.next;
|
||||
hp->items.next += hp->items.size;
|
||||
hp->items.more--;
|
||||
memcpy( (char *)&i->data, (char *)*data, hp->items.datalen );
|
||||
i->hdr.keyval = keyval;
|
||||
i->hdr.next = *base;
|
||||
*base = i;
|
||||
*data = &i->data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* hashrehash() - resize and rebuild hp->tab, the hash table
|
||||
*/
|
||||
|
||||
static void hashrehash( register struct hash *hp )
|
||||
{
|
||||
int i = ++hp->items.list;
|
||||
|
||||
hp->items.more = i ? 2 * hp->items.nel : hp->inel;
|
||||
hp->items.next = (char *)malloc( hp->items.more * hp->items.size );
|
||||
|
||||
hp->items.lists[i].nel = hp->items.more;
|
||||
hp->items.lists[i].base = hp->items.next;
|
||||
hp->items.nel += hp->items.more;
|
||||
|
||||
if( hp->tab.base )
|
||||
free( (char *)hp->tab.base );
|
||||
|
||||
hp->tab.nel = hp->items.nel * hp->bloat;
|
||||
hp->tab.base = (ITEM **)malloc( hp->tab.nel * sizeof(ITEM **) );
|
||||
|
||||
memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
|
||||
|
||||
for( i = 0; i < hp->items.list; i++ )
|
||||
{
|
||||
int nel = hp->items.lists[i].nel;
|
||||
char *next = hp->items.lists[i].base;
|
||||
|
||||
for( ; nel--; next += hp->items.size )
|
||||
{
|
||||
register ITEM *i = (ITEM *)next;
|
||||
ITEM **ip = hp->tab.base + i->hdr.keyval % hp->tab.nel;
|
||||
|
||||
i->hdr.next = *ip;
|
||||
*ip = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hashenumerate( struct hash *hp, void (*f)(void*,void*), void* data )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i <= hp->items.list; i++ )
|
||||
{
|
||||
char *next = hp->items.lists[i].base;
|
||||
int nel = hp->items.lists[i].nel;
|
||||
if ( i == hp->items.list )
|
||||
nel -= hp->items.more;
|
||||
|
||||
for( ; nel--; next += hp->items.size )
|
||||
{
|
||||
register ITEM *i = (ITEM *)next;
|
||||
f(&i->data, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --- */
|
||||
|
||||
# define ALIGNED(x) ( ( x + sizeof( ITEM ) - 1 ) & ~( sizeof( ITEM ) - 1 ) )
|
||||
|
||||
/*
|
||||
* hashinit() - initialize a hash table, returning a handle
|
||||
*/
|
||||
|
||||
struct hash *
|
||||
hashinit(
|
||||
int datalen,
|
||||
char *name )
|
||||
{
|
||||
struct hash *hp = (struct hash *)malloc( sizeof( *hp ) );
|
||||
|
||||
hp->bloat = 3;
|
||||
hp->tab.nel = 0;
|
||||
hp->tab.base = (ITEM **)0;
|
||||
hp->items.more = 0;
|
||||
hp->items.datalen = datalen;
|
||||
hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
|
||||
hp->items.list = -1;
|
||||
hp->items.nel = 0;
|
||||
hp->inel = 11;
|
||||
hp->name = name;
|
||||
|
||||
return hp;
|
||||
}
|
||||
|
||||
/*
|
||||
* hashdone() - free a hash table, given its handle
|
||||
*/
|
||||
|
||||
void
|
||||
hashdone( struct hash *hp )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( !hp )
|
||||
return;
|
||||
|
||||
if( DEBUG_MEM )
|
||||
hashstat( hp );
|
||||
|
||||
if( hp->tab.base )
|
||||
free( (char *)hp->tab.base );
|
||||
for( i = 0; i <= hp->items.list; i++ )
|
||||
free( hp->items.lists[i].base );
|
||||
free( (char *)hp );
|
||||
}
|
||||
|
||||
/* ---- */
|
||||
|
||||
static void
|
||||
hashstat( struct hash *hp )
|
||||
{
|
||||
ITEM **tab = hp->tab.base;
|
||||
int nel = hp->tab.nel;
|
||||
int count = 0;
|
||||
int sets = 0;
|
||||
int run = ( tab[ nel - 1 ] != (ITEM *)0 );
|
||||
int i, here;
|
||||
|
||||
for( i = nel; i > 0; i-- )
|
||||
{
|
||||
if( here = ( *tab++ != (ITEM *)0 ) )
|
||||
count++;
|
||||
if( here && !run )
|
||||
sets++;
|
||||
run = here;
|
||||
}
|
||||
|
||||
printf( "%s table: %d+%d+%d (%dK+%dK) items+table+hash, %f density\n",
|
||||
hp->name,
|
||||
count,
|
||||
hp->items.nel,
|
||||
hp->tab.nel,
|
||||
hp->items.nel * hp->items.size / 1024,
|
||||
hp->tab.nel * sizeof( ITEM ** ) / 1024,
|
||||
(float)count / (float)sets );
|
||||
}
|
||||
19
historic/jam/src/hash.h
Normal file
19
historic/jam/src/hash.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* hash.h - simple in-memory hashing routines
|
||||
*/
|
||||
|
||||
typedef struct hashdata HASHDATA;
|
||||
|
||||
struct hash * hashinit( int datalen, char *name );
|
||||
int hashitem( struct hash *hp, HASHDATA **data, int enter );
|
||||
void hashdone( struct hash *hp );
|
||||
void hashenumerate( struct hash *hp, void (*f)(void*,void*), void* data );
|
||||
|
||||
# define hashenter( hp, data ) !hashitem( hp, data, !0 )
|
||||
# define hashcheck( hp, data ) hashitem( hp, data, 0 )
|
||||
135
historic/jam/src/hdrmacro.c
Normal file
135
historic/jam/src/hdrmacro.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "compile.h"
|
||||
# include "rules.h"
|
||||
# include "variable.h"
|
||||
# include "regexp.h"
|
||||
# include "hdrmacro.h"
|
||||
# include "hash.h"
|
||||
# include "newstr.h"
|
||||
# include "strings.h"
|
||||
|
||||
/*
|
||||
* hdrmacro.c - handle header files that define macros used in
|
||||
* #include statements.
|
||||
*
|
||||
* we look for lines like "#define MACRO <....>" or '#define MACRO " "'
|
||||
* in the target file. When found, we
|
||||
*
|
||||
* we then phony up a rule invocation like:
|
||||
*
|
||||
* $(HDRRULE) <target> : <resolved included files> ;
|
||||
*
|
||||
* External routines:
|
||||
* headers1() - scan a target for "#include MACRO" lines and try
|
||||
* to resolve them when needed
|
||||
*
|
||||
* Internal routines:
|
||||
* headers1() - using regexp, scan a file and build include LIST
|
||||
*
|
||||
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
|
||||
* 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
|
||||
* so that headers() doesn't have to mock up a parse structure
|
||||
* just to invoke a rule.
|
||||
*/
|
||||
|
||||
static LIST *header_macros1( LIST *l, char *file, int rec, regexp *re[] );
|
||||
|
||||
/* this type is used to store a dictionary of file header macros */
|
||||
typedef struct header_macro
|
||||
{
|
||||
char* symbol;
|
||||
char* filename; /* we could maybe use a LIST here ?? */
|
||||
|
||||
} HEADER_MACRO;
|
||||
|
||||
static struct hash* header_macros_hash = 0;
|
||||
|
||||
/*
|
||||
* headers() - scan a target for include files and call HDRRULE
|
||||
*/
|
||||
|
||||
# define MAXINC 10
|
||||
|
||||
void
|
||||
macro_headers( TARGET *t )
|
||||
{
|
||||
LIST *hdrrule;
|
||||
static regexp *re = 0;
|
||||
FILE *f;
|
||||
char buf[ 1024 ];
|
||||
int i;
|
||||
|
||||
if ( DEBUG_HEADER )
|
||||
printf( "macro header scan for %s\n", t->name );
|
||||
|
||||
/* this regexp is used to detect lines of the form */
|
||||
/* "#define MACRO <....>" or "#define MACRO "....." */
|
||||
/* in the header macro files.. */
|
||||
if ( re == 0 )
|
||||
{
|
||||
re = regex_compile(
|
||||
"^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*"
|
||||
"[<\"]([^\">]*)[\">].*$" );
|
||||
}
|
||||
|
||||
if( !( f = fopen( t->boundname, "r" ) ) )
|
||||
return;
|
||||
|
||||
while( fgets( buf, sizeof( buf ), f ) )
|
||||
{
|
||||
HEADER_MACRO var, *v = &var;
|
||||
|
||||
if ( regexec( re, buf ) && re->startp[1] )
|
||||
{
|
||||
/* we detected a line that looks like "#define MACRO filename */
|
||||
re->endp[1][0] = '\0';
|
||||
re->endp[2][0] = '\0';
|
||||
|
||||
if ( DEBUG_HEADER )
|
||||
printf( "macro '%s' used to define filename '%s' in '%s'\n",
|
||||
re->startp[1], re->startp[2], t->boundname );
|
||||
|
||||
/* add macro definition to hash table */
|
||||
if ( !header_macros_hash )
|
||||
header_macros_hash = hashinit( sizeof( HEADER_MACRO ), "hdrmacros" );
|
||||
|
||||
v->symbol = re->startp[1];
|
||||
v->filename = 0;
|
||||
if ( hashenter( header_macros_hash, (HASHDATA **)&v ) )
|
||||
{
|
||||
v->symbol = newstr( re->startp[1] ); /* never freed */
|
||||
v->filename = newstr( re->startp[2] ); /* never freed */
|
||||
}
|
||||
/* XXXX: FOR NOW, WE IGNORE MULTIPLE MACRO DEFINITIONS !! */
|
||||
/* WE MIGHT AS WELL USE A LIST TO STORE THEM.. */
|
||||
}
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
macro_header_get( const char* macro_name )
|
||||
{
|
||||
HEADER_MACRO var, *v = &var;
|
||||
|
||||
v->symbol = (char*)macro_name;
|
||||
|
||||
if( header_macros_hash && hashcheck( header_macros_hash, (HASHDATA **)&v ) )
|
||||
{
|
||||
if ( DEBUG_HEADER )
|
||||
printf( "### macro '%s' evaluated to '%s'\n", macro_name, v->filename );
|
||||
return v->filename;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
14
historic/jam/src/hdrmacro.h
Normal file
14
historic/jam/src/hdrmacro.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* hdrmacro.h - parses header files for #define MACRO <filename> or
|
||||
* #define MACRO "filename" definitions
|
||||
*/
|
||||
|
||||
void macro_headers( TARGET *t );
|
||||
|
||||
char* macro_header_get( const char* macro_name );
|
||||
164
historic/jam/src/headers.c
Normal file
164
historic/jam/src/headers.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "compile.h"
|
||||
# include "rules.h"
|
||||
# include "variable.h"
|
||||
# include "regexp.h"
|
||||
# include "headers.h"
|
||||
# include "hdrmacro.h"
|
||||
# include "newstr.h"
|
||||
|
||||
/*
|
||||
* headers.c - handle #includes in source files
|
||||
*
|
||||
* Using regular expressions provided as the variable $(HDRSCAN),
|
||||
* headers() searches a file for #include files and phonies up a
|
||||
* rule invocation:
|
||||
*
|
||||
* $(HDRRULE) <target> : <include files> ;
|
||||
*
|
||||
* External routines:
|
||||
* headers() - scan a target for include files and call HDRRULE
|
||||
*
|
||||
* Internal routines:
|
||||
* headers1() - using regexp, scan a file and build include LIST
|
||||
*
|
||||
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
|
||||
* 09/10/00 (seiwald) - replaced call to compile_rule with evaluate_rule,
|
||||
* so that headers() doesn't have to mock up a parse structure
|
||||
* just to invoke a rule.
|
||||
*/
|
||||
|
||||
static LIST *headers1( LIST *l, char *file, int rec, regexp *re[],
|
||||
regexp* re_macros );
|
||||
|
||||
/*
|
||||
* headers() - scan a target for include files and call HDRRULE
|
||||
*/
|
||||
|
||||
# define MAXINC 10
|
||||
|
||||
void
|
||||
headers( TARGET *t )
|
||||
{
|
||||
LIST *hdrscan;
|
||||
LIST *hdrrule;
|
||||
LIST *headlist = 0;
|
||||
regexp *re[ MAXINC ];
|
||||
int rec = 0;
|
||||
|
||||
/* the following regexp is used to detect cases where a */
|
||||
/* file is included through a line line "#include MACRO" */
|
||||
static regexp *re_macros = 0;
|
||||
if ( re_macros == 0 )
|
||||
{
|
||||
re_macros = regex_compile(
|
||||
"^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
|
||||
}
|
||||
|
||||
if( !( hdrscan = var_get( "HDRSCAN" ) ) ||
|
||||
!( hdrrule = var_get( "HDRRULE" ) ) )
|
||||
return;
|
||||
|
||||
if( DEBUG_HEADER )
|
||||
printf( "header scan %s\n", t->name );
|
||||
|
||||
/* Compile all regular expressions in HDRSCAN */
|
||||
|
||||
while( rec < MAXINC && hdrscan )
|
||||
{
|
||||
re[rec++] = regex_compile( hdrscan->string );
|
||||
hdrscan = list_next( hdrscan );
|
||||
}
|
||||
|
||||
/* Doctor up call to HDRRULE rule */
|
||||
/* Call headers1() to get LIST of included files. */
|
||||
{
|
||||
FRAME frame[1];
|
||||
frame_init( frame );
|
||||
lol_add( frame->args, list_new( L0, t->name ) );
|
||||
lol_add( frame->args, headers1( headlist, t->boundname, rec, re, re_macros ) );
|
||||
|
||||
if( lol_get( frame->args, 1 ) )
|
||||
evaluate_rule( hdrrule->string, frame );
|
||||
|
||||
/* Clean up */
|
||||
|
||||
frame_free( frame );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* headers1() - using regexp, scan a file and build include LIST
|
||||
*/
|
||||
|
||||
static LIST *
|
||||
headers1(
|
||||
LIST *l,
|
||||
char *file,
|
||||
int rec,
|
||||
regexp *re[],
|
||||
regexp *re_macros )
|
||||
{
|
||||
FILE *f;
|
||||
char buf[ 1024 ];
|
||||
int i;
|
||||
|
||||
if( !( f = fopen( file, "r" ) ) )
|
||||
return l;
|
||||
|
||||
while( fgets( buf, sizeof( buf ), f ) )
|
||||
{
|
||||
for( i = 0; i < rec; i++ )
|
||||
if( regexec( re[i], buf ) && re[i]->startp[1] )
|
||||
{
|
||||
re[i]->endp[1][0] = '\0';
|
||||
|
||||
if( DEBUG_HEADER )
|
||||
printf( "header found: %s\n", re[i]->startp[1] );
|
||||
|
||||
l = list_new( l, newstr( re[i]->startp[1] ) );
|
||||
}
|
||||
|
||||
/* special treatment for #include MACRO */
|
||||
if ( regexec( re_macros, buf ) && re_macros->startp[1] )
|
||||
{
|
||||
char* header_filename;
|
||||
|
||||
re_macros->endp[1][0] = '\0';
|
||||
|
||||
if ( DEBUG_HEADER )
|
||||
printf( "macro header found: %s", re_macros->startp[1] );
|
||||
|
||||
header_filename = macro_header_get( re_macros->startp[1] );
|
||||
if (header_filename)
|
||||
{
|
||||
if ( DEBUG_HEADER )
|
||||
printf( " resolved to '%s'\n", header_filename );
|
||||
l = list_new( l, newstr( header_filename ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( DEBUG_HEADER )
|
||||
printf( " ignored !!\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
regerror( char *s )
|
||||
{
|
||||
printf( "re error %s\n", s );
|
||||
}
|
||||
11
historic/jam/src/headers.h
Normal file
11
historic/jam/src/headers.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* headers.h - handle #includes in source files
|
||||
*/
|
||||
|
||||
void headers( TARGET *t );
|
||||
385
historic/jam/src/jam.c
Normal file
385
historic/jam/src/jam.c
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* /+\
|
||||
* +\ Copyright 1993, 2000 Christopher Seiwald.
|
||||
* \+/
|
||||
*
|
||||
* 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 and Jamlang.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
|
||||
* | | \
|
||||
* | | \
|
||||
* | | \
|
||||
* timestamp command execute
|
||||
*
|
||||
*
|
||||
* The support routines are called by all of the above, but themselves
|
||||
* are layered thus:
|
||||
*
|
||||
* variable|expand
|
||||
* / | | |
|
||||
* / | | |
|
||||
* / | | |
|
||||
* lists | | filesys
|
||||
* \ | |
|
||||
* \ | |
|
||||
* \ | |
|
||||
* newstr |
|
||||
* \ |
|
||||
* \ |
|
||||
* \ |
|
||||
* hash
|
||||
*
|
||||
* Roughly, the modules are:
|
||||
*
|
||||
* 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
|
||||
* fileunix.c - manipulate file names and scan directories on UNIX
|
||||
* filevms.c - manipulate file names and scan directories on VMS
|
||||
* fileos2.c - manipulate file names and scan directories on OS/2
|
||||
* filent.c - manipulate file names and scan directories on Windows
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
# 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 "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
|
||||
|
||||
struct globs globs = {
|
||||
0, /* noexec */
|
||||
1, /* jobs */
|
||||
# ifdef OS_MAC
|
||||
{ 0, 0 }, /* debug - suppress tracing output */
|
||||
# else
|
||||
{ 0, 1 }, /* debug ... */
|
||||
# endif
|
||||
0 /* output commands, not run them */
|
||||
} ;
|
||||
|
||||
/* 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 MPW
|
||||
QDGlobals qd;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* on Win32-LCC */
|
||||
# if defined( OS_NT ) && defined( __LCC__ )
|
||||
# define use_environ _environ
|
||||
# endif
|
||||
|
||||
|
||||
# ifndef use_environ
|
||||
# define use_environ environ
|
||||
# if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
|
||||
extern char **environ;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
extern int yydebug;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void run_unit_tests()
|
||||
{
|
||||
var_expand_unit_test();
|
||||
}
|
||||
#endif
|
||||
|
||||
int main( int argc, char **argv, char **arg_environ )
|
||||
{
|
||||
int n;
|
||||
char *s;
|
||||
struct option optv[N_OPTS];
|
||||
char *all = "all";
|
||||
int anyhow = 0;
|
||||
int status;
|
||||
|
||||
# ifdef OS_MAC
|
||||
InitGraf(&qd.thePort);
|
||||
# endif
|
||||
|
||||
argc--, argv++;
|
||||
|
||||
if( ( n = getoptions( argc, argv, "d:j:f:s:t:ano:v", optv ) ) < 0 )
|
||||
{
|
||||
printf( "\nusage: jam [ options ] targets...\n\n" );
|
||||
|
||||
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( "-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( "-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\n" );
|
||||
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
argc -= n, argv += n;
|
||||
|
||||
/* Version info. */
|
||||
|
||||
if( ( s = getoptval( optv, 'v', 0 ) ) )
|
||||
{
|
||||
printf( "Jam/MR " );
|
||||
printf( "Version %s. ", VERSION );
|
||||
printf( "Copyright 1993, 2000 Christopher Seiwald. " );
|
||||
printf( "%s.\n", OSMINOR );
|
||||
|
||||
return EXITOK;
|
||||
}
|
||||
|
||||
/* Pick up interesting options */
|
||||
|
||||
if( ( s = getoptval( optv, 'n', 0 ) ) )
|
||||
globs.noexec++, globs.debug[2] = 1;
|
||||
|
||||
if( ( s = getoptval( optv, 'a', 0 ) ) )
|
||||
anyhow++;
|
||||
|
||||
if( ( s = getoptval( optv, 'j', 0 ) ) )
|
||||
globs.jobs = 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;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
run_unit_tests();
|
||||
#endif // NDEBUG
|
||||
if ( DEBUG_PARSE )
|
||||
yydebug = 1;
|
||||
|
||||
/* 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( L0, newstr( "03" ) ), newstr( "00" ) ),
|
||||
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 */
|
||||
|
||||
/*
|
||||
* Jam defined variables OS, OSPLAT
|
||||
*/
|
||||
|
||||
var_defines( othersyms );
|
||||
|
||||
/* load up environment variables */
|
||||
|
||||
var_defines( use_environ );
|
||||
|
||||
/* 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 );
|
||||
}
|
||||
|
||||
/* Initialize builtins */
|
||||
|
||||
|
||||
compile_builtins();
|
||||
|
||||
/* 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 */
|
||||
|
||||
if( !argc )
|
||||
status |= make( 1, &all, anyhow );
|
||||
else
|
||||
status |= make( argc, argv, anyhow );
|
||||
|
||||
if ( DEBUG_PROFILE )
|
||||
profile_dump();
|
||||
|
||||
/* Widely scattered cleanup */
|
||||
|
||||
var_done();
|
||||
donerules();
|
||||
donestamps();
|
||||
donestr();
|
||||
|
||||
/* close cmdout */
|
||||
|
||||
if( globs.cmdout )
|
||||
fclose( globs.cmdout );
|
||||
|
||||
return status ? EXITBAD : EXITOK;
|
||||
}
|
||||
483
historic/jam/src/jam.h
Normal file
483
historic/jam/src/jam.h
Normal file
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jam.h - includes and globals for jam
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 04/21/94 (seiwald) - DGUX is __DGUX__, not just __DGUX.
|
||||
* 05/04/94 (seiwald) - new globs.jobs (-j jobs)
|
||||
* 11/01/94 (wingerd) - let us define path of Jambase at compile time.
|
||||
* 12/30/94 (wingerd) - changed command buffer size for NT (MS-DOS shell).
|
||||
* 02/22/95 (seiwald) - Jambase now in /usr/local/lib.
|
||||
* 04/30/95 (seiwald) - FreeBSD added. Live Free or Die.
|
||||
* 05/10/95 (seiwald) - SPLITPATH character set up here.
|
||||
* 08/20/95 (seiwald) - added LINUX.
|
||||
* 08/21/95 (seiwald) - added NCR.
|
||||
* 10/23/95 (seiwald) - added SCO.
|
||||
* 01/03/96 (seiwald) - SINIX (nixdorf) added.
|
||||
* 03/13/96 (seiwald) - Jambase now compiled in; remove JAMBASE variable.
|
||||
* 04/29/96 (seiwald) - AIX now has 31 and 42 OSVERs.
|
||||
* 11/21/96 (peterk) - added BeOS with MW CW mwcc
|
||||
* 12/21/96 (seiwald) - OSPLAT now defined for NT.
|
||||
* 07/19/99 (sickel) - Mac OS X Server and Client support added
|
||||
* 02/18/00 (belmonte)- Support for Cygwin.
|
||||
* 09/12/00 (seiwald) - OSSYMS split to OSMAJOR/OSMINOR/OSPLAT
|
||||
* 12/29/00 (seiwald) - OSVER dropped.
|
||||
*/
|
||||
|
||||
/*
|
||||
* VMS, OPENVMS
|
||||
*/
|
||||
|
||||
# ifdef VMS
|
||||
|
||||
int unlink( char *f ); /* In filevms.c */
|
||||
|
||||
# include <types.h>
|
||||
# include <file.h>
|
||||
# include <stat.h>
|
||||
# include <stdio.h>
|
||||
# include <ctype.h>
|
||||
# include <stdlib.h>
|
||||
# include <signal.h>
|
||||
# include <string.h>
|
||||
# include <time.h>
|
||||
# include <unixlib.h>
|
||||
|
||||
# define OSMINOR "OS=VMS"
|
||||
# define OSMAJOR "VMS=true"
|
||||
# define OS_VMS
|
||||
# define MAXLINE 1024 /* longest 'together' actions */
|
||||
# define SPLITPATH ','
|
||||
# define EXITOK 1
|
||||
# define EXITBAD 0
|
||||
# define DOWNSHIFT_PATHS
|
||||
|
||||
/* This may be inaccurate */
|
||||
# ifndef __DECC
|
||||
# define OSPLAT "OSPLAT=VAX"
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Windows NT
|
||||
*/
|
||||
|
||||
# ifdef NT
|
||||
|
||||
# include <fcntl.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <ctype.h>
|
||||
# include <malloc.h>
|
||||
# include <memory.h>
|
||||
# include <signal.h>
|
||||
# include <string.h>
|
||||
# include <time.h>
|
||||
|
||||
# define OSMAJOR "NT=true"
|
||||
# define OSMINOR "OS=NT"
|
||||
# define OS_NT
|
||||
# define SPLITPATH ';'
|
||||
/* Windows NT 3.51 only allows 996 chars per line, but we deal */
|
||||
/* with problem in "execnt.c". */
|
||||
# define MAXLINE 2047 /* longest 'together' actions */
|
||||
# define USE_EXECNT
|
||||
# define USE_PATHUNIX
|
||||
# define PATH_DELIM '\\'
|
||||
# define DOWNSHIFT_PATHS
|
||||
|
||||
/* AS400 cross-compile from NT */
|
||||
|
||||
# ifdef AS400
|
||||
# undef OSMINOR
|
||||
# undef OSMAJOR
|
||||
# define OSMAJOR "AS400=true"
|
||||
# define OSMINOR "OS=AS400"
|
||||
# define OS_AS400
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
/*
|
||||
* OS2
|
||||
*/
|
||||
|
||||
# ifdef __OS2__
|
||||
|
||||
# include <fcntl.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <ctype.h>
|
||||
# include <malloc.h>
|
||||
# include <signal.h>
|
||||
# include <string.h>
|
||||
# include <time.h>
|
||||
|
||||
# define OSMAJOR "OS2=true"
|
||||
# define OSMINOR "OS=OS2"
|
||||
# define OS_OS2
|
||||
# define SPLITPATH ';'
|
||||
# define MAXLINE 996 /* longest 'together' actions */
|
||||
# define USE_EXECUNIX
|
||||
# define USE_PATHUNIX
|
||||
# define PATH_DELIM '\\'
|
||||
# define DOWNSHIFT_PATHS
|
||||
|
||||
# ifdef __EMX__
|
||||
# define USE_FILEUNIX
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Macintosh MPW
|
||||
*/
|
||||
|
||||
# ifdef macintosh
|
||||
|
||||
# include <time.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
|
||||
# define OSMAJOR "MAC=true"
|
||||
# define OSMINOR "OS=MAC"
|
||||
# define OS_MAC
|
||||
# define SPLITPATH ','
|
||||
|
||||
# endif
|
||||
|
||||
/*
|
||||
* God fearing UNIX
|
||||
*/
|
||||
|
||||
# ifndef OSMINOR
|
||||
|
||||
# define OSMAJOR "UNIX=true"
|
||||
# define USE_EXECUNIX
|
||||
# define USE_FILEUNIX
|
||||
# define USE_PATHUNIX
|
||||
# define PATH_DELIM '/'
|
||||
|
||||
# ifdef _AIX
|
||||
# define unix
|
||||
# define OSMINOR "OS=AIX"
|
||||
# define OS_AIX
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef AMIGA
|
||||
# define OSMINOR "OS=AMIGA"
|
||||
# define OS_AMIGA
|
||||
# endif
|
||||
# ifdef __BEOS__
|
||||
# define unix
|
||||
# define OSMINOR "OS=BEOS"
|
||||
# define OS_BEOS
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef __bsdi__
|
||||
# define OSMINOR "OS=BSDI"
|
||||
# define OS_BSDI
|
||||
# endif
|
||||
# if defined (COHERENT) && defined (_I386)
|
||||
# define OSMINOR "OS=COHERENT"
|
||||
# define OS_COHERENT
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef __cygwin__
|
||||
# define OSMINOR "OS=CYGWIN"
|
||||
# define OS_CYGWIN
|
||||
# endif
|
||||
# ifdef __FreeBSD__
|
||||
# define OSMINOR "OS=FREEBSD"
|
||||
# define OS_FREEBSD
|
||||
# endif
|
||||
# ifdef __DGUX__
|
||||
# define OSMINOR "OS=DGUX"
|
||||
# define OS_DGUX
|
||||
# endif
|
||||
# ifdef __hpux
|
||||
# define OSMINOR "OS=HPUX"
|
||||
# define OS_HPUX
|
||||
# endif
|
||||
# ifdef __OPENNT
|
||||
# define unix
|
||||
# define OSMINOR "OS=INTERIX"
|
||||
# define OS_INTERIX
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef __sgi
|
||||
# define OSMINOR "OS=IRIX"
|
||||
# define OS_IRIX
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef __ISC
|
||||
# define OSMINOR "OS=ISC"
|
||||
# define OS_ISC
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef linux
|
||||
# define OSMINOR "OS=LINUX"
|
||||
# define OS_LINUX
|
||||
# endif
|
||||
# ifdef __Lynx__
|
||||
# define OSMINOR "OS=LYNX"
|
||||
# define OS_LYNX
|
||||
# define NO_VFORK
|
||||
# define unix
|
||||
# endif
|
||||
# ifdef __MACHTEN__
|
||||
# define OSMINOR "OS=MACHTEN"
|
||||
# define OS_MACHTEN
|
||||
# endif
|
||||
# ifdef mpeix
|
||||
# define unix
|
||||
# define OSMINOR "OS=MPEIX"
|
||||
# define OS_MPEIX
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef __MVS__
|
||||
# define unix
|
||||
# define OSMINOR "OS=MVS"
|
||||
# define OS_MVS
|
||||
# endif
|
||||
# ifdef _ATT4
|
||||
# define OSMINOR "OS=NCR"
|
||||
# define OS_NCR
|
||||
# endif
|
||||
# ifdef __NetBSD__
|
||||
# define unix
|
||||
# define OSMINOR "OS=NETBSD"
|
||||
# define OS_NETBSD
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef __QNX__
|
||||
# ifdef __QNXNTO__
|
||||
# define OSMINOR "OS=QNXNTO"
|
||||
# define OS_QNXNTO
|
||||
# else
|
||||
# define unix
|
||||
# define OSMINOR "OS=QNX"
|
||||
# define OS_QNX
|
||||
# define NO_VFORK
|
||||
# define MAXLINE 996
|
||||
# endif
|
||||
# endif
|
||||
# ifdef NeXT
|
||||
# ifdef __APPLE__
|
||||
# define OSMINOR "OS=RHAPSODY"
|
||||
# define OS_RHAPSODY
|
||||
# else
|
||||
# define OSMINOR "OS=NEXT"
|
||||
# define OS_NEXT
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __APPLE__
|
||||
# define unix
|
||||
# define OSMINOR "OS=MACOSX"
|
||||
# define OS_MACOSX
|
||||
# endif
|
||||
# ifdef __osf__
|
||||
# define OSMINOR "OS=OSF"
|
||||
# define OS_OSF
|
||||
# endif
|
||||
# ifdef _SEQUENT_
|
||||
# define OSMINOR "OS=PTX"
|
||||
# define OS_PTX
|
||||
# endif
|
||||
# ifdef M_XENIX
|
||||
# define OSMINOR "OS=SCO"
|
||||
# define OS_SCO
|
||||
# define NO_VFORK
|
||||
# endif
|
||||
# ifdef sinix
|
||||
# define unix
|
||||
# define OSMINOR "OS=SINIX"
|
||||
# define OS_SINIX
|
||||
# endif
|
||||
# ifdef sun
|
||||
# if defined(__svr4__) || defined(__SVR4)
|
||||
# define OSMINOR "OS=SOLARIS"
|
||||
# define OS_SOLARIS
|
||||
# else
|
||||
# define OSMINOR "OS=SUNOS"
|
||||
# define OS_SUNOS
|
||||
# endif
|
||||
# endif
|
||||
# ifdef ultrix
|
||||
# define OSMINOR "OS=ULTRIX"
|
||||
# define OS_ULTRIX
|
||||
# endif
|
||||
# ifdef _UNICOS
|
||||
# define OSMINOR "OS=UNICOS"
|
||||
# define OS_UNICOS
|
||||
# endif
|
||||
# if defined(__USLC__) && !defined(M_XENIX)
|
||||
# define OSMINOR "OS=UNIXWARE"
|
||||
# define OS_UNIXWARE
|
||||
# endif
|
||||
# ifndef OSMINOR
|
||||
# define OSMINOR "OS=UNKNOWN"
|
||||
# endif
|
||||
|
||||
/* All the UNIX includes */
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
|
||||
# ifndef OS_MPEIX
|
||||
# include <sys/file.h>
|
||||
# endif
|
||||
|
||||
# include <fcntl.h>
|
||||
# include <stdio.h>
|
||||
# include <ctype.h>
|
||||
# include <signal.h>
|
||||
# include <string.h>
|
||||
# include <time.h>
|
||||
|
||||
# ifndef OS_QNX
|
||||
# include <memory.h>
|
||||
# endif
|
||||
|
||||
# ifndef OS_ULTRIX
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
|
||||
# if !defined(OS_BSDI) && \
|
||||
!defined(OS_FREEBSD) && \
|
||||
!defined(OS_NEXT) && \
|
||||
!defined(OS_MACHTEN) && \
|
||||
!defined(OS_MACOSX) && \
|
||||
!defined(OS_RHAPSODY) && \
|
||||
!defined(OS_MVS)
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
/*
|
||||
* OSPLAT definitions - suppressed when it's a one-of-a-kind
|
||||
*/
|
||||
|
||||
# if defined( _M_PPC ) || \
|
||||
defined( PPC ) || \
|
||||
defined( ppc ) || \
|
||||
defined( __powerpc__ ) || \
|
||||
defined( __ppc__ )
|
||||
# define OSPLAT "OSPLAT=PPC"
|
||||
# endif
|
||||
|
||||
# if defined( _ALPHA_ ) || \
|
||||
defined( __alpha__ )
|
||||
# define OSPLAT "OSPLAT=AXP"
|
||||
# endif
|
||||
|
||||
# if defined( _i386_ ) || \
|
||||
defined( __i386__ ) || \
|
||||
defined( _M_IX86 )
|
||||
# if !defined( OS_FREEBSD ) && \
|
||||
!defined( OS_OS2 ) && \
|
||||
!defined( OS_AS400 )
|
||||
# define OSPLAT "OSPLAT=X86"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __sparc__
|
||||
# if !defined( OS_SUNOS ) && \
|
||||
!defined( OS_SOLARIS )
|
||||
# define OSPLAT "OSPLAT=SPARC"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __mips__
|
||||
# if !defined( OS_SGI )
|
||||
# define OSPLAT "OSPLAT=MIPS"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifdef __arm__
|
||||
# define OSPLAT "OSPLAT=ARM"
|
||||
# endif
|
||||
|
||||
# if defined( __ia64__ ) || defined( __IA64__ )
|
||||
# define OSPLAT "OSPLAT=IA64"
|
||||
# endif
|
||||
|
||||
# ifdef __s390__
|
||||
# define OSPLAT "OSPLAT=390"
|
||||
# endif
|
||||
|
||||
# ifndef OSPLAT
|
||||
# define OSPLAT ""
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Jam implementation misc.
|
||||
*/
|
||||
|
||||
# ifndef MAXLINE
|
||||
# define MAXLINE 10240 /* longest 'together' actions' */
|
||||
# endif
|
||||
|
||||
# ifndef EXITOK
|
||||
# define EXITOK 0
|
||||
# define EXITBAD 1
|
||||
# endif
|
||||
|
||||
# ifndef SPLITPATH
|
||||
# define SPLITPATH ':'
|
||||
# endif
|
||||
|
||||
/* You probably don't need to muck with these. */
|
||||
|
||||
# define MAXSYM 1024 /* longest symbol in the environment */
|
||||
# define MAXJPATH 1024 /* longest filename */
|
||||
|
||||
# define MAXJOBS 64 /* silently enforce -j limit */
|
||||
# define MAXARGC 32 /* words in $(JAMSHELL) */
|
||||
|
||||
/* Jam private definitions below. */
|
||||
|
||||
# define DEBUG_MAX 12
|
||||
|
||||
struct globs {
|
||||
int noexec;
|
||||
int jobs;
|
||||
char debug[DEBUG_MAX];
|
||||
FILE *cmdout; /* print cmds, not run them */
|
||||
} ;
|
||||
|
||||
extern struct globs globs;
|
||||
|
||||
# define DEBUG_MAKE ( globs.debug[ 1 ] ) /* show actions when executed */
|
||||
# define DEBUG_MAKEQ ( globs.debug[ 2 ] ) /* show even quiet actions */
|
||||
# define DEBUG_EXEC ( globs.debug[ 2 ] ) /* show text of actons */
|
||||
# define DEBUG_MAKEPROG ( globs.debug[ 3 ] ) /* show progress of make0 */
|
||||
# define DEBUG_BIND ( globs.debug[ 3 ] ) /* show when files bound */
|
||||
|
||||
# define DEBUG_EXECCMD ( globs.debug[ 4 ] ) /* show execcmds()'s work */
|
||||
|
||||
# define DEBUG_COMPILE ( globs.debug[ 5 ] ) /* show rule invocations */
|
||||
|
||||
# define DEBUG_HEADER ( globs.debug[ 6 ] ) /* show result of header scan */
|
||||
# define DEBUG_BINDSCAN ( globs.debug[ 6 ] ) /* show result of dir scan */
|
||||
# define DEBUG_SEARCH ( globs.debug[ 6 ] ) /* show attempts at binding */
|
||||
|
||||
# define DEBUG_VARSET ( globs.debug[ 7 ] ) /* show variable settings */
|
||||
# define DEBUG_VARGET ( globs.debug[ 8 ] ) /* show variable fetches */
|
||||
# define DEBUG_VAREXP ( globs.debug[ 8 ] ) /* show variable expansions */
|
||||
# define DEBUG_IF ( globs.debug[ 8 ] ) /* show 'if' calculations */
|
||||
# define DEBUG_LISTS ( globs.debug[ 9 ] ) /* show list manipulation */
|
||||
# define DEBUG_SCAN ( globs.debug[ 9 ] ) /* show scanner tokens */
|
||||
# define DEBUG_MEM ( globs.debug[ 9 ] ) /* show memory use */
|
||||
|
||||
# define DEBUG_PROFILE ( globs.debug[ 10 ] ) /* dump rule execution times */
|
||||
# define DEBUG_PARSE ( globs.debug[ 11 ] ) /* debug parsing */
|
||||
|
||||
1554
historic/jam/src/jambase.c
Normal file
1554
historic/jam/src/jambase.c
Normal file
File diff suppressed because it is too large
Load Diff
15
historic/jam/src/jambase.h
Normal file
15
historic/jam/src/jambase.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jambase.h - declaration for the internal jambase
|
||||
*
|
||||
* The file Jambase is turned into a C array of strings in jambase.c
|
||||
* so that it can be built in to the executable. This is the
|
||||
* declaration for that array.
|
||||
*/
|
||||
|
||||
extern char *jambase[];
|
||||
1212
historic/jam/src/jamgram.c
Normal file
1212
historic/jam/src/jamgram.c
Normal file
File diff suppressed because it is too large
Load Diff
49
historic/jam/src/jamgram.h
Normal file
49
historic/jam/src/jamgram.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef YYSTYPE
|
||||
#define YYSTYPE int
|
||||
#endif
|
||||
#define _BANG 257
|
||||
#define _BANG_EQUALS 258
|
||||
#define _AMPERAMPER 259
|
||||
#define _LPAREN 260
|
||||
#define _RPAREN 261
|
||||
#define _PLUS_EQUALS 262
|
||||
#define _COLON 263
|
||||
#define _SEMIC 264
|
||||
#define _LANGLE 265
|
||||
#define _LANGLE_EQUALS 266
|
||||
#define _EQUALS 267
|
||||
#define _RANGLE 268
|
||||
#define _RANGLE_EQUALS 269
|
||||
#define _QUESTION_EQUALS 270
|
||||
#define _LBRACKET 271
|
||||
#define _RBRACKET 272
|
||||
#define ACTIONS 273
|
||||
#define BIND 274
|
||||
#define CASE 275
|
||||
#define DEFAULT 276
|
||||
#define ELSE 277
|
||||
#define EXISTING 278
|
||||
#define FOR 279
|
||||
#define IF 280
|
||||
#define IGNORE 281
|
||||
#define IN 282
|
||||
#define INCLUDE 283
|
||||
#define LOCAL 284
|
||||
#define MODULE 285
|
||||
#define ON 286
|
||||
#define PIECEMEAL 287
|
||||
#define QUIETLY 288
|
||||
#define RETURN 289
|
||||
#define RULE 290
|
||||
#define SWITCH 291
|
||||
#define TOGETHER 292
|
||||
#define UPDATED 293
|
||||
#define WHILE 294
|
||||
#define _LBRACE 295
|
||||
#define _BARBAR 296
|
||||
#define _RBRACE 297
|
||||
#define ARG 298
|
||||
#define STRING 299
|
||||
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
328
historic/jam/src/jamgram.y
Normal file
328
historic/jam/src/jamgram.y
Normal file
@@ -0,0 +1,328 @@
|
||||
%token _BANG
|
||||
%token _BANG_EQUALS
|
||||
%token _AMPERAMPER
|
||||
%token _LPAREN
|
||||
%token _RPAREN
|
||||
%token _PLUS_EQUALS
|
||||
%token _COLON
|
||||
%token _SEMIC
|
||||
%token _LANGLE
|
||||
%token _LANGLE_EQUALS
|
||||
%token _EQUALS
|
||||
%token _RANGLE
|
||||
%token _RANGLE_EQUALS
|
||||
%token _QUESTION_EQUALS
|
||||
%token _LBRACKET
|
||||
%token _RBRACKET
|
||||
%token ACTIONS
|
||||
%token BIND
|
||||
%token CASE
|
||||
%token DEFAULT
|
||||
%token ELSE
|
||||
%token EXISTING
|
||||
%token FOR
|
||||
%token IF
|
||||
%token IGNORE
|
||||
%token IN
|
||||
%token INCLUDE
|
||||
%token LOCAL
|
||||
%token MODULE
|
||||
%token ON
|
||||
%token PIECEMEAL
|
||||
%token QUIETLY
|
||||
%token RETURN
|
||||
%token RULE
|
||||
%token SWITCH
|
||||
%token TOGETHER
|
||||
%token UPDATED
|
||||
%token WHILE
|
||||
%token _LBRACE
|
||||
%token _BARBAR
|
||||
%token _RBRACE
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jamgram.yy - jam grammar
|
||||
*
|
||||
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
|
||||
* 06/01/94 (seiwald) - new 'actions existing' does existing sources
|
||||
* 08/23/94 (seiwald) - Support for '+=' (append to variable)
|
||||
* 08/31/94 (seiwald) - Allow ?= as alias for "default =".
|
||||
* 09/15/94 (seiwald) - if conditionals take only single arguments, so
|
||||
* that 'if foo == bar' gives syntax error (use =).
|
||||
* 02/11/95 (seiwald) - when scanning arguments to rules, only treat
|
||||
* punctuation keywords as keywords. All arg lists
|
||||
* are terminated with punctuation keywords.
|
||||
*
|
||||
* 09/11/00 (seiwald) - Support for function calls:
|
||||
*
|
||||
* Rules now return lists (LIST *), rather than void.
|
||||
*
|
||||
* New "[ rule ]" syntax evals rule into a LIST.
|
||||
*
|
||||
* Lists are now generated by compile_list() and
|
||||
* compile_append(), and any other rule that indirectly
|
||||
* makes a list, rather than being built directly here,
|
||||
* so that lists values can contain rule evaluations.
|
||||
*
|
||||
* New 'return' rule sets the return value, though
|
||||
* other statements also may have return values.
|
||||
*
|
||||
* 'run' production split from 'block' production so
|
||||
* that empty blocks can be handled separately.
|
||||
*/
|
||||
|
||||
%token ARG STRING
|
||||
|
||||
%left _BARBAR
|
||||
%left _AMPERAMPER
|
||||
%left _BANG
|
||||
|
||||
%{
|
||||
#include "jam.h"
|
||||
|
||||
#include "lists.h"
|
||||
#include "parse.h"
|
||||
#include "scan.h"
|
||||
#include "compile.h"
|
||||
#include "newstr.h"
|
||||
|
||||
# define F0 (LIST *(*)(PARSE *, FRAME *))0
|
||||
# define P0 (PARSE *)0
|
||||
# define S0 (char *)0
|
||||
|
||||
# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
|
||||
# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
|
||||
# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
|
||||
# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
|
||||
# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
|
||||
# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
|
||||
# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
|
||||
# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
|
||||
# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
|
||||
# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
|
||||
# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
|
||||
# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
|
||||
# define psetmodule( l,r ) parse_make( compile_set_module,l,r,P0,S0,S0,0 )
|
||||
# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
|
||||
# define psetc( s,p ) parse_make( compile_setcomp,p,P0,P0,s,S0,0 )
|
||||
# define psetc_args( s,p,a ) parse_make( compile_setcomp,p,a,P0,s,S0,0 )
|
||||
# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
|
||||
# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
|
||||
|
||||
# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
|
||||
# define pcnode( c,l,r ) parse_make( F0,l,r,P0,S0,S0,c )
|
||||
# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
run : /* empty */
|
||||
/* do nothing */
|
||||
| rules
|
||||
{ parse_save( $1.parse ); }
|
||||
;
|
||||
|
||||
/*
|
||||
* block - zero or more rules
|
||||
* rules - one or more rules
|
||||
* rule - any one of jam's rules
|
||||
* right-recursive so rules execute in order.
|
||||
*/
|
||||
|
||||
block : /* empty */
|
||||
{ $$.parse = pnull(); }
|
||||
| rules
|
||||
{ $$.parse = $1.parse; }
|
||||
;
|
||||
|
||||
rules : rule
|
||||
{ $$.parse = $1.parse; }
|
||||
| rule rules
|
||||
{ $$.parse = prules( $1.parse, $2.parse ); }
|
||||
| LOCAL list assign_list_opt _SEMIC block
|
||||
{ $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
|
||||
;
|
||||
|
||||
assign_list_opt : /* empty */
|
||||
{ $$.parse = pnull(); }
|
||||
| _EQUALS list
|
||||
{ $$.parse = $2.parse; }
|
||||
;
|
||||
|
||||
rule : _LBRACE block _RBRACE
|
||||
{ $$.parse = $2.parse; }
|
||||
| INCLUDE list _SEMIC
|
||||
{ $$.parse = pincl( $2.parse ); }
|
||||
| ARG lol _SEMIC
|
||||
{ $$.parse = prule( $1.string, $2.parse ); }
|
||||
| arg assign list _SEMIC
|
||||
{ $$.parse = pset( $1.parse, $3.parse, $2.number ); }
|
||||
| MODULE LOCAL list assign_list_opt _SEMIC
|
||||
{ $$.parse = psetmodule( $3.parse, $4.parse ); }
|
||||
| arg ON list assign list _SEMIC
|
||||
{ $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
|
||||
| RETURN list _SEMIC
|
||||
{ $$.parse = $2.parse; }
|
||||
| FOR ARG IN list _LBRACE block _RBRACE
|
||||
{ $$.parse = pfor( $2.string, $4.parse, $6.parse, 0 ); }
|
||||
| FOR LOCAL ARG IN list _LBRACE block _RBRACE
|
||||
{ $$.parse = pfor( $3.string, $5.parse, $7.parse, 1 ); }
|
||||
| SWITCH list _LBRACE cases _RBRACE
|
||||
{ $$.parse = pswitch( $2.parse, $4.parse ); }
|
||||
| IF cond _LBRACE block _RBRACE
|
||||
{ $$.parse = pif( $2.parse, $4.parse, pnull() ); }
|
||||
| MODULE list _LBRACE block _RBRACE
|
||||
{ $$.parse = pmodule( $2.parse, $4.parse ); }
|
||||
| WHILE cond _LBRACE block _RBRACE
|
||||
{ $$.parse = pwhile( $2.parse, $4.parse ); }
|
||||
| IF cond _LBRACE block _RBRACE ELSE rule
|
||||
{ $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
|
||||
| RULE ARG _LPAREN lol _RPAREN rule
|
||||
{ $$.parse = psetc_args( $2.string, $6.parse, $4.parse ); }
|
||||
| RULE ARG rule
|
||||
{ $$.parse = psetc( $2.string, $3.parse ); }
|
||||
| ACTIONS eflags ARG bindlist _LBRACE
|
||||
{ yymode( SCAN_STRING ); }
|
||||
STRING
|
||||
{ yymode( SCAN_NORMAL ); }
|
||||
_RBRACE
|
||||
{ $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
|
||||
;
|
||||
|
||||
/*
|
||||
* assign - = or +=
|
||||
*/
|
||||
|
||||
assign : _EQUALS
|
||||
{ $$.number = ASSIGN_SET; }
|
||||
| _PLUS_EQUALS
|
||||
{ $$.number = ASSIGN_APPEND; }
|
||||
| _QUESTION_EQUALS
|
||||
{ $$.number = ASSIGN_DEFAULT; }
|
||||
| DEFAULT _EQUALS
|
||||
{ $$.number = ASSIGN_DEFAULT; }
|
||||
;
|
||||
|
||||
/*
|
||||
* cond - a conditional for 'if'
|
||||
*/
|
||||
|
||||
cond : arg
|
||||
{ $$.parse = pcnode( COND_EXISTS, $1.parse, pnull() ); }
|
||||
| arg _EQUALS arg
|
||||
{ $$.parse = pcnode( COND_EQUALS, $1.parse, $3.parse ); }
|
||||
| arg _BANG_EQUALS arg
|
||||
{ $$.parse = pcnode( COND_NOTEQ, $1.parse, $3.parse ); }
|
||||
| arg _LANGLE arg
|
||||
{ $$.parse = pcnode( COND_LESS, $1.parse, $3.parse ); }
|
||||
| arg _LANGLE_EQUALS arg
|
||||
{ $$.parse = pcnode( COND_LESSEQ, $1.parse, $3.parse ); }
|
||||
| arg _RANGLE arg
|
||||
{ $$.parse = pcnode( COND_MORE, $1.parse, $3.parse ); }
|
||||
| arg _RANGLE_EQUALS arg
|
||||
{ $$.parse = pcnode( COND_MOREEQ, $1.parse, $3.parse ); }
|
||||
| arg IN list
|
||||
{ $$.parse = pcnode( COND_IN, $1.parse, $3.parse ); }
|
||||
| _BANG cond
|
||||
{ $$.parse = pcnode( COND_NOT, $2.parse, P0 ); }
|
||||
| cond _AMPERAMPER cond
|
||||
{ $$.parse = pcnode( COND_AND, $1.parse, $3.parse ); }
|
||||
| cond _BARBAR cond
|
||||
{ $$.parse = pcnode( COND_OR, $1.parse, $3.parse ); }
|
||||
| _LPAREN cond _RPAREN
|
||||
{ $$.parse = $2.parse; }
|
||||
;
|
||||
|
||||
/*
|
||||
* cases - action elements inside a 'switch'
|
||||
* case - a single action element inside a 'switch'
|
||||
* right-recursive rule so cases can be examined in order.
|
||||
*/
|
||||
|
||||
cases : /* empty */
|
||||
{ $$.parse = P0; }
|
||||
| case cases
|
||||
{ $$.parse = pnode( $1.parse, $2.parse ); }
|
||||
;
|
||||
|
||||
case : CASE ARG _COLON block
|
||||
{ $$.parse = psnode( $2.string, $4.parse ); }
|
||||
;
|
||||
|
||||
/*
|
||||
* lol - list of lists
|
||||
* right-recursive rule so that lists can be added in order.
|
||||
*/
|
||||
|
||||
lol : list
|
||||
{ $$.parse = pnode( P0, $1.parse ); }
|
||||
| list _COLON lol
|
||||
{ $$.parse = pnode( $3.parse, $1.parse ); }
|
||||
;
|
||||
|
||||
/*
|
||||
* list - zero or more args in a LIST
|
||||
* listp - list (in puncutation only mode)
|
||||
* arg - one ARG or function call
|
||||
*/
|
||||
|
||||
list : listp
|
||||
{ $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
|
||||
;
|
||||
|
||||
listp : /* empty */
|
||||
{ $$.parse = pnull(); yymode( SCAN_PUNCT ); }
|
||||
| listp arg
|
||||
{ $$.parse = pappend( $1.parse, $2.parse ); }
|
||||
;
|
||||
|
||||
arg : ARG
|
||||
{ $$.parse = plist( $1.string ); }
|
||||
| _LBRACKET ARG lol _RBRACKET
|
||||
{ $$.parse = prule( $2.string, $3.parse ); }
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
* eflags - zero or more modifiers to 'executes'
|
||||
* eflag - a single modifier to 'executes'
|
||||
*/
|
||||
|
||||
eflags : /* empty */
|
||||
{ $$.number = 0; }
|
||||
| eflags eflag
|
||||
{ $$.number = $1.number | $2.number; }
|
||||
;
|
||||
|
||||
eflag : UPDATED
|
||||
{ $$.number = EXEC_UPDATED; }
|
||||
| TOGETHER
|
||||
{ $$.number = EXEC_TOGETHER; }
|
||||
| IGNORE
|
||||
{ $$.number = EXEC_IGNORE; }
|
||||
| QUIETLY
|
||||
{ $$.number = EXEC_QUIETLY; }
|
||||
| PIECEMEAL
|
||||
{ $$.number = EXEC_PIECEMEAL; }
|
||||
| EXISTING
|
||||
{ $$.number = EXEC_EXISTING; }
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
* bindlist - list of variable to bind for an action
|
||||
*/
|
||||
|
||||
bindlist : /* empty */
|
||||
{ $$.parse = pnull(); }
|
||||
| BIND list
|
||||
{ $$.parse = $2.parse; }
|
||||
;
|
||||
|
||||
|
||||
287
historic/jam/src/jamgram.yy
Normal file
287
historic/jam/src/jamgram.yy
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* jamgram.yy - jam grammar
|
||||
*
|
||||
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
|
||||
* 06/01/94 (seiwald) - new 'actions existing' does existing sources
|
||||
* 08/23/94 (seiwald) - Support for '+=' (append to variable)
|
||||
* 08/31/94 (seiwald) - Allow ?= as alias for "default =".
|
||||
* 09/15/94 (seiwald) - if conditionals take only single arguments, so
|
||||
* that 'if foo == bar' gives syntax error (use =).
|
||||
* 02/11/95 (seiwald) - when scanning arguments to rules, only treat
|
||||
* punctuation keywords as keywords. All arg lists
|
||||
* are terminated with punctuation keywords.
|
||||
*
|
||||
* 09/11/00 (seiwald) - Support for function calls:
|
||||
*
|
||||
* Rules now return lists (LIST *), rather than void.
|
||||
*
|
||||
* New "[ rule ]" syntax evals rule into a LIST.
|
||||
*
|
||||
* Lists are now generated by compile_list() and
|
||||
* compile_append(), and any other rule that indirectly
|
||||
* makes a list, rather than being built directly here,
|
||||
* so that lists values can contain rule evaluations.
|
||||
*
|
||||
* New 'return' rule sets the return value, though
|
||||
* other statements also may have return values.
|
||||
*
|
||||
* 'run' production split from 'block' production so
|
||||
* that empty blocks can be handled separately.
|
||||
*/
|
||||
|
||||
%token ARG STRING
|
||||
|
||||
%left `||`
|
||||
%left `&&`
|
||||
%left `!`
|
||||
|
||||
%{
|
||||
#include "jam.h"
|
||||
|
||||
#include "lists.h"
|
||||
#include "parse.h"
|
||||
#include "scan.h"
|
||||
#include "compile.h"
|
||||
#include "newstr.h"
|
||||
|
||||
# define F0 (LIST *(*)(PARSE *, FRAME *))0
|
||||
# define P0 (PARSE *)0
|
||||
# define S0 (char *)0
|
||||
|
||||
# define pappend( l,r ) parse_make( compile_append,l,r,P0,S0,S0,0 )
|
||||
# define pfor( s,l,r,x ) parse_make( compile_foreach,l,r,P0,s,S0,x )
|
||||
# define pif( l,r,t ) parse_make( compile_if,l,r,t,S0,S0,0 )
|
||||
# define pwhile( l,r ) parse_make( compile_while,l,r,P0,S0,S0,0 )
|
||||
# define pincl( l ) parse_make( compile_include,l,P0,P0,S0,S0,0 )
|
||||
# define plist( s ) parse_make( compile_list,P0,P0,P0,s,S0,0 )
|
||||
# define plocal( l,r,t ) parse_make( compile_local,l,r,t,S0,S0,0 )
|
||||
# define pmodule( l,r ) parse_make( compile_module,l,r,P0,S0,S0,0 )
|
||||
# define pnull() parse_make( compile_null,P0,P0,P0,S0,S0,0 )
|
||||
# define prule( s,p ) parse_make( compile_rule,p,P0,P0,s,S0,0 )
|
||||
# define prules( l,r ) parse_make( compile_rules,l,r,P0,S0,S0,0 )
|
||||
# define pset( l,r,a ) parse_make( compile_set,l,r,P0,S0,S0,a )
|
||||
# define psetmodule( l,r ) parse_make( compile_set_module,l,r,P0,S0,S0,0 )
|
||||
# define pset1( l,r,t,a ) parse_make( compile_settings,l,r,t,S0,S0,a )
|
||||
# define psetc( s,p ) parse_make( compile_setcomp,p,P0,P0,s,S0,0 )
|
||||
# define psetc_args( s,p,a ) parse_make( compile_setcomp,p,a,P0,s,S0,0 )
|
||||
# define psete( s,l,s1,f ) parse_make( compile_setexec,l,P0,P0,s,s1,f )
|
||||
# define pswitch( l,r ) parse_make( compile_switch,l,r,P0,S0,S0,0 )
|
||||
|
||||
# define pnode( l,r ) parse_make( F0,l,r,P0,S0,S0,0 )
|
||||
# define pcnode( c,l,r ) parse_make( F0,l,r,P0,S0,S0,c )
|
||||
# define psnode( s,l ) parse_make( F0,l,P0,P0,s,S0,0 )
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
run : /* empty */
|
||||
/* do nothing */
|
||||
| rules
|
||||
{ parse_save( $1.parse ); }
|
||||
;
|
||||
|
||||
/*
|
||||
* block - zero or more rules
|
||||
* rules - one or more rules
|
||||
* rule - any one of jam's rules
|
||||
* right-recursive so rules execute in order.
|
||||
*/
|
||||
|
||||
block : /* empty */
|
||||
{ $$.parse = pnull(); }
|
||||
| rules
|
||||
{ $$.parse = $1.parse; }
|
||||
;
|
||||
|
||||
rules : rule
|
||||
{ $$.parse = $1.parse; }
|
||||
| rule rules
|
||||
{ $$.parse = prules( $1.parse, $2.parse ); }
|
||||
| `local` list assign_list_opt `;` block
|
||||
{ $$.parse = plocal( $2.parse, $3.parse, $5.parse ); }
|
||||
;
|
||||
|
||||
assign_list_opt : /* empty */
|
||||
{ $$.parse = pnull(); }
|
||||
| `=` list
|
||||
{ $$.parse = $2.parse; }
|
||||
;
|
||||
|
||||
rule : `{` block `}`
|
||||
{ $$.parse = $2.parse; }
|
||||
| `include` list `;`
|
||||
{ $$.parse = pincl( $2.parse ); }
|
||||
| ARG lol `;`
|
||||
{ $$.parse = prule( $1.string, $2.parse ); }
|
||||
| arg assign list `;`
|
||||
{ $$.parse = pset( $1.parse, $3.parse, $2.number ); }
|
||||
| `module` `local` list assign_list_opt `;`
|
||||
{ $$.parse = psetmodule( $3.parse, $4.parse ); }
|
||||
| arg `on` list assign list `;`
|
||||
{ $$.parse = pset1( $1.parse, $3.parse, $5.parse, $4.number ); }
|
||||
| `return` list `;`
|
||||
{ $$.parse = $2.parse; }
|
||||
| `for` ARG `in` list `{` block `}`
|
||||
{ $$.parse = pfor( $2.string, $4.parse, $6.parse, 0 ); }
|
||||
| `for` `local` ARG `in` list `{` block `}`
|
||||
{ $$.parse = pfor( $3.string, $5.parse, $7.parse, 1 ); }
|
||||
| `switch` list `{` cases `}`
|
||||
{ $$.parse = pswitch( $2.parse, $4.parse ); }
|
||||
| `if` cond `{` block `}`
|
||||
{ $$.parse = pif( $2.parse, $4.parse, pnull() ); }
|
||||
| `module` list `{` block `}`
|
||||
{ $$.parse = pmodule( $2.parse, $4.parse ); }
|
||||
| `while` cond `{` block `}`
|
||||
{ $$.parse = pwhile( $2.parse, $4.parse ); }
|
||||
| `if` cond `{` block `}` `else` rule
|
||||
{ $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
|
||||
| `rule` ARG `(` lol `)` rule
|
||||
{ $$.parse = psetc_args( $2.string, $6.parse, $4.parse ); }
|
||||
| `rule` ARG rule
|
||||
{ $$.parse = psetc( $2.string, $3.parse ); }
|
||||
| `actions` eflags ARG bindlist `{`
|
||||
{ yymode( SCAN_STRING ); }
|
||||
STRING
|
||||
{ yymode( SCAN_NORMAL ); }
|
||||
`}`
|
||||
{ $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
|
||||
;
|
||||
|
||||
/*
|
||||
* assign - = or +=
|
||||
*/
|
||||
|
||||
assign : `=`
|
||||
{ $$.number = ASSIGN_SET; }
|
||||
| `+=`
|
||||
{ $$.number = ASSIGN_APPEND; }
|
||||
| `?=`
|
||||
{ $$.number = ASSIGN_DEFAULT; }
|
||||
| `default` `=`
|
||||
{ $$.number = ASSIGN_DEFAULT; }
|
||||
;
|
||||
|
||||
/*
|
||||
* cond - a conditional for 'if'
|
||||
*/
|
||||
|
||||
cond : arg
|
||||
{ $$.parse = pcnode( COND_EXISTS, $1.parse, pnull() ); }
|
||||
| arg `=` arg
|
||||
{ $$.parse = pcnode( COND_EQUALS, $1.parse, $3.parse ); }
|
||||
| arg `!=` arg
|
||||
{ $$.parse = pcnode( COND_NOTEQ, $1.parse, $3.parse ); }
|
||||
| arg `<` arg
|
||||
{ $$.parse = pcnode( COND_LESS, $1.parse, $3.parse ); }
|
||||
| arg `<=` arg
|
||||
{ $$.parse = pcnode( COND_LESSEQ, $1.parse, $3.parse ); }
|
||||
| arg `>` arg
|
||||
{ $$.parse = pcnode( COND_MORE, $1.parse, $3.parse ); }
|
||||
| arg `>=` arg
|
||||
{ $$.parse = pcnode( COND_MOREEQ, $1.parse, $3.parse ); }
|
||||
| arg `in` list
|
||||
{ $$.parse = pcnode( COND_IN, $1.parse, $3.parse ); }
|
||||
| `!` cond
|
||||
{ $$.parse = pcnode( COND_NOT, $2.parse, P0 ); }
|
||||
| cond `&&` cond
|
||||
{ $$.parse = pcnode( COND_AND, $1.parse, $3.parse ); }
|
||||
| cond `||` cond
|
||||
{ $$.parse = pcnode( COND_OR, $1.parse, $3.parse ); }
|
||||
| `(` cond `)`
|
||||
{ $$.parse = $2.parse; }
|
||||
;
|
||||
|
||||
/*
|
||||
* cases - action elements inside a 'switch'
|
||||
* case - a single action element inside a 'switch'
|
||||
* right-recursive rule so cases can be examined in order.
|
||||
*/
|
||||
|
||||
cases : /* empty */
|
||||
{ $$.parse = P0; }
|
||||
| case cases
|
||||
{ $$.parse = pnode( $1.parse, $2.parse ); }
|
||||
;
|
||||
|
||||
case : `case` ARG `:` block
|
||||
{ $$.parse = psnode( $2.string, $4.parse ); }
|
||||
;
|
||||
|
||||
/*
|
||||
* lol - list of lists
|
||||
* right-recursive rule so that lists can be added in order.
|
||||
*/
|
||||
|
||||
lol : list
|
||||
{ $$.parse = pnode( P0, $1.parse ); }
|
||||
| list `:` lol
|
||||
{ $$.parse = pnode( $3.parse, $1.parse ); }
|
||||
;
|
||||
|
||||
/*
|
||||
* list - zero or more args in a LIST
|
||||
* listp - list (in puncutation only mode)
|
||||
* arg - one ARG or function call
|
||||
*/
|
||||
|
||||
list : listp
|
||||
{ $$.parse = $1.parse; yymode( SCAN_NORMAL ); }
|
||||
;
|
||||
|
||||
listp : /* empty */
|
||||
{ $$.parse = pnull(); yymode( SCAN_PUNCT ); }
|
||||
| listp arg
|
||||
{ $$.parse = pappend( $1.parse, $2.parse ); }
|
||||
;
|
||||
|
||||
arg : ARG
|
||||
{ $$.parse = plist( $1.string ); }
|
||||
| `[` ARG lol `]`
|
||||
{ $$.parse = prule( $2.string, $3.parse ); }
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
* eflags - zero or more modifiers to 'executes'
|
||||
* eflag - a single modifier to 'executes'
|
||||
*/
|
||||
|
||||
eflags : /* empty */
|
||||
{ $$.number = 0; }
|
||||
| eflags eflag
|
||||
{ $$.number = $1.number | $2.number; }
|
||||
;
|
||||
|
||||
eflag : `updated`
|
||||
{ $$.number = EXEC_UPDATED; }
|
||||
| `together`
|
||||
{ $$.number = EXEC_TOGETHER; }
|
||||
| `ignore`
|
||||
{ $$.number = EXEC_IGNORE; }
|
||||
| `quietly`
|
||||
{ $$.number = EXEC_QUIETLY; }
|
||||
| `piecemeal`
|
||||
{ $$.number = EXEC_PIECEMEAL; }
|
||||
| `existing`
|
||||
{ $$.number = EXEC_EXISTING; }
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
* bindlist - list of variable to bind for an action
|
||||
*/
|
||||
|
||||
bindlist : /* empty */
|
||||
{ $$.parse = pnull(); }
|
||||
| `bind` list
|
||||
{ $$.parse = $2.parse; }
|
||||
;
|
||||
|
||||
|
||||
41
historic/jam/src/jamgramtab.h
Normal file
41
historic/jam/src/jamgramtab.h
Normal file
@@ -0,0 +1,41 @@
|
||||
{ "!", _BANG },
|
||||
{ "!=", _BANG_EQUALS },
|
||||
{ "&&", _AMPERAMPER },
|
||||
{ "(", _LPAREN },
|
||||
{ ")", _RPAREN },
|
||||
{ "+=", _PLUS_EQUALS },
|
||||
{ ":", _COLON },
|
||||
{ ";", _SEMIC },
|
||||
{ "<", _LANGLE },
|
||||
{ "<=", _LANGLE_EQUALS },
|
||||
{ "=", _EQUALS },
|
||||
{ ">", _RANGLE },
|
||||
{ ">=", _RANGLE_EQUALS },
|
||||
{ "?=", _QUESTION_EQUALS },
|
||||
{ "[", _LBRACKET },
|
||||
{ "]", _RBRACKET },
|
||||
{ "actions", ACTIONS },
|
||||
{ "bind", BIND },
|
||||
{ "case", CASE },
|
||||
{ "default", DEFAULT },
|
||||
{ "else", ELSE },
|
||||
{ "existing", EXISTING },
|
||||
{ "for", FOR },
|
||||
{ "if", IF },
|
||||
{ "ignore", IGNORE },
|
||||
{ "in", IN },
|
||||
{ "include", INCLUDE },
|
||||
{ "local", LOCAL },
|
||||
{ "module", MODULE },
|
||||
{ "on", ON },
|
||||
{ "piecemeal", PIECEMEAL },
|
||||
{ "quietly", QUIETLY },
|
||||
{ "return", RETURN },
|
||||
{ "rule", RULE },
|
||||
{ "switch", SWITCH },
|
||||
{ "together", TOGETHER },
|
||||
{ "updated", UPDATED },
|
||||
{ "while", WHILE },
|
||||
{ "{", _LBRACE },
|
||||
{ "||", _BARBAR },
|
||||
{ "}", _RBRACE },
|
||||
243
historic/jam/src/lists.c
Normal file
243
historic/jam/src/lists.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "newstr.h"
|
||||
# include "lists.h"
|
||||
|
||||
/*
|
||||
* lists.c - maintain lists of strings
|
||||
*
|
||||
* This implementation essentially uses a singly linked list, but
|
||||
* guarantees that the head element of every list has a valid pointer
|
||||
* to the tail of the list, so the new elements can efficiently and
|
||||
* properly be appended to the end of a list.
|
||||
*
|
||||
* To avoid massive allocation, list_free() just tacks the whole freed
|
||||
* chain onto freelist and list_new() looks on freelist first for an
|
||||
* available list struct. list_free() does not free the strings in the
|
||||
* chain: it lazily lets list_new() do so.
|
||||
*
|
||||
* 08/23/94 (seiwald) - new list_append()
|
||||
* 09/07/00 (seiwald) - documented lol_*() functions
|
||||
*/
|
||||
|
||||
static LIST *freelist = 0; /* junkpile for list_free() */
|
||||
|
||||
/*
|
||||
* list_append() - append a list onto another one, returning total
|
||||
*/
|
||||
|
||||
LIST *
|
||||
list_append(
|
||||
LIST *l,
|
||||
LIST *nl )
|
||||
{
|
||||
if( !nl )
|
||||
{
|
||||
/* Just return l */
|
||||
}
|
||||
else if( !l )
|
||||
{
|
||||
l = nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Graft two non-empty lists. */
|
||||
l->tail->next = nl;
|
||||
l->tail = nl->tail;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* list_new() - tack a string onto the end of a list of strings
|
||||
*/
|
||||
|
||||
LIST *
|
||||
list_new(
|
||||
LIST *head,
|
||||
char *string )
|
||||
{
|
||||
LIST *l;
|
||||
|
||||
if( DEBUG_LISTS )
|
||||
printf( "list > %s <\n", string );
|
||||
|
||||
/* Get list struct from freelist, if one available. */
|
||||
/* Otherwise allocate. */
|
||||
/* If from freelist, must free string first */
|
||||
|
||||
if( freelist )
|
||||
{
|
||||
l = freelist;
|
||||
freestr( l->string );
|
||||
freelist = freelist->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = (LIST *)malloc( sizeof( *l ) );
|
||||
}
|
||||
|
||||
/* If first on chain, head points here. */
|
||||
/* If adding to chain, tack us on. */
|
||||
/* Tail must point to this new, last element. */
|
||||
|
||||
if( !head ) head = l;
|
||||
else head->tail->next = l;
|
||||
head->tail = l;
|
||||
l->next = 0;
|
||||
|
||||
l->string = string;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/*
|
||||
* list_copy() - copy a whole list of strings (nl) onto end of another (l)
|
||||
*/
|
||||
|
||||
LIST *
|
||||
list_copy(
|
||||
LIST *l,
|
||||
LIST *nl )
|
||||
{
|
||||
for( ; nl; nl = list_next( nl ) )
|
||||
l = list_new( l, copystr( nl->string ) );
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* list_sublist() - copy a subset of a list of strings
|
||||
*/
|
||||
|
||||
LIST *
|
||||
list_sublist(
|
||||
LIST *l,
|
||||
int start,
|
||||
int count )
|
||||
{
|
||||
LIST *nl = 0;
|
||||
|
||||
for( ; l && start--; l = list_next( l ) )
|
||||
;
|
||||
|
||||
for( ; l && count--; l = list_next( l ) )
|
||||
nl = list_new( nl, copystr( l->string ) );
|
||||
|
||||
return nl;
|
||||
}
|
||||
|
||||
/*
|
||||
* list_free() - free a list of strings
|
||||
*/
|
||||
|
||||
void
|
||||
list_free( LIST *head )
|
||||
{
|
||||
/* Just tack onto freelist. */
|
||||
|
||||
if( head )
|
||||
{
|
||||
head->tail->next = freelist;
|
||||
freelist = head;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* list_print() - print a list of strings to stdout
|
||||
*/
|
||||
|
||||
void
|
||||
list_print( LIST *l )
|
||||
{
|
||||
for( ; l; l = list_next( l ) )
|
||||
printf( "%s ", l->string );
|
||||
}
|
||||
|
||||
/*
|
||||
* list_length() - return the number of items in the list
|
||||
*/
|
||||
|
||||
int
|
||||
list_length( LIST *l )
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for( ; l; l = list_next( l ), ++n )
|
||||
;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* lol_init() - initialize a LOL (list of lists)
|
||||
*/
|
||||
|
||||
void
|
||||
lol_init( LOL *lol )
|
||||
{
|
||||
lol->count = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* lol_add() - append a LIST onto an LOL
|
||||
*/
|
||||
|
||||
void
|
||||
lol_add(
|
||||
LOL *lol,
|
||||
LIST *l )
|
||||
{
|
||||
if( lol->count < LOL_MAX )
|
||||
lol->list[ lol->count++ ] = l;
|
||||
}
|
||||
|
||||
/*
|
||||
* lol_free() - free the LOL and its LISTs
|
||||
*/
|
||||
|
||||
void
|
||||
lol_free( LOL *lol )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < lol->count; i++ )
|
||||
list_free( lol->list[i] );
|
||||
|
||||
lol->count = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* lol_get() - return one of the LISTs in the LOL
|
||||
*/
|
||||
|
||||
LIST *
|
||||
lol_get(
|
||||
LOL *lol,
|
||||
int i )
|
||||
{
|
||||
return i < lol->count ? lol->list[i] : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* lol_print() - debug print LISTS separated by ":"
|
||||
*/
|
||||
|
||||
void
|
||||
lol_print( LOL *lol )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < lol->count; i++ )
|
||||
{
|
||||
if( i )
|
||||
printf( " : " );
|
||||
list_print( lol->list[i] );
|
||||
}
|
||||
}
|
||||
85
historic/jam/src/lists.h
Normal file
85
historic/jam/src/lists.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* lists.h - the LIST structure and routines to manipulate them
|
||||
*
|
||||
* The whole of jam relies on lists of strings as a datatype. This
|
||||
* module, in conjunction with newstr.c, handles these relatively
|
||||
* efficiently.
|
||||
*
|
||||
* Structures defined:
|
||||
*
|
||||
* LIST - list of strings
|
||||
* LOL - list of LISTs
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* list_append() - append a list onto another one, returning total
|
||||
* list_new() - tack a string onto the end of a list of strings
|
||||
* list_copy() - copy a whole list of strings
|
||||
* list_sublist() - copy a subset of a list of strings
|
||||
* list_free() - free a list of strings
|
||||
* list_print() - print a list of strings to stdout
|
||||
* list_length() - return the number of items in the list
|
||||
*
|
||||
* lol_init() - initialize a LOL (list of lists)
|
||||
* lol_add() - append a LIST onto an LOL
|
||||
* lol_free() - free the LOL and its LISTs
|
||||
* lol_get() - return one of the LISTs in the LOL
|
||||
* lol_print() - debug print LISTS separated by ":"
|
||||
*
|
||||
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
|
||||
* 08/23/94 (seiwald) - new list_append()
|
||||
*/
|
||||
|
||||
#ifndef LISTS_DWA20011022_H
|
||||
# define LISTS_DWA20011022_H
|
||||
|
||||
/*
|
||||
* LIST - list of strings
|
||||
*/
|
||||
|
||||
typedef struct _list LIST;
|
||||
|
||||
struct _list {
|
||||
LIST *next;
|
||||
LIST *tail; /* only valid in head node */
|
||||
char *string; /* private copy */
|
||||
} ;
|
||||
|
||||
/*
|
||||
* LOL - list of LISTs
|
||||
*/
|
||||
|
||||
typedef struct _lol LOL;
|
||||
|
||||
# define LOL_MAX 9
|
||||
|
||||
struct _lol {
|
||||
int count;
|
||||
LIST *list[ LOL_MAX ];
|
||||
} ;
|
||||
|
||||
LIST * list_append( LIST *l, LIST *nl );
|
||||
LIST * list_copy( LIST *l, LIST *nl );
|
||||
void list_free( LIST *head );
|
||||
LIST * list_new( LIST *head, char *string );
|
||||
void list_print( LIST *l );
|
||||
int list_length( LIST *l );
|
||||
LIST * list_sublist( LIST *l, int start, int count );
|
||||
|
||||
# define list_next( l ) ((l)->next)
|
||||
|
||||
# define L0 ((LIST *)0)
|
||||
|
||||
void lol_add( LOL *lol, LIST *l );
|
||||
void lol_init( LOL *lol );
|
||||
void lol_free( LOL *lol );
|
||||
LIST * lol_get( LOL *lol, int i );
|
||||
void lol_print( LOL *lol );
|
||||
|
||||
#endif // LISTS_DWA20011022_H
|
||||
447
historic/jam/src/make.c
Normal file
447
historic/jam/src/make.c
Normal file
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* make.c - bring a target up to date, once rules are in place
|
||||
*
|
||||
* This modules controls the execution of rules to bring a target and
|
||||
* its dependencies up to date. It is invoked after the targets, rules,
|
||||
* et. al. described in rules.h are created by the interpreting of the
|
||||
* jam files.
|
||||
*
|
||||
* This file contains the main make() entry point and the first pass
|
||||
* make0(). The second pass, make1(), which actually does the command
|
||||
* execution, is in make1.c.
|
||||
*
|
||||
* External routines:
|
||||
* make() - make a target, given its name
|
||||
*
|
||||
* Internal routines:
|
||||
* make0() - bind and scan everything to make a TARGET
|
||||
*
|
||||
* 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>)
|
||||
* 01/04/94 (seiwald) - print all targets, bounded, when tracing commands
|
||||
* 04/08/94 (seiwald) - progress report now reflects only targets with actions
|
||||
* 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
|
||||
* 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
|
||||
* 12/20/94 (seiwald) - make0() headers after determining fate of target, so
|
||||
* that headers aren't seen as dependents on themselves.
|
||||
* 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
|
||||
* 02/02/95 (seiwald) - propagate leaf source time for new LEAVES rule.
|
||||
* 02/14/95 (seiwald) - NOUPDATE rule means don't update existing target.
|
||||
* 08/22/95 (seiwald) - NOUPDATE targets immune to anyhow (-a) flag.
|
||||
* 09/06/00 (seiwald) - NOCARE affects targets with sources/actions.
|
||||
* 03/02/01 (seiwald) - reverse NOCARE change.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "variable.h"
|
||||
# include "rules.h"
|
||||
|
||||
# include "search.h"
|
||||
# include "newstr.h"
|
||||
# include "make.h"
|
||||
# include "headers.h"
|
||||
# include "command.h"
|
||||
|
||||
# ifndef max
|
||||
# define max( a,b ) ((a)>(b)?(a):(b))
|
||||
# endif
|
||||
|
||||
typedef struct {
|
||||
int temp;
|
||||
int updating;
|
||||
int cantfind;
|
||||
int cantmake;
|
||||
int targets;
|
||||
int made;
|
||||
} COUNTS ;
|
||||
|
||||
static void make0( TARGET *t, int pbinding, time_t ptime,
|
||||
int depth, COUNTS *counts, int anyhow );
|
||||
|
||||
static char *target_fate[] =
|
||||
{
|
||||
"init", /* T_FATE_INIT */
|
||||
"making", /* T_FATE_MAKING */
|
||||
"stable", /* T_FATE_STABLE */
|
||||
"newer", /* T_FATE_NEWER */
|
||||
"temp", /* T_FATE_ISTMP */
|
||||
"touched", /* T_FATE_TOUCHED */
|
||||
"missing", /* T_FATE_MISSING */
|
||||
"old", /* T_FATE_OUTDATED */
|
||||
"update", /* T_FATE_UPDATE */
|
||||
"nofind", /* T_FATE_CANTFIND */
|
||||
"nomake" /* T_FATE_CANTMAKE */
|
||||
} ;
|
||||
|
||||
static char *target_bind[] =
|
||||
{
|
||||
"unbound",
|
||||
"missing",
|
||||
"parents",
|
||||
"exists",
|
||||
} ;
|
||||
|
||||
# define spaces(x) ( " " + ( x > 20 ? 0 : 20-x ) )
|
||||
|
||||
/*
|
||||
* make() - make a target, given its name
|
||||
*/
|
||||
|
||||
int
|
||||
make(
|
||||
int n_targets,
|
||||
char **targets,
|
||||
int anyhow )
|
||||
{
|
||||
int i;
|
||||
COUNTS counts[1];
|
||||
int status = 0; /* 1 if anything fails */
|
||||
|
||||
memset( (char *)counts, 0, sizeof( *counts ) );
|
||||
|
||||
for( i = 0; i < n_targets; i++ )
|
||||
{
|
||||
TARGET *t = bindtarget( targets[i] );
|
||||
|
||||
make0( t, T_BIND_UNBOUND, (time_t)0, 0, counts, anyhow );
|
||||
}
|
||||
|
||||
if( DEBUG_MAKE )
|
||||
{
|
||||
if( counts->targets )
|
||||
printf( "...found %d target%s...\n", counts->targets,
|
||||
counts->targets > 1 ? "s" : "" );
|
||||
if( counts->temp )
|
||||
printf( "...using %d temp target%s...\n", counts->temp,
|
||||
counts->temp > 1 ? "s" : "" );
|
||||
if( counts->updating )
|
||||
printf( "...updating %d target%s...\n", counts->updating,
|
||||
counts->updating > 1 ? "s" : "" );
|
||||
if( counts->cantfind )
|
||||
printf( "...can't find %d target%s...\n", counts->cantfind,
|
||||
counts->cantfind > 1 ? "s" : "" );
|
||||
if( counts->cantmake )
|
||||
printf( "...can't make %d target%s...\n", counts->cantmake,
|
||||
counts->cantmake > 1 ? "s" : "" );
|
||||
}
|
||||
|
||||
status = counts->cantfind || counts->cantmake;
|
||||
|
||||
for( i = 0; i < n_targets; i++ )
|
||||
status |= make1( bindtarget( targets[i] ) );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* make0() - bind and scan everything to make a TARGET
|
||||
*
|
||||
* Make0() recursively binds a target, searches for #included headers,
|
||||
* calls itself on those headers, and calls itself on any dependents.
|
||||
*/
|
||||
|
||||
static void
|
||||
make0(
|
||||
TARGET *t,
|
||||
int pbinding, /* parent target's binding */
|
||||
time_t ptime, /* parent target's timestamp */
|
||||
int depth, /* for display purposes */
|
||||
COUNTS *counts, /* for reporting */
|
||||
int anyhow ) /* forcibly touch all (real) targets */
|
||||
{
|
||||
TARGETS *c;
|
||||
int fate, hfate;
|
||||
time_t last, leaf, hlast, hleaf;
|
||||
char *flag = "";
|
||||
|
||||
if( DEBUG_MAKEPROG )
|
||||
printf( "make\t--\t%s%s\n", spaces( depth ), t->name );
|
||||
|
||||
/*
|
||||
* Step 1: don't remake if already trying or tried
|
||||
*/
|
||||
|
||||
switch( t->fate )
|
||||
{
|
||||
case T_FATE_MAKING:
|
||||
printf( "warning: %s depends on itself\n", t->name );
|
||||
return;
|
||||
|
||||
/* Deal with TEMPORARY targets with multiple parents. When a missing
|
||||
* TEMPORARY target is determined to be stable, it inherits the
|
||||
* timestamp of the parent being checked, and is given a binding of
|
||||
* T_BIND_PARENTS. To avoid outdating parents with earlier modification
|
||||
* times, we set the target's time to the minimum time of all parents.
|
||||
*/
|
||||
case T_FATE_STABLE:
|
||||
if ( t->binding == T_BIND_PARENTS && t->time > ptime && t->flags & T_FLAG_TEMP )
|
||||
t->time = ptime;
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
|
||||
case T_FATE_INIT:
|
||||
break;
|
||||
}
|
||||
|
||||
t->fate = T_FATE_MAKING;
|
||||
|
||||
/*
|
||||
* Step 2: under the influence of "on target" variables,
|
||||
* bind the target and search for headers.
|
||||
*/
|
||||
|
||||
/* Step 2a: set "on target" variables. */
|
||||
|
||||
pushsettings( t->settings );
|
||||
|
||||
/* Step 2b: find and timestamp the target file (if it's a file). */
|
||||
|
||||
if( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) )
|
||||
{
|
||||
t->boundname = search( t->name, &t->time );
|
||||
t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
|
||||
}
|
||||
|
||||
/* If temp file doesn't exist, use parent */
|
||||
|
||||
if( t->binding == T_BIND_MISSING && t->flags & T_FLAG_TEMP && ptime )
|
||||
{
|
||||
t->time = ptime;
|
||||
t->binding = t->time ? T_BIND_PARENTS : T_BIND_MISSING;
|
||||
}
|
||||
|
||||
/* Step 2c: If its a file, search for headers. */
|
||||
|
||||
if( t->binding == T_BIND_EXISTS )
|
||||
headers( t );
|
||||
|
||||
/* Step 2d: reset "on target" variables */
|
||||
|
||||
popsettings( t->settings );
|
||||
|
||||
/*
|
||||
* Pause for a little progress reporting
|
||||
*/
|
||||
|
||||
if( DEBUG_BIND )
|
||||
{
|
||||
if( strcmp( t->name, t->boundname ) )
|
||||
{
|
||||
printf( "bind\t--\t%s%s: %s\n",
|
||||
spaces( depth ), t->name, t->boundname );
|
||||
}
|
||||
|
||||
switch( t->binding )
|
||||
{
|
||||
case T_BIND_UNBOUND:
|
||||
case T_BIND_MISSING:
|
||||
case T_BIND_PARENTS:
|
||||
printf( "time\t--\t%s%s: %s\n",
|
||||
spaces( depth ), t->name, target_bind[ t->binding ] );
|
||||
break;
|
||||
|
||||
case T_BIND_EXISTS:
|
||||
printf( "time\t--\t%s%s: %s",
|
||||
spaces( depth ), t->name, ctime( &t->time ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Step 3: recursively make0() dependents
|
||||
*/
|
||||
|
||||
last = 0;
|
||||
leaf = 0;
|
||||
fate = T_FATE_STABLE;
|
||||
|
||||
for( c = t->deps[ T_DEPS_DEPENDS ]; c; c = c->next )
|
||||
{
|
||||
make0( c->target, t->binding, t->time, depth + 1, counts, anyhow );
|
||||
leaf = max( leaf, c->target->leaf );
|
||||
leaf = max( leaf, c->target->hleaf );
|
||||
|
||||
/* If LEAVES has been applied, we only heed the timestamps of */
|
||||
/* the leaf source nodes. */
|
||||
|
||||
if( t->flags & T_FLAG_LEAVES )
|
||||
{
|
||||
last = leaf;
|
||||
continue;
|
||||
}
|
||||
|
||||
last = max( last, c->target->time );
|
||||
last = max( last, c->target->htime );
|
||||
fate = max( fate, c->target->fate );
|
||||
fate = max( fate, c->target->hfate );
|
||||
}
|
||||
|
||||
/* If a NOUPDATE file exists, make dependents eternally old. */
|
||||
|
||||
if( t->flags & T_FLAG_NOUPDATE )
|
||||
{
|
||||
last = 0;
|
||||
t->time = 0;
|
||||
|
||||
/*
|
||||
* Don't inherit our fate from our dependents. Decide fate
|
||||
* based only upon other flags and our binding (done later).
|
||||
*/
|
||||
|
||||
fate = T_FATE_STABLE;
|
||||
}
|
||||
|
||||
/* Step 3b: determine fate: rebuild target or what? */
|
||||
|
||||
/*
|
||||
In English:
|
||||
If can't find or make child, can't make target.
|
||||
If children changed, make target.
|
||||
If target missing, make it.
|
||||
If children newer, make target.
|
||||
If temp's children newer, make temp.
|
||||
If deliberately touched, make it.
|
||||
If up-to-date temp file present, use it.
|
||||
If target exists but parent not, mark target newer.
|
||||
If target newer than parent, mark target newer.
|
||||
Don't propagate child's "newer" status.
|
||||
*/
|
||||
|
||||
if( fate >= T_FATE_BROKEN )
|
||||
{
|
||||
fate = T_FATE_CANTMAKE;
|
||||
}
|
||||
else if( fate >= T_FATE_SPOIL )
|
||||
{
|
||||
fate = T_FATE_UPDATE;
|
||||
}
|
||||
else if( t->binding == T_BIND_MISSING )
|
||||
{
|
||||
fate = T_FATE_MISSING;
|
||||
}
|
||||
else if( t->binding == T_BIND_EXISTS && last > t->time )
|
||||
{
|
||||
fate = T_FATE_OUTDATED;
|
||||
}
|
||||
else if( t->binding == T_BIND_PARENTS && last > t->time )
|
||||
{
|
||||
fate = T_FATE_OUTDATED;
|
||||
}
|
||||
else if( t->flags & T_FLAG_TOUCHED )
|
||||
{
|
||||
fate = T_FATE_TOUCHED;
|
||||
}
|
||||
else if( anyhow && !( t->flags & T_FLAG_NOUPDATE ) )
|
||||
{
|
||||
fate = T_FATE_TOUCHED;
|
||||
}
|
||||
else if( t->binding == T_BIND_EXISTS && t->flags & T_FLAG_TEMP )
|
||||
{
|
||||
fate = T_FATE_ISTMP;
|
||||
}
|
||||
else if( t->binding == T_BIND_EXISTS && pbinding == T_BIND_MISSING )
|
||||
{
|
||||
fate = T_FATE_NEWER;
|
||||
}
|
||||
else if( t->binding == T_BIND_EXISTS && ptime && t->time > ptime )
|
||||
{
|
||||
fate = T_FATE_NEWER;
|
||||
}
|
||||
else if( fate == T_FATE_NEWER )
|
||||
{
|
||||
fate = T_FATE_STABLE;
|
||||
}
|
||||
|
||||
/* Step 3c: handle missing files */
|
||||
/* If it's missing and there are no actions to create it, boom. */
|
||||
/* If we can't make a target we don't care about, 'sokay */
|
||||
/* We could insist that there are updating actions for all missing */
|
||||
/* files, but if they have dependents we just pretend it's NOTFILE. */
|
||||
|
||||
if( fate == T_FATE_MISSING &&
|
||||
!t->actions &&
|
||||
!t->deps[ T_DEPS_DEPENDS ] )
|
||||
{
|
||||
if( t->flags & T_FLAG_NOCARE )
|
||||
{
|
||||
fate = T_FATE_STABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "don't know how to make %s\n", t->name );
|
||||
|
||||
fate = T_FATE_CANTFIND;
|
||||
}
|
||||
}
|
||||
|
||||
/* Step 3d: propagate dependents' time & fate. */
|
||||
/* Set leaf time to be our time only if this is a leaf. */
|
||||
|
||||
t->time = max( t->time, last );
|
||||
t->leaf = leaf ? leaf : t->time ;
|
||||
t->fate = fate;
|
||||
|
||||
/*
|
||||
* Step 4: Recursively make0() headers.
|
||||
*/
|
||||
|
||||
/* Step 4a: recursively make0() headers */
|
||||
|
||||
hlast = 0;
|
||||
hleaf = 0;
|
||||
hfate = T_FATE_STABLE;
|
||||
|
||||
for( c = t->deps[ T_DEPS_INCLUDES ]; c; c = c->next )
|
||||
{
|
||||
make0( c->target, pbinding, ptime, depth + 1, counts, anyhow );
|
||||
hlast = max( hlast, c->target->time );
|
||||
hlast = max( hlast, c->target->htime );
|
||||
hleaf = max( hleaf, c->target->leaf );
|
||||
hleaf = max( hleaf, c->target->hleaf );
|
||||
hfate = max( hfate, c->target->fate );
|
||||
hfate = max( hfate, c->target->hfate );
|
||||
}
|
||||
|
||||
/* Step 4b: propagate dependents' time & fate. */
|
||||
|
||||
t->htime = hlast;
|
||||
t->hleaf = hleaf ? hleaf : t->htime;
|
||||
t->hfate = hfate;
|
||||
|
||||
/*
|
||||
* Step 5: a little harmless tabulating for tracing purposes
|
||||
*/
|
||||
|
||||
if( !( ++counts->targets % 1000 ) && DEBUG_MAKE )
|
||||
printf( "...patience...\n" );
|
||||
|
||||
if( fate == T_FATE_ISTMP )
|
||||
counts->temp++;
|
||||
else if( fate == T_FATE_CANTFIND )
|
||||
counts->cantfind++;
|
||||
else if( fate == T_FATE_CANTMAKE && t->actions )
|
||||
counts->cantmake++;
|
||||
else if( fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions )
|
||||
counts->updating++;
|
||||
|
||||
if( !( t->flags & T_FLAG_NOTFILE ) && fate >= T_FATE_SPOIL )
|
||||
flag = "+";
|
||||
else if( t->binding == T_BIND_EXISTS && ptime && t->time > ptime )
|
||||
flag = "*";
|
||||
|
||||
if( DEBUG_MAKEPROG )
|
||||
printf( "made%s\t%s\t%s%s\n",
|
||||
flag, target_fate[ t->fate ],
|
||||
spaces( depth ), t->name );
|
||||
}
|
||||
|
||||
12
historic/jam/src/make.h
Normal file
12
historic/jam/src/make.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* make.h - bring a target up to date, once rules are in place
|
||||
*/
|
||||
|
||||
int make( int n_targets, char **targets, int anyhow );
|
||||
int make1( TARGET *t );
|
||||
659
historic/jam/src/make1.c
Normal file
659
historic/jam/src/make1.c
Normal file
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* make1.c - execute command to bring targets up to date
|
||||
*
|
||||
* This module contains make1(), the entry point called by make() to
|
||||
* recursively decend the dependency graph executing update actions as
|
||||
* marked by make0().
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* make1() - execute commands to update a TARGET and all its dependents
|
||||
*
|
||||
* Internal routines, the recursive/asynchronous command executors:
|
||||
*
|
||||
* make1a() - recursively traverse target tree, calling make1b()
|
||||
* make1b() - dependents of target built, now build target with make1c()
|
||||
* make1c() - launch target's next command, call make1b() when done
|
||||
* make1d() - handle command execution completion and call back make1c()
|
||||
*
|
||||
* Internal support routines:
|
||||
*
|
||||
* make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc
|
||||
* make1list() - turn a list of targets into a LIST, for $(<) and $(>)
|
||||
* make1settings() - for vars that get bound values, build up replacement lists
|
||||
* make1bind() - bind targets that weren't bound in dependency analysis
|
||||
*
|
||||
* 04/16/94 (seiwald) - Split from make.c.
|
||||
* 04/21/94 (seiwald) - Handle empty "updated" actions.
|
||||
* 05/04/94 (seiwald) - async multiprocess (-j) support
|
||||
* 06/01/94 (seiwald) - new 'actions existing' does existing sources
|
||||
* 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
|
||||
* 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets.
|
||||
* 01/22/94 (seiwald) - pass per-target JAMSHELL down to execcmd().
|
||||
* 02/28/95 (seiwald) - Handle empty "existing" actions.
|
||||
* 03/10/95 (seiwald) - Fancy counts.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "variable.h"
|
||||
# include "rules.h"
|
||||
|
||||
# include "search.h"
|
||||
# include "newstr.h"
|
||||
# include "make.h"
|
||||
# include "command.h"
|
||||
# include "execcmd.h"
|
||||
|
||||
static void make1a( TARGET *t, TARGET *parent );
|
||||
static void make1b( TARGET *t );
|
||||
static void make1c( TARGET *t );
|
||||
static void make1d( void *closure, int status );
|
||||
|
||||
static CMD *make1cmds( ACTIONS *a0 );
|
||||
static LIST *make1list( LIST *l, TARGETS *targets, int flags );
|
||||
static SETTINGS *make1settings( LIST *vars );
|
||||
static void make1bind( TARGET *t, int warn );
|
||||
|
||||
/* Ugly static - it's too hard to carry it through the callbacks. */
|
||||
|
||||
static struct {
|
||||
int failed;
|
||||
int skipped;
|
||||
int total;
|
||||
int made;
|
||||
} counts[1] ;
|
||||
|
||||
/*
|
||||
* make1() - execute commands to update a TARGET and all its dependents
|
||||
*/
|
||||
|
||||
static int intr = 0;
|
||||
|
||||
int
|
||||
make1( TARGET *t )
|
||||
{
|
||||
memset( (char *)counts, 0, sizeof( *counts ) );
|
||||
|
||||
/* Recursively make the target and its dependents */
|
||||
|
||||
make1a( t, (TARGET *)0 );
|
||||
|
||||
/* Wait for any outstanding commands to finish running. */
|
||||
|
||||
while( execwait() )
|
||||
;
|
||||
|
||||
/* Talk about it */
|
||||
|
||||
if( DEBUG_MAKE && counts->failed )
|
||||
printf( "...failed updating %d target%s...\n", counts->failed,
|
||||
counts->failed > 1 ? "s" : "" );
|
||||
|
||||
if( DEBUG_MAKE && counts->skipped )
|
||||
printf( "...skipped %d target%s...\n", counts->skipped,
|
||||
counts->skipped > 1 ? "s" : "" );
|
||||
|
||||
if( DEBUG_MAKE && counts->made )
|
||||
printf( "...updated %d target%s...\n", counts->made,
|
||||
counts->made > 1 ? "s" : "" );
|
||||
|
||||
return counts->total != counts->made;
|
||||
}
|
||||
|
||||
/*
|
||||
* make1a() - recursively traverse target tree, calling make1b()
|
||||
*/
|
||||
|
||||
static void
|
||||
make1a(
|
||||
TARGET *t,
|
||||
TARGET *parent )
|
||||
{
|
||||
TARGETS *c;
|
||||
int i;
|
||||
|
||||
/* If the parent is the first to try to build this target */
|
||||
/* or this target is in the make1c() quagmire, arrange for the */
|
||||
/* parent to be notified when this target is built. */
|
||||
|
||||
if( parent )
|
||||
switch( t->progress )
|
||||
{
|
||||
case T_MAKE_INIT:
|
||||
case T_MAKE_ACTIVE:
|
||||
case T_MAKE_RUNNING:
|
||||
t->parents = targetentry( t->parents, parent );
|
||||
parent->asynccnt++;
|
||||
}
|
||||
|
||||
if( t->progress != T_MAKE_INIT )
|
||||
return;
|
||||
|
||||
/* Asynccnt counts the dependents preventing this target from */
|
||||
/* proceeding to make1b() for actual building. We start off with */
|
||||
/* a count of 1 to prevent anything from happening until we can */
|
||||
/* call all dependents. This 1 is accounted for when we call */
|
||||
/* make1b() ourselves, below. */
|
||||
|
||||
t->asynccnt = 1;
|
||||
|
||||
/* Recurse on our dependents, manipulating progress to guard */
|
||||
/* against circular dependency. */
|
||||
|
||||
t->progress = T_MAKE_ONSTACK;
|
||||
|
||||
for( i = T_DEPS_DEPENDS; i <= T_DEPS_INCLUDES; i++ )
|
||||
for( c = t->deps[i]; c && !intr; c = c->next )
|
||||
make1a( c->target, t );
|
||||
|
||||
t->progress = T_MAKE_ACTIVE;
|
||||
|
||||
/* Now that all dependents have bumped asynccnt, we now allow */
|
||||
/* decrement our reference to asynccnt. */
|
||||
|
||||
make1b( t );
|
||||
}
|
||||
|
||||
/*
|
||||
* make1b() - dependents of target built, now build target with make1c()
|
||||
*/
|
||||
|
||||
static void
|
||||
make1b( TARGET *t )
|
||||
{
|
||||
TARGETS *c;
|
||||
int i;
|
||||
char *failed = "dependents";
|
||||
|
||||
/* If any dependents are still outstanding, wait until they */
|
||||
/* call make1b() to signal their completion. */
|
||||
|
||||
if( --t->asynccnt )
|
||||
return;
|
||||
|
||||
/* Now ready to build target 't'... if dependents built ok. */
|
||||
|
||||
/* Collect status from dependents */
|
||||
|
||||
for( i = T_DEPS_DEPENDS; i <= T_DEPS_INCLUDES; i++ )
|
||||
for( c = t->deps[i]; c; c = c->next )
|
||||
if( c->target->status > t->status && !( c->target->flags & T_FLAG_NOCARE ) )
|
||||
{
|
||||
failed = c->target->name;
|
||||
t->status = c->target->status;
|
||||
}
|
||||
|
||||
/* If actions on deps have failed, bail. */
|
||||
/* Otherwise, execute all actions to make target */
|
||||
|
||||
if( t->status == EXEC_CMD_FAIL && t->actions )
|
||||
{
|
||||
++counts->skipped;
|
||||
printf( "...skipped %s for lack of %s...\n", t->name, failed );
|
||||
}
|
||||
|
||||
if( t->status == EXEC_CMD_OK )
|
||||
switch( t->fate )
|
||||
{
|
||||
case T_FATE_INIT:
|
||||
case T_FATE_MAKING:
|
||||
/* shouldn't happen */
|
||||
|
||||
case T_FATE_STABLE:
|
||||
case T_FATE_NEWER:
|
||||
break;
|
||||
|
||||
case T_FATE_CANTFIND:
|
||||
case T_FATE_CANTMAKE:
|
||||
t->status = EXEC_CMD_FAIL;
|
||||
break;
|
||||
|
||||
case T_FATE_ISTMP:
|
||||
if( DEBUG_MAKE )
|
||||
printf( "...using %s...\n", t->name );
|
||||
break;
|
||||
|
||||
case T_FATE_TOUCHED:
|
||||
case T_FATE_MISSING:
|
||||
case T_FATE_OUTDATED:
|
||||
case T_FATE_UPDATE:
|
||||
/* Set "on target" vars, build actions, unset vars */
|
||||
/* Set "progress" so that make1c() counts this target among */
|
||||
/* the successes/failures. */
|
||||
|
||||
if( t->actions )
|
||||
{
|
||||
++counts->total;
|
||||
if( DEBUG_MAKE && !( counts->total % 100 ) )
|
||||
printf( "...on %dth target...\n", counts->total );
|
||||
|
||||
pushsettings( t->settings );
|
||||
t->cmds = (char *)make1cmds( t->actions );
|
||||
popsettings( t->settings );
|
||||
|
||||
t->progress = T_MAKE_RUNNING;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call make1c() to begin the execution of the chain of commands */
|
||||
/* needed to build target. If we're not going to build target */
|
||||
/* (because of dependency failures or because no commands need to */
|
||||
/* be run) the chain will be empty and make1c() will directly */
|
||||
/* signal the completion of target. */
|
||||
|
||||
make1c( t );
|
||||
}
|
||||
|
||||
/*
|
||||
* make1c() - launch target's next command, call make1b() when done
|
||||
*/
|
||||
|
||||
static void
|
||||
make1c( TARGET *t )
|
||||
{
|
||||
CMD *cmd = (CMD *)t->cmds;
|
||||
|
||||
/* If there are (more) commands to run to build this target */
|
||||
/* (and we haven't hit an error running earlier comands) we */
|
||||
/* launch the command with execcmd(). */
|
||||
|
||||
/* If there are no more commands to run, we collect the status */
|
||||
/* from all the actions then report our completion to all the */
|
||||
/* parents. */
|
||||
|
||||
if( cmd && t->status == EXEC_CMD_OK )
|
||||
{
|
||||
if( DEBUG_MAKE )
|
||||
if( DEBUG_MAKEQ || ! ( cmd->rule->actions->flags & RULE_QUIETLY ) )
|
||||
{
|
||||
printf( "%s ", cmd->rule->name );
|
||||
list_print( lol_get( &cmd->args, 0 ) );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
if( DEBUG_EXEC )
|
||||
printf( "%s\n", cmd->buf );
|
||||
|
||||
if( globs.cmdout )
|
||||
fprintf( globs.cmdout, "%s", cmd->buf );
|
||||
|
||||
if( globs.noexec )
|
||||
{
|
||||
make1d( t, EXEC_CMD_OK );
|
||||
}
|
||||
else
|
||||
{
|
||||
fflush( stdout );
|
||||
execcmd( cmd->buf, make1d, t, cmd->shell );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TARGETS *c;
|
||||
ACTIONS *actions;
|
||||
|
||||
/* Collect status from actions, and distribute it as well */
|
||||
|
||||
for( actions = t->actions; actions; actions = actions->next )
|
||||
if( actions->action->status > t->status )
|
||||
t->status = actions->action->status;
|
||||
|
||||
for( actions = t->actions; actions; actions = actions->next )
|
||||
if( t->status > actions->action->status )
|
||||
actions->action->status = t->status;
|
||||
|
||||
/* Tally success/failure for those we tried to update. */
|
||||
|
||||
if( t->progress == T_MAKE_RUNNING )
|
||||
switch( t->status )
|
||||
{
|
||||
case EXEC_CMD_OK:
|
||||
++counts->made;
|
||||
break;
|
||||
case EXEC_CMD_FAIL:
|
||||
++counts->failed;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Tell parents dependent has been built */
|
||||
|
||||
t->progress = T_MAKE_DONE;
|
||||
|
||||
for( c = t->parents; c; c = c->next )
|
||||
make1b( c->target );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* make1d() - handle command execution completion and call back make1c()
|
||||
*/
|
||||
|
||||
static void
|
||||
make1d(
|
||||
void *closure,
|
||||
int status )
|
||||
{
|
||||
TARGET *t = (TARGET *)closure;
|
||||
CMD *cmd = (CMD *)t->cmds;
|
||||
|
||||
/* Execcmd() has completed. All we need to do is fiddle with the */
|
||||
/* status and signal our completion so make1c() can run the next */
|
||||
/* command. On interrupts, we bail heavily. */
|
||||
|
||||
if ( t->flags & T_FLAG_FAIL_EXPECTED )
|
||||
{
|
||||
/* invert execution result when FAIL_EXPECTED was applied */
|
||||
switch (status)
|
||||
{
|
||||
case EXEC_CMD_FAIL: status = EXEC_CMD_OK; break;
|
||||
case EXEC_CMD_OK: status = EXEC_CMD_FAIL; break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if( status == EXEC_CMD_FAIL && ( cmd->rule->actions->flags & RULE_IGNORE ) )
|
||||
status = EXEC_CMD_OK;
|
||||
|
||||
/* On interrupt, set intr so _everything_ fails */
|
||||
|
||||
if( status == EXEC_CMD_INTR )
|
||||
++intr;
|
||||
|
||||
if( status == EXEC_CMD_FAIL && DEBUG_MAKE )
|
||||
{
|
||||
/* Print command text on failure */
|
||||
|
||||
if( !DEBUG_EXEC )
|
||||
printf( "%s\n", cmd->buf );
|
||||
|
||||
printf( "...failed %s ", cmd->rule->name );
|
||||
list_print( lol_get( &cmd->args, 0 ) );
|
||||
printf( "...\n" );
|
||||
}
|
||||
|
||||
/* If the command was interrupted or failed and the target */
|
||||
/* is not "precious", remove the targets */
|
||||
|
||||
if( status != EXEC_CMD_OK && !( cmd->rule->actions->flags & RULE_TOGETHER ) )
|
||||
{
|
||||
LIST *targets = lol_get( &cmd->args, 0 );
|
||||
|
||||
for( ; targets; targets = list_next( targets ) )
|
||||
if( !unlink( targets->string ) )
|
||||
printf( "...removing %s\n", targets->string );
|
||||
}
|
||||
|
||||
/* Free this command and call make1c() to move onto next command. */
|
||||
|
||||
t->status = status;
|
||||
t->cmds = (char *)cmd_next( cmd );
|
||||
|
||||
cmd_free( cmd );
|
||||
|
||||
make1c( t );
|
||||
}
|
||||
|
||||
/*
|
||||
* make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc
|
||||
*
|
||||
* Essentially copies a chain of ACTIONs to a chain of CMDs,
|
||||
* grouping RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions,
|
||||
* and handling RULE_NEWSRCS actions. The result is a chain of
|
||||
* CMDs which can be expanded by var_string() and executed with
|
||||
* execcmd().
|
||||
*/
|
||||
|
||||
static CMD *
|
||||
make1cmds( ACTIONS *a0 )
|
||||
{
|
||||
CMD *cmds = 0;
|
||||
LIST *shell = var_get( "JAMSHELL" ); /* shell is per-target */
|
||||
|
||||
/* Step through actions */
|
||||
/* Actions may be shared with other targets or grouped with */
|
||||
/* RULE_TOGETHER, so actions already seen are skipped. */
|
||||
|
||||
for( ; a0; a0 = a0->next )
|
||||
{
|
||||
RULE *rule = a0->action->rule;
|
||||
rule_actions *actions = rule->actions;
|
||||
SETTINGS *boundvars;
|
||||
LIST *nt, *ns;
|
||||
ACTIONS *a1;
|
||||
CMD *cmd;
|
||||
int start, chunk, length;
|
||||
|
||||
/* Only do rules with commands to execute. */
|
||||
/* If this action has already been executed, use saved status */
|
||||
|
||||
if( !actions || a0->action->running )
|
||||
continue;
|
||||
|
||||
a0->action->running = 1;
|
||||
|
||||
/* Make LISTS of targets and sources */
|
||||
/* If `execute together` has been specified for this rule, tack */
|
||||
/* on sources from each instance of this rule for this target. */
|
||||
|
||||
nt = make1list( L0, a0->action->targets, 0 );
|
||||
ns = make1list( L0, a0->action->sources, actions->flags );
|
||||
|
||||
if( actions->flags & RULE_TOGETHER )
|
||||
for( a1 = a0->next; a1; a1 = a1->next )
|
||||
if( a1->action->rule == rule && !a1->action->running )
|
||||
{
|
||||
ns = make1list( ns, a1->action->sources, actions->flags );
|
||||
a1->action->running = 1;
|
||||
}
|
||||
|
||||
/* If doing only updated (or existing) sources, but none have */
|
||||
/* been updated (or exist), skip this action. */
|
||||
|
||||
if( !ns && ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) )
|
||||
{
|
||||
list_free( nt );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we had 'actions xxx bind vars' we bind the vars now */
|
||||
|
||||
boundvars = make1settings( actions->bindlist );
|
||||
pushsettings( boundvars );
|
||||
|
||||
/*
|
||||
* Build command, starting with all source args.
|
||||
*
|
||||
* If cmd_new returns 0, it's because the resulting command
|
||||
* length is > MAXLINE. In this case, we'll slowly reduce
|
||||
* the number of source arguments presented until it does
|
||||
* fit. This only applies to actions that allow PIECEMEAL
|
||||
* commands.
|
||||
*
|
||||
* While reducing slowly takes a bit of compute time to get
|
||||
* things just right, it's worth it to get as close to MAXLINE
|
||||
* as possible, because launching the commands we're executing
|
||||
* is likely to be much more compute intensive!
|
||||
*
|
||||
* Note we loop through at least once, for sourceless actions.
|
||||
*/
|
||||
|
||||
start = 0;
|
||||
chunk = length = list_length( ns );
|
||||
|
||||
do
|
||||
{
|
||||
/* Build cmd: cmd_new consumes its lists. */
|
||||
|
||||
CMD *cmd = cmd_new( rule,
|
||||
list_copy( L0, nt ),
|
||||
list_sublist( ns, start, chunk ),
|
||||
list_copy( L0, shell ) );
|
||||
|
||||
if( cmd )
|
||||
{
|
||||
/* It fit: chain it up. */
|
||||
|
||||
if( !cmds ) cmds = cmd;
|
||||
else cmds->tail->next = cmd;
|
||||
cmds->tail = cmd;
|
||||
start += chunk;
|
||||
}
|
||||
else if( ( actions->flags & RULE_PIECEMEAL ) && chunk > 1 )
|
||||
{
|
||||
/* Reduce chunk size slowly. */
|
||||
|
||||
chunk = chunk * 9 / 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Too long and not splittable. */
|
||||
|
||||
printf( "%s actions too long (max %d)!\n",
|
||||
rule->name, MAXLINE );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
}
|
||||
while( start < length );
|
||||
|
||||
/* These were always copied when used. */
|
||||
|
||||
list_free( nt );
|
||||
list_free( ns );
|
||||
|
||||
/* Free the variables whose values were bound by */
|
||||
/* 'actions xxx bind vars' */
|
||||
|
||||
popsettings( boundvars );
|
||||
freesettings( boundvars );
|
||||
}
|
||||
|
||||
return cmds;
|
||||
}
|
||||
|
||||
/*
|
||||
* make1list() - turn a list of targets into a LIST, for $(<) and $(>)
|
||||
*/
|
||||
|
||||
static LIST *
|
||||
make1list(
|
||||
LIST *l,
|
||||
TARGETS *targets,
|
||||
int flags )
|
||||
{
|
||||
for( ; targets; targets = targets->next )
|
||||
{
|
||||
TARGET *t = targets->target;
|
||||
|
||||
/* Sources to 'actions existing' are never in the dependency */
|
||||
/* graph (if they were, they'd get built and 'existing' would */
|
||||
/* be superfluous, so throttle warning message about independent */
|
||||
/* targets. */
|
||||
|
||||
if( t->binding == T_BIND_UNBOUND )
|
||||
make1bind( t, !( flags & RULE_EXISTING ) );
|
||||
|
||||
if( ( flags & RULE_EXISTING ) && t->binding != T_BIND_EXISTS )
|
||||
continue;
|
||||
|
||||
if( ( flags & RULE_NEWSRCS ) && t->fate <= T_FATE_STABLE )
|
||||
continue;
|
||||
|
||||
/* Prohibit duplicates for RULE_TOGETHER */
|
||||
|
||||
if( flags & RULE_TOGETHER )
|
||||
{
|
||||
LIST *m;
|
||||
|
||||
for( m = l; m; m = m->next )
|
||||
if( !strcmp( m->string, t->boundname ) )
|
||||
break;
|
||||
|
||||
if( m )
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Build new list */
|
||||
|
||||
l = list_new( l, copystr( t->boundname ) );
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* make1settings() - for vars that get bound values, build up replacement lists
|
||||
*/
|
||||
|
||||
static SETTINGS *
|
||||
make1settings( LIST *vars )
|
||||
{
|
||||
SETTINGS *settings = 0;
|
||||
|
||||
for( ; vars; vars = list_next( vars ) )
|
||||
{
|
||||
LIST *l = var_get( vars->string );
|
||||
LIST *nl = 0;
|
||||
|
||||
for( ; l; l = list_next( l ) )
|
||||
{
|
||||
TARGET *t = bindtarget( l->string );
|
||||
|
||||
/* Make sure the target is bound, warning if it is not in the */
|
||||
/* dependency graph. */
|
||||
|
||||
if( t->binding == T_BIND_UNBOUND )
|
||||
make1bind( t, 1 );
|
||||
|
||||
/* Build new list */
|
||||
|
||||
nl = list_new( nl, copystr( t->boundname ) );
|
||||
}
|
||||
|
||||
/* Add to settings chain */
|
||||
|
||||
settings = addsettings( settings, 0, vars->string, nl );
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
/*
|
||||
* make1bind() - bind targets that weren't bound in dependency analysis
|
||||
*
|
||||
* Spot the kludge! If a target is not in the dependency tree, it didn't
|
||||
* get bound by make0(), so we have to do it here. Ugly.
|
||||
*/
|
||||
|
||||
static void
|
||||
make1bind(
|
||||
TARGET *t,
|
||||
int warn )
|
||||
{
|
||||
if( t->flags & T_FLAG_NOTFILE )
|
||||
return;
|
||||
|
||||
/* Sources to 'actions existing' are never in the dependency */
|
||||
/* graph (if they were, they'd get built and 'existing' would */
|
||||
/* be superfluous, so throttle warning message about independent */
|
||||
/* targets. */
|
||||
|
||||
if( warn )
|
||||
printf( "warning: using independent target %s\n", t->name );
|
||||
|
||||
pushsettings( t->settings );
|
||||
t->boundname = search( t->name, &t->time );
|
||||
t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING;
|
||||
popsettings( t->settings );
|
||||
}
|
||||
4
historic/jam/src/makecygwindebugjam.bat
Executable file
4
historic/jam/src/makecygwindebugjam.bat
Executable file
@@ -0,0 +1,4 @@
|
||||
set VISUALC=c:\tools\msvc6\vc98
|
||||
set JAM_TOOLSET=VISUALC
|
||||
rm -rf bin.ntx86
|
||||
make -fbuilds/win32-gcc.mk CFLAGS="/GZ /Zi /MLd -DNT" CCFLAGS="/GZ /Zi /MLd" YACC="bison -t -d -l -v --yacc" LINKLIBS="c:\tools\msvc6\vc98\lib\advapi32.lib c:\tools\msvc6\vc98\lib\oldnames.lib c:\tools\msvc6\vc98\lib\gdi32.lib c:\tools\msvc6\vc98\lib\user32.lib c:\tools\msvc6\vc98\lib\kernel32.lib" LINKFLAGS="/DEBUG" %*
|
||||
5
historic/jam/src/makedebugjam.bat
Executable file
5
historic/jam/src/makedebugjam.bat
Executable file
@@ -0,0 +1,5 @@
|
||||
set VISUALC=c:\tools\msvc6\vc98
|
||||
set JAM_TOOLSET=VISUALC
|
||||
rm -rf bin.ntx86
|
||||
mkdir bin.ntx86
|
||||
nmake -fbuilds/win32-visualc.mk JAMBASE= BOOST_ROOT= BOOST_BUILD_PATH= CFLAGS="/GZ /Zi /MLd -DNT" CCFLAGS="/GZ /Zi /MLd" LINKLIBS="c:\tools\msvc6\vc98\lib\advapi32.lib c:\tools\msvc6\vc98\lib\oldnames.lib c:\tools\msvc6\vc98\lib\gdi32.lib c:\tools\msvc6\vc98\lib\user32.lib c:\tools\msvc6\vc98\lib\kernel32.lib" LINKFLAGS="/DEBUG" YACC="bison -t -d -l -v --debug --yacc" YACCFILES="y.tab" %*
|
||||
6
historic/jam/src/makedebugjam.sh
Normal file
6
historic/jam/src/makedebugjam.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
./yyacc jamgram.y jamgramtab.h jamgram.yy
|
||||
export VISUALC=c:\tools\msvc6\vc98
|
||||
export JAM_TOOLSET=VISUALC
|
||||
rm -rf bin.ntx86
|
||||
nmake -fbuilds/win32-visualc.mk CFLAGS="/GZ /Zi /MLd -DNT" CCFLAGS="/GZ /Zi /MLd" YACC="bison -t -d -l -v --debug --yacc" LINKLIBS="c:\tools\msvc6\vc98\lib\advapi32.lib c:\tools\msvc6\vc98\lib\oldnames.lib c:\tools\msvc6\vc98\lib\gdi32.lib c:\tools\msvc6\vc98\lib\user32.lib c:\tools\msvc6\vc98\lib\kernel32.lib" LINKFLAGS="/DEBUG"
|
||||
125
historic/jam/src/mkjambase.c
Normal file
125
historic/jam/src/mkjambase.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* mkjambase.c - turn Jambase into a big C structure
|
||||
*
|
||||
* Usage: mkjambase jambase.c Jambase ...
|
||||
*
|
||||
* Results look like this:
|
||||
*
|
||||
* char *jambase[] = {
|
||||
* "...\n",
|
||||
* ...
|
||||
* 0 };
|
||||
*
|
||||
* Handles \'s and "'s specially; knows to delete blank and comment lines.
|
||||
*
|
||||
*/
|
||||
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
|
||||
int main( int argc, char **argv, char **envp )
|
||||
{
|
||||
char buf[ 1024 ];
|
||||
FILE *fin;
|
||||
FILE *fout;
|
||||
char *p;
|
||||
int doDotC = 0;
|
||||
|
||||
if( argc < 3 )
|
||||
{
|
||||
fprintf( stderr, "usage: %s jambase.c Jambase ...\n", argv[0] );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( !( fout = fopen( argv[1], "w" ) ) )
|
||||
{
|
||||
perror( argv[1] );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If the file ends in .c generate a C source file */
|
||||
|
||||
if( ( p = strrchr( argv[1], '.' ) ) && !strcmp( p, ".c" ) )
|
||||
doDotC++;
|
||||
|
||||
/* Now process the files */
|
||||
|
||||
argc -= 2, argv += 2;
|
||||
|
||||
if( doDotC )
|
||||
{
|
||||
fprintf( fout, "/* Generated by mkjambase from Jambase */\n" );
|
||||
fprintf( fout, "char *jambase[] = {\n" );
|
||||
}
|
||||
|
||||
for( ; argc--; argv++ )
|
||||
{
|
||||
if( !( fin = fopen( *argv, "r" ) ) )
|
||||
{
|
||||
perror( *argv );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( doDotC )
|
||||
{
|
||||
fprintf( fout, "/* %s */\n", *argv );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( fout, "### %s ###\n", *argv );
|
||||
}
|
||||
|
||||
while( fgets( buf, sizeof( buf ), fin ) )
|
||||
{
|
||||
if( doDotC )
|
||||
{
|
||||
char *p = buf;
|
||||
|
||||
/* Strip leading whitespace. */
|
||||
|
||||
while( *p == ' ' || *p == '\t' || *p == '\n' )
|
||||
p++;
|
||||
|
||||
/* Drop comments and empty lines. */
|
||||
|
||||
if( *p == '#' || !*p )
|
||||
continue;
|
||||
|
||||
/* Copy */
|
||||
|
||||
putc( '"', fout );
|
||||
|
||||
for( ; *p && *p != '\n'; p++ )
|
||||
switch( *p )
|
||||
{
|
||||
case '\\': putc( '\\', fout ); putc( '\\', fout ); break;
|
||||
case '"': putc( '\\', fout ); putc( '"', fout ); break;
|
||||
case '\r': break;
|
||||
default: putc( *p, fout ); break;
|
||||
}
|
||||
|
||||
fprintf( fout, "\\n\",\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( fout, "%s", buf );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fclose( fin );
|
||||
}
|
||||
|
||||
if( doDotC )
|
||||
fprintf( fout, "0 };\n" );
|
||||
|
||||
fclose( fout );
|
||||
|
||||
return 0;
|
||||
}
|
||||
95
historic/jam/src/modules.c
Normal file
95
historic/jam/src/modules.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/* (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
|
||||
* distribute this software is granted provided this copyright notice appears
|
||||
* in all copies. This software is provided "as is" without express or implied
|
||||
* warranty, and with no claim as to its suitability for any purpose.
|
||||
*/
|
||||
#include "modules.h"
|
||||
#include "jam.h"
|
||||
#include "string.h"
|
||||
#include "hash.h"
|
||||
#include "newstr.h"
|
||||
#include "lists.h"
|
||||
#include "parse.h"
|
||||
#include "rules.h"
|
||||
#include "variable.h"
|
||||
#include "strings.h"
|
||||
|
||||
static struct hash* module_hash = 0;
|
||||
|
||||
static char* new_module_str( module* m, char* suffix )
|
||||
{
|
||||
char* result;
|
||||
string s;
|
||||
string_copy( &s, m->name );
|
||||
string_append( &s, suffix );
|
||||
result = newstr( s.value );
|
||||
string_free( &s );
|
||||
return result;
|
||||
}
|
||||
|
||||
module* bindmodule( char* name )
|
||||
{
|
||||
string s;
|
||||
module m_, *m = &m_;
|
||||
|
||||
if( !module_hash )
|
||||
module_hash = hashinit( sizeof( module ), "modules" );
|
||||
|
||||
string_new( &s );
|
||||
if (name)
|
||||
{
|
||||
string_append( &s, name );
|
||||
string_push_back( &s, '.' );
|
||||
}
|
||||
|
||||
m->name = s.value;
|
||||
|
||||
if ( hashenter( module_hash, (HASHDATA **)&m ) )
|
||||
{
|
||||
m->name = newstr( m->name );
|
||||
m->local_names = 0;
|
||||
m->locals = 0;
|
||||
m->rules = hashinit( sizeof( RULE ), new_module_str( m, "rules" ) );
|
||||
}
|
||||
string_free( &s );
|
||||
return m;
|
||||
}
|
||||
|
||||
module* root_module()
|
||||
{
|
||||
static module* root = 0;
|
||||
if ( !root )
|
||||
root = bindmodule(0);
|
||||
return root;
|
||||
}
|
||||
|
||||
/*
|
||||
* bind_module_var --
|
||||
*
|
||||
* Add the symbol to the module's list of symbols if it is not already in the
|
||||
* module. m is assumed to be the current module and if the symbol is new, any
|
||||
* current value is replaced by an empty list until the module is exited.
|
||||
*
|
||||
*/
|
||||
void bind_module_var( module* m, char* symbol )
|
||||
{
|
||||
char** name = &symbol;
|
||||
|
||||
if ( !m->local_names )
|
||||
m->local_names = hashinit( sizeof( char* ), new_module_str( m, "variables" ) );
|
||||
|
||||
if ( hashenter( m->local_names, (HASHDATA **)&name ) )
|
||||
{
|
||||
m->locals = addsettings( m->locals, 0, symbol, var_swap( symbol, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
void enter_module( module* m )
|
||||
{
|
||||
pushsettings( m->locals );
|
||||
}
|
||||
|
||||
void exit_module( module* m )
|
||||
{
|
||||
popsettings( m->locals );
|
||||
}
|
||||
25
historic/jam/src/modules.h
Normal file
25
historic/jam/src/modules.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
|
||||
* distribute this software is granted provided this copyright notice appears
|
||||
* in all copies. This software is provided "as is" without express or implied
|
||||
* warranty, and with no claim as to its suitability for any purpose.
|
||||
*/
|
||||
#ifndef MODULES_DWA10182001_H
|
||||
# define MODULES_DWA10182001_H
|
||||
|
||||
struct module
|
||||
{
|
||||
char* name;
|
||||
struct hash* rules;
|
||||
struct hash* local_names;
|
||||
struct _settings* locals;
|
||||
};
|
||||
|
||||
typedef struct module module; /* MSVC debugger gets confused unless this is provided */
|
||||
|
||||
module* bindmodule( char* name );
|
||||
module* root_module();
|
||||
void bind_module_var( module*, char* name );
|
||||
void enter_module( module* );
|
||||
void exit_module( module* );
|
||||
|
||||
#endif // MODULES_DWA10182001_H
|
||||
93
historic/jam/src/newstr.c
Normal file
93
historic/jam/src/newstr.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "newstr.h"
|
||||
# include "hash.h"
|
||||
|
||||
/*
|
||||
* newstr.c - string manipulation routines
|
||||
*
|
||||
* To minimize string copying, string creation, copying, and freeing
|
||||
* is done through newstr.
|
||||
*
|
||||
* External functions:
|
||||
*
|
||||
* newstr() - return a malloc'ed copy of a string
|
||||
* copystr() - return a copy of a string previously returned by newstr()
|
||||
* freestr() - free a string returned by newstr() or copystr()
|
||||
* donestr() - free string tables
|
||||
*
|
||||
* Once a string is passed to newstr(), the returned string is readonly.
|
||||
*
|
||||
* This implementation builds a hash table of all strings, so that multiple
|
||||
* calls of newstr() on the same string allocate memory for the string once.
|
||||
* Strings are never actually freed.
|
||||
*/
|
||||
|
||||
typedef char *STRING;
|
||||
|
||||
static struct hash *strhash = 0;
|
||||
static int strtotal = 0;
|
||||
|
||||
/*
|
||||
* newstr() - return a malloc'ed copy of a string
|
||||
*/
|
||||
|
||||
char *
|
||||
newstr( char *string )
|
||||
{
|
||||
STRING str, *s = &str;
|
||||
|
||||
if( !strhash )
|
||||
strhash = hashinit( sizeof( STRING ), "strings" );
|
||||
|
||||
*s = string;
|
||||
|
||||
if( hashenter( strhash, (HASHDATA **)&s ) )
|
||||
{
|
||||
int l = strlen( string );
|
||||
char *m = (char *)malloc( l + 1 );
|
||||
|
||||
strtotal += l + 1;
|
||||
memcpy( m, string, l + 1 );
|
||||
*s = m;
|
||||
}
|
||||
|
||||
return *s;
|
||||
}
|
||||
|
||||
/*
|
||||
* copystr() - return a copy of a string previously returned by newstr()
|
||||
*/
|
||||
|
||||
char *
|
||||
copystr( char *s )
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* freestr() - free a string returned by newstr() or copystr()
|
||||
*/
|
||||
|
||||
void
|
||||
freestr( char *s )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* donestr() - free string tables
|
||||
*/
|
||||
|
||||
void
|
||||
donestr()
|
||||
{
|
||||
hashdone( strhash );
|
||||
|
||||
if( DEBUG_MEM )
|
||||
printf( "%dK in strings\n", strtotal / 1024 );
|
||||
}
|
||||
14
historic/jam/src/newstr.h
Normal file
14
historic/jam/src/newstr.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* newstr.h - string manipulation routines
|
||||
*/
|
||||
|
||||
char *newstr( char *string );
|
||||
char *copystr( char *s );
|
||||
void freestr( char *s );
|
||||
void donestr();
|
||||
103
historic/jam/src/option.c
Normal file
103
historic/jam/src/option.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "option.h"
|
||||
|
||||
/*
|
||||
* option.c - command line option processing
|
||||
*
|
||||
* {o >o
|
||||
* \<>) "Process command line options as defined in <option.h>.
|
||||
* Return the number of argv[] elements used up by options,
|
||||
* or -1 if an invalid option flag was given or an argument
|
||||
* was supplied for an option that does not require one."
|
||||
*/
|
||||
|
||||
int
|
||||
getoptions(
|
||||
int argc,
|
||||
char **argv,
|
||||
char *opts,
|
||||
option *optv )
|
||||
{
|
||||
int i;
|
||||
int optc = N_OPTS;
|
||||
|
||||
memset( (char *)optv, '\0', sizeof( *optv ) * N_OPTS );
|
||||
|
||||
for( i = 0; i < argc; i++ )
|
||||
{
|
||||
char *arg;
|
||||
|
||||
if( argv[i][0] != '-' || !isalpha( argv[i][1] ) )
|
||||
break;
|
||||
|
||||
if( !optc-- )
|
||||
{
|
||||
printf( "too many options (%d max)\n", N_OPTS );
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( arg = &argv[i][1]; *arg; arg++ )
|
||||
{
|
||||
char *f;
|
||||
|
||||
for( f = opts; *f; f++ )
|
||||
if( *f == *arg )
|
||||
break;
|
||||
|
||||
if( !*f )
|
||||
{
|
||||
printf( "Invalid option: -%c\n", *arg );
|
||||
return -1;
|
||||
}
|
||||
|
||||
optv->flag = *f;
|
||||
|
||||
if( f[1] != ':' )
|
||||
{
|
||||
optv++->val = "true";
|
||||
}
|
||||
else if( arg[1] )
|
||||
{
|
||||
optv++->val = &arg[1];
|
||||
break;
|
||||
}
|
||||
else if( ++i < argc )
|
||||
{
|
||||
optv++->val = argv[i];
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "option: -%c needs argument\n", *f );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Name: getoptval() - find an option given its character
|
||||
*/
|
||||
|
||||
char *
|
||||
getoptval(
|
||||
option *optv,
|
||||
char opt,
|
||||
int subopt )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < N_OPTS; i++, optv++ )
|
||||
if( optv->flag == opt && !subopt-- )
|
||||
return optv->val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
23
historic/jam/src/option.h
Normal file
23
historic/jam/src/option.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* option.h - command line option processing
|
||||
*
|
||||
* {o >o
|
||||
* \ -) "Command line option."
|
||||
*/
|
||||
|
||||
typedef struct option
|
||||
{
|
||||
char flag; /* filled in by getoption() */
|
||||
char *val; /* set to random address if true */
|
||||
} option;
|
||||
|
||||
# define N_OPTS 256
|
||||
|
||||
int getoptions( int argc, char **argv, char *opts, option *optv );
|
||||
char * getoptval( option *optv, char opt, int subopt );
|
||||
117
historic/jam/src/parse.c
Normal file
117
historic/jam/src/parse.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "scan.h"
|
||||
# include "newstr.h"
|
||||
# include "modules.h"
|
||||
# include "frames.h"
|
||||
|
||||
/*
|
||||
* parse.c - make and destroy parse trees as driven by the parser
|
||||
*
|
||||
* 09/07/00 (seiwald) - ref count on PARSE to avoid freeing when used,
|
||||
* as per Matt Armstrong.
|
||||
* 09/11/00 (seiwald) - structure reworked to reflect that (*func)()
|
||||
* returns a LIST *.
|
||||
*/
|
||||
|
||||
static PARSE *yypsave;
|
||||
|
||||
void
|
||||
parse_file( char *f, FRAME* frame )
|
||||
{
|
||||
/* Suspend scan of current file */
|
||||
/* and push this new file in the stream */
|
||||
|
||||
yyfparse(f);
|
||||
|
||||
/* Now parse each block of rules and execute it. */
|
||||
/* Execute it outside of the parser so that recursive */
|
||||
/* calls to yyrun() work (no recursive yyparse's). */
|
||||
|
||||
for(;;)
|
||||
{
|
||||
PARSE *p;
|
||||
|
||||
/* Filled by yyparse() calling parse_save() */
|
||||
|
||||
yypsave = 0;
|
||||
|
||||
/* If parse error or empty parse, outta here */
|
||||
|
||||
if( yyparse() || !( p = yypsave ) )
|
||||
break;
|
||||
|
||||
/* Run the parse tree. */
|
||||
|
||||
(*(p->func))( p, frame );
|
||||
|
||||
parse_free( p );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse_save( PARSE *p )
|
||||
{
|
||||
yypsave = p;
|
||||
}
|
||||
|
||||
PARSE *
|
||||
parse_make(
|
||||
LIST *(*func)( PARSE *p, FRAME *args ),
|
||||
PARSE *left,
|
||||
PARSE *right,
|
||||
PARSE *third,
|
||||
char *string,
|
||||
char *string1,
|
||||
int num )
|
||||
{
|
||||
PARSE *p = (PARSE *)malloc( sizeof( PARSE ) );
|
||||
|
||||
p->func = func;
|
||||
p->left = left;
|
||||
p->right = right;
|
||||
p->third = third;
|
||||
p->string = string;
|
||||
p->string1 = string1;
|
||||
p->num = num;
|
||||
p->refs = 1;
|
||||
p->module = 0;
|
||||
p->rulename = 0;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
parse_refer( PARSE *p )
|
||||
{
|
||||
++p->refs;
|
||||
}
|
||||
|
||||
void
|
||||
parse_free( PARSE *p )
|
||||
{
|
||||
if( --p->refs )
|
||||
return;
|
||||
|
||||
if( p->string )
|
||||
freestr( p->string );
|
||||
if( p->string1 )
|
||||
freestr( p->string1 );
|
||||
if( p->left )
|
||||
parse_free( p->left );
|
||||
if( p->right )
|
||||
parse_free( p->right );
|
||||
if( p->third )
|
||||
parse_free( p->third );
|
||||
if ( p->rulename )
|
||||
freestr( p->rulename );
|
||||
|
||||
free( (char *)p );
|
||||
}
|
||||
50
historic/jam/src/parse.h
Normal file
50
historic/jam/src/parse.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
#ifndef PARSE_DWA20011020_H
|
||||
# define PARSE_DWA20011020_H
|
||||
# include "frames.h"
|
||||
# include "modules.h"
|
||||
|
||||
/*
|
||||
* parse.h - make and destroy parse trees as driven by the parser
|
||||
*/
|
||||
|
||||
/*
|
||||
* parse tree node
|
||||
*/
|
||||
|
||||
typedef struct _PARSE PARSE;
|
||||
|
||||
struct _PARSE {
|
||||
LIST *(*func)( PARSE *p, FRAME *frame );
|
||||
PARSE *left;
|
||||
PARSE *right;
|
||||
PARSE *third;
|
||||
char *string;
|
||||
char *string1;
|
||||
int num;
|
||||
int refs;
|
||||
module* module;
|
||||
char* rulename;
|
||||
} ;
|
||||
|
||||
void parse_file( char *f, FRAME* frame );
|
||||
void parse_save( PARSE *p );
|
||||
|
||||
PARSE * parse_make(
|
||||
LIST *(*func)( PARSE *p, FRAME* frame ),
|
||||
PARSE *left,
|
||||
PARSE *right,
|
||||
PARSE *third,
|
||||
char *string,
|
||||
char *string1,
|
||||
int num );
|
||||
|
||||
void parse_refer( PARSE *p );
|
||||
void parse_free( PARSE *p );
|
||||
|
||||
#endif // PARSE_DWA20011020_H
|
||||
5
historic/jam/src/patchlevel.h
Normal file
5
historic/jam/src/patchlevel.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Keep JAMVERSYM in sync with VERSION. */
|
||||
/* It can be accessed as $(JAMVERSION) in the Jamfile. */
|
||||
|
||||
#define VERSION "2.3.2"
|
||||
#define JAMVERSYM "JAMVERSION=2.3"
|
||||
249
historic/jam/src/pathmac.c
Normal file
249
historic/jam/src/pathmac.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
|
||||
# ifdef OS_MAC
|
||||
|
||||
# define DELIM ':'
|
||||
|
||||
/*
|
||||
* pathunix.c - manipulate file names on UNIX, NT, OS2
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* file_parse() - split a file name into dir/base/suffix/member
|
||||
* file_build() - build a filename given dir/base/suffix/member
|
||||
* file_parent() - make a FILENAME point to its parent dir
|
||||
*
|
||||
* File_parse() and file_build() just manipuate a string and a structure;
|
||||
* they do not make system calls.
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 12/26/93 (seiwald) - handle dir/.suffix properly in file_build()
|
||||
* 12/19/94 (mikem) - solaris string table insanity support
|
||||
* 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
|
||||
* 02/14/95 (seiwald) - parse and build /xxx properly
|
||||
* 02/23/95 (wingerd) Compilers on NT can handle "/" in pathnames, so we
|
||||
* should expect hdr searches to come up with strings
|
||||
* like "thing/thing.h". So we need to test for "/" as
|
||||
* well as "\" when parsing pathnames.
|
||||
* 03/16/95 (seiwald) - fixed accursed typo on line 69.
|
||||
* 05/03/96 (seiwald) - split from filent.c, fileunix.c
|
||||
* 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
|
||||
* don't include the archive member name.
|
||||
*/
|
||||
|
||||
/*
|
||||
* file_parse() - split a file name into dir/base/suffix/member
|
||||
*/
|
||||
|
||||
void
|
||||
file_parse(
|
||||
char *file,
|
||||
FILENAME *f )
|
||||
{
|
||||
char *p, *q;
|
||||
char *end;
|
||||
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
|
||||
/* Look for <grist> */
|
||||
|
||||
if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
/* Look for dir: */
|
||||
|
||||
p = strrchr( file, DELIM );
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p - file;
|
||||
|
||||
/* Dir of : is : */
|
||||
f->f_dir.len++;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
end = file + strlen( file );
|
||||
|
||||
/* Look for (member) */
|
||||
|
||||
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
|
||||
{
|
||||
f->f_member.ptr = p + 1;
|
||||
f->f_member.len = end - p - 2;
|
||||
end = p;
|
||||
}
|
||||
|
||||
/* Look for .suffix */
|
||||
/* This would be memrchr() */
|
||||
|
||||
p = 0;
|
||||
q = file;
|
||||
|
||||
while( q = memchr( q, '.', end - q ) )
|
||||
p = q++;
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_suffix.ptr = p;
|
||||
f->f_suffix.len = end - p;
|
||||
end = p;
|
||||
}
|
||||
|
||||
/* Leaves base */
|
||||
|
||||
f->f_base.ptr = file;
|
||||
f->f_base.len = end - file;
|
||||
}
|
||||
|
||||
/*
|
||||
* file_build() - build a filename given dir/base/suffix/member
|
||||
*/
|
||||
|
||||
# define DIR_EMPTY 0 /* "" */
|
||||
# define DIR_DOT 1 /* : */
|
||||
# define DIR_DOTDOT 2 /* :: */
|
||||
# define DIR_ABS 3 /* dira:dirb: */
|
||||
# define DIR_REL 4 /* :dira:dirb: */
|
||||
|
||||
# define G_DIR 0 /* take dir */
|
||||
# define G_ROOT 1 /* take root */
|
||||
# define G_CAT 2 /* prepend root to dir */
|
||||
# define G_DTDR 3 /* :: of rel dir */
|
||||
# define G_DDDD 4 /* make it ::: (../..) */
|
||||
# define G_MT 5 /* leave it empty */
|
||||
|
||||
char grid[5][5] = {
|
||||
/* EMPTY DOT DOTDOT ABS REL */
|
||||
/* EMPTY */ { G_MT, G_DIR, G_DIR, G_DIR, G_DIR },
|
||||
/* DOT */ { G_ROOT, G_DIR, G_DIR, G_DIR, G_DIR },
|
||||
/* DOTDOT */ { G_ROOT, G_ROOT, G_DDDD, G_DIR, G_DTDR },
|
||||
/* ABS */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT },
|
||||
/* REL */ { G_ROOT, G_ROOT, G_ROOT, G_DIR, G_CAT }
|
||||
} ;
|
||||
|
||||
static int
|
||||
file_flags(
|
||||
char *ptr,
|
||||
int len )
|
||||
{
|
||||
if( !len )
|
||||
return DIR_EMPTY;
|
||||
if( len == 1 && ptr[0] == DELIM )
|
||||
return DIR_DOT;
|
||||
if( len == 2 && ptr[0] == DELIM && ptr[1] == DELIM )
|
||||
return DIR_DOTDOT;
|
||||
if( ptr[0] == DELIM )
|
||||
return DIR_REL;
|
||||
return DIR_ABS;
|
||||
}
|
||||
|
||||
void
|
||||
file_build(
|
||||
FILENAME *f,
|
||||
string* file,
|
||||
int binding )
|
||||
{
|
||||
int dflag, rflag, act;
|
||||
|
||||
file_build1( f, file );
|
||||
|
||||
/* Combine root & directory, according to the grid. */
|
||||
|
||||
dflag = file_flags( f->f_dir.ptr, f->f_dir.len );
|
||||
rflag = file_flags( f->f_root.ptr, f->f_root.len );
|
||||
|
||||
switch( act = grid[ rflag ][ dflag ] )
|
||||
{
|
||||
case G_DTDR:
|
||||
{
|
||||
/* :: of rel dir */
|
||||
string_push_back( file, DELIM );
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case G_DIR:
|
||||
/* take dir */
|
||||
string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
|
||||
break;
|
||||
|
||||
case G_ROOT:
|
||||
/* take root */
|
||||
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
|
||||
break;
|
||||
|
||||
case G_CAT:
|
||||
/* prepend root to dir */
|
||||
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
|
||||
if( file->value[file->size - 1] == DELIM )
|
||||
string_pop_back( file );
|
||||
string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
|
||||
break;
|
||||
|
||||
case G_DDDD:
|
||||
/* make it ::: (../..) */
|
||||
string_append( file, ":::" );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Put : between dir and file (if none already) */
|
||||
|
||||
if( act != G_MT &&
|
||||
file->value[file->size - 1] != DELIM &&
|
||||
( f->f_base.len || f->f_suffix.len ) )
|
||||
{
|
||||
string_push_back( file, DELIM );
|
||||
}
|
||||
|
||||
if( f->f_base.len )
|
||||
{
|
||||
string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
|
||||
}
|
||||
|
||||
if( f->f_suffix.len )
|
||||
{
|
||||
string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
|
||||
}
|
||||
|
||||
if( f->f_member.len )
|
||||
{
|
||||
string_push_back( file, '(' );
|
||||
string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
|
||||
string_push_back( file, ')' );
|
||||
}
|
||||
|
||||
if( DEBUG_SEARCH )
|
||||
printf(" -> '%s'\n", file->value);
|
||||
}
|
||||
|
||||
/*
|
||||
* file_parent() - make a FILENAME point to its parent dir
|
||||
*/
|
||||
|
||||
void
|
||||
file_parent( FILENAME *f )
|
||||
{
|
||||
/* just set everything else to nothing */
|
||||
|
||||
f->f_base.ptr =
|
||||
f->f_suffix.ptr =
|
||||
f->f_member.ptr = "";
|
||||
|
||||
f->f_base.len =
|
||||
f->f_suffix.len =
|
||||
f->f_member.len = 0;
|
||||
}
|
||||
|
||||
# endif /* OS_MAC */
|
||||
222
historic/jam/src/pathunix.c
Normal file
222
historic/jam/src/pathunix.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
# include "strings.h"
|
||||
|
||||
# ifdef USE_PATHUNIX
|
||||
|
||||
/*
|
||||
* pathunix.c - manipulate file names on UNIX, NT, OS2, AmigaOS
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* file_parse() - split a file name into dir/base/suffix/member
|
||||
* file_build() - build a filename given dir/base/suffix/member
|
||||
* file_parent() - make a FILENAME point to its parent dir
|
||||
*
|
||||
* File_parse() and file_build() just manipuate a string and a structure;
|
||||
* they do not make system calls.
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 12/26/93 (seiwald) - handle dir/.suffix properly in file_build()
|
||||
* 12/19/94 (mikem) - solaris string table insanity support
|
||||
* 12/21/94 (wingerd) Use backslashes for pathnames - the NT way.
|
||||
* 02/14/95 (seiwald) - parse and build /xxx properly
|
||||
* 02/23/95 (wingerd) Compilers on NT can handle "/" in pathnames, so we
|
||||
* should expect hdr searches to come up with strings
|
||||
* like "thing/thing.h". So we need to test for "/" as
|
||||
* well as "\" when parsing pathnames.
|
||||
* 03/16/95 (seiwald) - fixed accursed typo on line 69.
|
||||
* 05/03/96 (seiwald) - split from filent.c, fileunix.c
|
||||
* 12/20/96 (seiwald) - when looking for the rightmost . in a file name,
|
||||
* don't include the archive member name.
|
||||
*/
|
||||
|
||||
/*
|
||||
* file_parse() - split a file name into dir/base/suffix/member
|
||||
*/
|
||||
|
||||
void
|
||||
file_parse(
|
||||
char *file,
|
||||
FILENAME *f )
|
||||
{
|
||||
char *p, *q;
|
||||
char *end;
|
||||
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
|
||||
/* Look for <grist> */
|
||||
|
||||
if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
/* Look for dir/ */
|
||||
|
||||
p = strrchr( file, '/' );
|
||||
|
||||
# ifndef UNIX
|
||||
# ifndef AMIGA
|
||||
/* On NT, look for dir\ as well */
|
||||
{
|
||||
char *p1 = strrchr( file, '\\' );
|
||||
p = p1 > p ? p1 : p;
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p - file;
|
||||
|
||||
/* Special case for / - dirname is /, not "" */
|
||||
|
||||
if( !f->f_dir.len )
|
||||
f->f_dir.len = 1;
|
||||
|
||||
# ifndef UNIX
|
||||
# ifndef AMIGA
|
||||
/* Special case for D:/ - dirname is D:/, not "D:" */
|
||||
|
||||
if( f->f_dir.len == 2 && file[1] == ':' )
|
||||
f->f_dir.len = 3;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
end = file + strlen( file );
|
||||
|
||||
/* Look for (member) */
|
||||
|
||||
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
|
||||
{
|
||||
f->f_member.ptr = p + 1;
|
||||
f->f_member.len = end - p - 2;
|
||||
end = p;
|
||||
}
|
||||
|
||||
/* Look for .suffix */
|
||||
/* This would be memrchr() */
|
||||
|
||||
p = 0;
|
||||
q = file;
|
||||
|
||||
while( q = (char *)memchr( q, '.', end - q ) )
|
||||
p = q++;
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_suffix.ptr = p;
|
||||
f->f_suffix.len = end - p;
|
||||
end = p;
|
||||
}
|
||||
|
||||
/* Leaves base */
|
||||
|
||||
f->f_base.ptr = file;
|
||||
f->f_base.len = end - file;
|
||||
}
|
||||
|
||||
/*
|
||||
* file_build() - build a filename given dir/base/suffix/member
|
||||
*/
|
||||
|
||||
void
|
||||
file_build(
|
||||
FILENAME *f,
|
||||
string *file,
|
||||
int binding )
|
||||
{
|
||||
file_build1( f, file );
|
||||
|
||||
/* Don't prepend root if it's . or directory is rooted */
|
||||
# if PATH_DELIM == '/'
|
||||
|
||||
if( f->f_root.len
|
||||
&& !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
|
||||
&& !( f->f_dir.len && f->f_dir.ptr[0] == '/' ) )
|
||||
|
||||
# else /* unix */
|
||||
|
||||
if( f->f_root.len
|
||||
&& !( f->f_root.len == 1 && f->f_root.ptr[0] == '.' )
|
||||
&& !( f->f_dir.len && f->f_dir.ptr[0] == '/' )
|
||||
&& !( f->f_dir.len && f->f_dir.ptr[0] == '\\' )
|
||||
&& !( f->f_dir.len && f->f_dir.ptr[1] == ':' ) )
|
||||
|
||||
# endif /* unix */
|
||||
|
||||
{
|
||||
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
|
||||
string_push_back( file, PATH_DELIM );
|
||||
}
|
||||
|
||||
if( f->f_dir.len )
|
||||
{
|
||||
string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
|
||||
}
|
||||
|
||||
/* UNIX: Put / between dir and file */
|
||||
/* NT: Put \ between dir and file */
|
||||
|
||||
if( f->f_dir.len && ( f->f_base.len || f->f_suffix.len ) )
|
||||
{
|
||||
/* UNIX: Special case for dir \ : don't add another \ */
|
||||
/* NT: Special case for dir / : don't add another / */
|
||||
|
||||
# if PATH_DELIM == '\\'
|
||||
if( !( f->f_dir.len == 3 && f->f_dir.ptr[1] == ':' ) )
|
||||
# endif
|
||||
if( !( f->f_dir.len == 1 && f->f_dir.ptr[0] == PATH_DELIM ) )
|
||||
string_push_back( file, PATH_DELIM );
|
||||
}
|
||||
|
||||
if( f->f_base.len )
|
||||
{
|
||||
string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
|
||||
}
|
||||
|
||||
if( f->f_suffix.len )
|
||||
{
|
||||
string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
|
||||
}
|
||||
|
||||
if( f->f_member.len )
|
||||
{
|
||||
string_push_back( file, '(' );
|
||||
string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
|
||||
string_push_back( file, ')' );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* file_parent() - make a FILENAME point to its parent dir
|
||||
*/
|
||||
|
||||
void
|
||||
file_parent( FILENAME *f )
|
||||
{
|
||||
/* just set everything else to nothing */
|
||||
|
||||
f->f_base.ptr =
|
||||
f->f_suffix.ptr =
|
||||
f->f_member.ptr = "";
|
||||
|
||||
f->f_base.len =
|
||||
f->f_suffix.len =
|
||||
f->f_member.len = 0;
|
||||
}
|
||||
|
||||
# endif /* unix, NT, OS/2, AmigaOS */
|
||||
410
historic/jam/src/pathvms.c
Normal file
410
historic/jam/src/pathvms.c
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "filesys.h"
|
||||
|
||||
# ifdef OS_VMS
|
||||
|
||||
# define DEBUG
|
||||
|
||||
/*
|
||||
* pathvms.c - manipulate file names on VMS
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* file_parse() - split a file name into dir/base/suffix/member
|
||||
* file_build() - build a filename given dir/base/suffix/member
|
||||
* file_parent() - make a FILENAME point to its parent dir
|
||||
*
|
||||
* File_parse() and file_build() just manipuate a string and a structure;
|
||||
* they do not make system calls.
|
||||
*
|
||||
* WARNING! This file contains voodoo logic, as black magic is
|
||||
* necessary for wrangling with VMS file name. Woe be to people
|
||||
* who mess with this code.
|
||||
*
|
||||
* 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
|
||||
* 05/03/96 (seiwald) - split from filevms.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* file_parse() - split a file name into dir/base/suffix/member
|
||||
*/
|
||||
|
||||
void
|
||||
file_parse(
|
||||
char *file,
|
||||
FILENAME *f )
|
||||
{
|
||||
char *p, *q;
|
||||
char *end;
|
||||
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
|
||||
/* Look for <grist> */
|
||||
|
||||
if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
/* Look for dev:[dir] or dev: */
|
||||
|
||||
if( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p + 1 - file;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
end = file + strlen( file );
|
||||
|
||||
/* Look for (member) */
|
||||
|
||||
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
|
||||
{
|
||||
f->f_member.ptr = p + 1;
|
||||
f->f_member.len = end - p - 2;
|
||||
end = p;
|
||||
}
|
||||
|
||||
/* Look for .suffix */
|
||||
/* This would be memrchr() */
|
||||
|
||||
p = 0;
|
||||
q = file;
|
||||
|
||||
while( q = memchr( q, '.', end - q ) )
|
||||
p = q++;
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_suffix.ptr = p;
|
||||
f->f_suffix.len = end - p;
|
||||
end = p;
|
||||
}
|
||||
|
||||
/* Leaves base */
|
||||
|
||||
f->f_base.ptr = file;
|
||||
f->f_base.len = end - file;
|
||||
|
||||
/* Is this a directory without a file spec? */
|
||||
|
||||
f->parent = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* dir mods result
|
||||
* --- --- ------
|
||||
* Rerooting:
|
||||
*
|
||||
* (none) :R=dev: dev:
|
||||
* devd: :R=dev: devd:
|
||||
* devd:[dir] :R=dev: devd:[dir]
|
||||
* [.dir] :R=dev: dev:[dir] questionable
|
||||
* [dir] :R=dev: dev:[dir]
|
||||
*
|
||||
* (none) :R=[rdir] [rdir] questionable
|
||||
* devd: :R=[rdir] devd:
|
||||
* devd:[dir] :R=[rdir] devd:[dir]
|
||||
* [.dir] :R=[rdir] [rdir.dir] questionable
|
||||
* [dir] :R=[rdir] [rdir]
|
||||
*
|
||||
* (none) :R=dev:[root] dev:[root]
|
||||
* devd: :R=dev:[root] devd:
|
||||
* devd:[dir] :R=dev:[root] devd:[dir]
|
||||
* [.dir] :R=dev:[root] dev:[root.dir]
|
||||
* [dir] :R=dev:[root] [dir]
|
||||
*
|
||||
* Climbing to parent:
|
||||
*
|
||||
*/
|
||||
|
||||
# define DIR_EMPTY 0 /* empty string */
|
||||
# define DIR_DEV 1 /* dev: */
|
||||
# define DIR_DEVDIR 2 /* dev:[dir] */
|
||||
# define DIR_DOTDIR 3 /* [.dir] */
|
||||
# define DIR_DASHDIR 4 /* [-] or [-.dir] */
|
||||
# define DIR_ABSDIR 5 /* [dir] */
|
||||
# define DIR_ROOT 6 /* [000000] or dev:[000000] */
|
||||
|
||||
# define G_DIR 0 /* take just dir */
|
||||
# define G_ROOT 1 /* take just root */
|
||||
# define G_VAD 2 /* root's dev: + [abs] */
|
||||
# define G_DRD 3 /* root's dev:[dir] + [.rel] */
|
||||
# define G_VRD 4 /* root's dev: + [.rel] made [abs] */
|
||||
# define G_DDD 5 /* root's dev:[dir] + . + [dir] */
|
||||
|
||||
static int grid[7][7] = {
|
||||
|
||||
/* root/dir EMPTY DEV DEVDIR DOTDIR DASH, ABSDIR ROOT */
|
||||
/* EMPTY */ G_DIR, G_DIR, G_DIR, G_DIR, G_DIR, G_DIR, G_DIR,
|
||||
/* DEV */ G_ROOT, G_DIR, G_DIR, G_VRD, G_VAD, G_VAD, G_VAD,
|
||||
/* DEVDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_VAD, G_VAD, G_VAD,
|
||||
/* DOTDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
|
||||
/* DASHDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DDD, G_DIR, G_DIR,
|
||||
/* ABSDIR */ G_ROOT, G_DIR, G_DIR, G_DRD, G_DIR, G_DIR, G_DIR,
|
||||
/* ROOT */ G_ROOT, G_DIR, G_DIR, G_VRD, G_DIR, G_DIR, G_DIR,
|
||||
|
||||
} ;
|
||||
|
||||
struct dirinf {
|
||||
int flags;
|
||||
|
||||
struct {
|
||||
char *ptr;
|
||||
int len;
|
||||
} dev, dir;
|
||||
} ;
|
||||
|
||||
static char *
|
||||
strnchr(
|
||||
char *buf,
|
||||
int c,
|
||||
int len )
|
||||
{
|
||||
while( len-- )
|
||||
if( *buf && *buf++ == c )
|
||||
return buf - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dir_flags(
|
||||
char *buf,
|
||||
int len,
|
||||
struct dirinf *i )
|
||||
{
|
||||
char *p;
|
||||
|
||||
if( !buf || !len )
|
||||
{
|
||||
i->flags = DIR_EMPTY;
|
||||
i->dev.ptr =
|
||||
i->dir.ptr = 0;
|
||||
i->dev.len =
|
||||
i->dir.len = 0;
|
||||
}
|
||||
else if( p = strnchr( buf, ':', len ) )
|
||||
{
|
||||
i->dev.ptr = buf;
|
||||
i->dev.len = p + 1 - buf;
|
||||
i->dir.ptr = buf + i->dev.len;
|
||||
i->dir.len = len - i->dev.len;
|
||||
i->flags = i->dir.len && *i->dir.ptr == '[' ? DIR_DEVDIR : DIR_DEV;
|
||||
}
|
||||
else
|
||||
{
|
||||
i->dev.ptr = buf;
|
||||
i->dev.len = 0;
|
||||
i->dir.ptr = buf;
|
||||
i->dir.len = len;
|
||||
|
||||
if( *buf == '[' && buf[1] == ']' )
|
||||
i->flags = DIR_EMPTY;
|
||||
else if( *buf == '[' && buf[1] == '.' )
|
||||
i->flags = DIR_DOTDIR;
|
||||
else if( *buf == '[' && buf[1] == '-' )
|
||||
i->flags = DIR_DASHDIR;
|
||||
else
|
||||
i->flags = DIR_ABSDIR;
|
||||
}
|
||||
|
||||
/* But if its rooted in any way */
|
||||
|
||||
if( i->dir.len == 8 && !strncmp( i->dir.ptr, "[000000]", 8 ) )
|
||||
i->flags = DIR_ROOT;
|
||||
}
|
||||
|
||||
/*
|
||||
* file_build() - build a filename given dir/base/suffix/member
|
||||
*/
|
||||
|
||||
void
|
||||
file_build(
|
||||
FILENAME *f,
|
||||
string *file,
|
||||
int binding )
|
||||
{
|
||||
struct dirinf root, dir;
|
||||
int g;
|
||||
|
||||
file_build1( f, file );
|
||||
|
||||
/* Get info on root and dir for combining. */
|
||||
|
||||
dir_flags( f->f_root.ptr, f->f_root.len, &root );
|
||||
dir_flags( f->f_dir.ptr, f->f_dir.len, &dir );
|
||||
|
||||
/* Combine */
|
||||
|
||||
switch( g = grid[ root.flags ][ dir.flags ] )
|
||||
{
|
||||
case G_DIR:
|
||||
/* take dir */
|
||||
string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len );
|
||||
break;
|
||||
|
||||
case G_ROOT:
|
||||
/* take root */
|
||||
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
|
||||
break;
|
||||
|
||||
case G_VAD:
|
||||
/* root's dev + abs directory */
|
||||
string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len );
|
||||
string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len );
|
||||
break;
|
||||
|
||||
case G_DRD:
|
||||
case G_DDD:
|
||||
/* root's dev:[dir] + rel directory */
|
||||
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
|
||||
|
||||
/* sanity checks: root ends with ] */
|
||||
|
||||
if( file->value[file->size - 1] == ']' )
|
||||
string_pop_back( file );
|
||||
|
||||
/* Add . if separating two -'s */
|
||||
|
||||
if( g == G_DDD )
|
||||
string_push_back( file, '.' );
|
||||
|
||||
/* skip [ of dir */
|
||||
string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1 );
|
||||
break;
|
||||
|
||||
case G_VRD:
|
||||
/* root's dev + rel directory made abs */
|
||||
string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len );
|
||||
string_push_back( file, '[' );
|
||||
/* skip [. of rel dir */
|
||||
string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2 );
|
||||
break;
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
if( DEBUG_SEARCH && ( root.flags || dir.flags ) )
|
||||
{
|
||||
printf( "%d x %d = %d (%s)\n", root.flags, dir.flags,
|
||||
grid[ root.flags ][ dir.flags ], file->value );
|
||||
}
|
||||
# endif
|
||||
|
||||
/*
|
||||
* Now do the special :P modifier when no file was present.
|
||||
* (none) (none)
|
||||
* [dir1.dir2] [dir1]
|
||||
* [dir] [000000]
|
||||
* [.dir] []
|
||||
* [] []
|
||||
*/
|
||||
|
||||
if( file->value[file->size - 1] == ']' && f->parent )
|
||||
{
|
||||
char* p = file->value + file->size;
|
||||
while( p-- > file->value )
|
||||
{
|
||||
if( *p == '.' )
|
||||
{
|
||||
string_truncate( file, p - file->value );
|
||||
string_push_back( file, ']' );
|
||||
break;
|
||||
}
|
||||
else if( *p == '-' )
|
||||
{
|
||||
/* handle .- or - */
|
||||
if( p > file->value && p[-1] == '.' )
|
||||
--p;
|
||||
|
||||
*p++ = ']';
|
||||
break;
|
||||
}
|
||||
else if( *p == '[' )
|
||||
{
|
||||
if( p[1] == ']' )
|
||||
{
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
string_truncate( file, p - file->value );
|
||||
string_append( file, "[000000]" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now copy the file pieces. */
|
||||
|
||||
if( f->f_base.len )
|
||||
{
|
||||
string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len );
|
||||
}
|
||||
|
||||
/* If there is no suffix, we append a "." onto all generated */
|
||||
/* names. This keeps VMS from appending its own (wrong) idea */
|
||||
/* of what the suffix should be. */
|
||||
|
||||
if( f->f_suffix.len )
|
||||
{
|
||||
string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len );
|
||||
}
|
||||
else if( binding && f->f_base.len )
|
||||
{
|
||||
string_push_back( file, '.' );
|
||||
}
|
||||
|
||||
if( f->f_member.len )
|
||||
{
|
||||
string_push_back( file, '(' );
|
||||
string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len );
|
||||
string_push_back( file, ')' );
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
if( DEBUG_SEARCH )
|
||||
printf("built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n",
|
||||
f->f_root.len, f->f_root.ptr,
|
||||
f->f_dir.len, f->f_dir.ptr,
|
||||
f->f_base.len, f->f_base.ptr,
|
||||
f->f_suffix.len, f->f_suffix.ptr,
|
||||
f->f_member.len, f->f_member.ptr,
|
||||
file->value );
|
||||
# endif
|
||||
}
|
||||
|
||||
/*
|
||||
* file_parent() - make a FILENAME point to its parent dir
|
||||
*/
|
||||
|
||||
void
|
||||
file_parent( FILENAME *f )
|
||||
{
|
||||
if( f->f_base.len )
|
||||
{
|
||||
f->f_base.ptr =
|
||||
f->f_suffix.ptr =
|
||||
f->f_member.ptr = "";
|
||||
|
||||
f->f_base.len =
|
||||
f->f_suffix.len =
|
||||
f->f_member.len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
f->parent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# endif /* VMS */
|
||||
1317
historic/jam/src/regexp.c
Normal file
1317
historic/jam/src/regexp.c
Normal file
File diff suppressed because it is too large
Load Diff
31
historic/jam/src/regexp.h
Normal file
31
historic/jam/src/regexp.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Definitions etc. for regexp(3) routines.
|
||||
*
|
||||
* Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
|
||||
* not the System V one.
|
||||
*/
|
||||
#ifndef REGEXP_DWA20011023_H
|
||||
# define REGEXP_DWA20011023_H
|
||||
|
||||
#define NSUBEXP 10
|
||||
typedef struct regexp {
|
||||
char *startp[NSUBEXP];
|
||||
char *endp[NSUBEXP];
|
||||
char regstart; /* Internal use only. */
|
||||
char reganch; /* Internal use only. */
|
||||
char *regmust; /* Internal use only. */
|
||||
int regmlen; /* Internal use only. */
|
||||
char program[1]; /* Unwarranted chumminess with compiler. */
|
||||
} regexp;
|
||||
|
||||
regexp *regcomp( char *exp );
|
||||
int regexec( regexp *prog, char *string );
|
||||
void regerror( char *s );
|
||||
|
||||
/*
|
||||
* The first byte of the regexp internal "program" is actually this magic
|
||||
* number; the start node begins in the second byte.
|
||||
*/
|
||||
#define MAGIC 0234
|
||||
|
||||
#endif // REGEXP_DWA20011023_H
|
||||
397
historic/jam/src/rules.c
Normal file
397
historic/jam/src/rules.c
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "variable.h"
|
||||
# include "rules.h"
|
||||
# include "newstr.h"
|
||||
# include "hash.h"
|
||||
# include "modules.h"
|
||||
|
||||
/*
|
||||
* rules.c - access to RULEs, TARGETs, and ACTIONs
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* bindrule() - return pointer to RULE, creating it if necessary
|
||||
* bindtarget() - return pointer to TARGET, creating it if necessary
|
||||
* touchtarget() - mark a target to simulate being new
|
||||
* targetlist() - turn list of target names into a TARGET chain
|
||||
* targetentry() - add a TARGET to a chain of TARGETS
|
||||
* actionlist() - append to an ACTION chain
|
||||
* addsettings() - add a deferred "set" command to a target
|
||||
* usesettings() - set all target specific variables
|
||||
* pushsettings() - set all target specific variables
|
||||
* popsettings() - reset target specific variables to their pre-push values
|
||||
* freesettings() - delete a settings list
|
||||
* donerules() - free RULE and TARGET tables
|
||||
*
|
||||
* 04/12/94 (seiwald) - actionlist() now just appends a single action.
|
||||
* 08/23/94 (seiwald) - Support for '+=' (append to variable)
|
||||
*/
|
||||
|
||||
static struct hash *targethash = 0;
|
||||
|
||||
|
||||
/*
|
||||
* bindrule() - return pointer to RULE, creating it if necessary
|
||||
*/
|
||||
|
||||
static RULE *
|
||||
enter_rule( char *rulename, module* m )
|
||||
{
|
||||
RULE rule, *r = &rule;
|
||||
|
||||
r->name = rulename;
|
||||
|
||||
if( hashenter( m->rules, (HASHDATA **)&r ) )
|
||||
{
|
||||
r->name = newstr( rulename ); /* never freed */
|
||||
r->procedure = (PARSE *)0;
|
||||
r->actions = 0;
|
||||
r->arguments = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* bindtarget() - return pointer to TARGET, creating it if necessary
|
||||
*/
|
||||
|
||||
TARGET *
|
||||
bindtarget( char *targetname )
|
||||
{
|
||||
TARGET target, *t = ⌖
|
||||
|
||||
if( !targethash )
|
||||
targethash = hashinit( sizeof( TARGET ), "targets" );
|
||||
|
||||
t->name = targetname;
|
||||
|
||||
if( hashenter( targethash, (HASHDATA **)&t ) )
|
||||
{
|
||||
memset( (char *)t, '\0', sizeof( *t ) );
|
||||
t->name = newstr( targetname ); /* never freed */
|
||||
t->boundname = t->name; /* default for T_FLAG_NOTFILE */
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/*
|
||||
* touchtarget() - mark a target to simulate being new
|
||||
*/
|
||||
|
||||
void
|
||||
touchtarget( char *t )
|
||||
{
|
||||
bindtarget( t )->flags |= T_FLAG_TOUCHED;
|
||||
}
|
||||
|
||||
/*
|
||||
* targetlist() - turn list of target names into a TARGET chain
|
||||
*
|
||||
* Inputs:
|
||||
* chain existing TARGETS to append to
|
||||
* targets list of target names
|
||||
*/
|
||||
|
||||
TARGETS *
|
||||
targetlist(
|
||||
TARGETS *chain,
|
||||
LIST *targets )
|
||||
{
|
||||
for( ; targets; targets = list_next( targets ) )
|
||||
chain = targetentry( chain, bindtarget( targets->string ) );
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
/*
|
||||
* targetentry() - add a TARGET to a chain of TARGETS
|
||||
*
|
||||
* Inputs:
|
||||
* chain exisitng TARGETS to append to
|
||||
* target new target to append
|
||||
*/
|
||||
|
||||
TARGETS *
|
||||
targetentry(
|
||||
TARGETS *chain,
|
||||
TARGET *target )
|
||||
{
|
||||
TARGETS *c;
|
||||
|
||||
c = (TARGETS *)malloc( sizeof( TARGETS ) );
|
||||
c->target = target;
|
||||
|
||||
if( !chain ) chain = c;
|
||||
else chain->tail->next = c;
|
||||
chain->tail = c;
|
||||
c->next = 0;
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
/*
|
||||
* actionlist() - append to an ACTION chain
|
||||
*/
|
||||
|
||||
ACTIONS *
|
||||
actionlist(
|
||||
ACTIONS *chain,
|
||||
ACTION *action )
|
||||
{
|
||||
ACTIONS *actions = (ACTIONS *)malloc( sizeof( ACTIONS ) );
|
||||
|
||||
actions->action = action;
|
||||
|
||||
if( !chain ) chain = actions;
|
||||
else chain->tail->next = actions;
|
||||
chain->tail = actions;
|
||||
actions->next = 0;
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
static SETTINGS* settings_freelist;
|
||||
|
||||
/*
|
||||
* addsettings() - add a deferred "set" command to a target
|
||||
*
|
||||
* Adds a variable setting (varname=list) onto a chain of settings
|
||||
* for a particular target. Replaces the previous previous value,
|
||||
* if any, unless 'append' says to append the new list onto the old.
|
||||
* Returns the head of the chain of settings.
|
||||
*/
|
||||
|
||||
SETTINGS *
|
||||
addsettings(
|
||||
SETTINGS *head,
|
||||
int append,
|
||||
char *symbol,
|
||||
LIST *value )
|
||||
{
|
||||
SETTINGS *v;
|
||||
|
||||
/* Look for previous setting */
|
||||
|
||||
for( v = head; v; v = v->next )
|
||||
if( !strcmp( v->symbol, symbol ) )
|
||||
break;
|
||||
|
||||
/* If not previously set, alloc a new. */
|
||||
/* If appending, do so. */
|
||||
/* Else free old and set new. */
|
||||
|
||||
if( !v )
|
||||
{
|
||||
v = settings_freelist;
|
||||
|
||||
if ( v )
|
||||
settings_freelist = v->next;
|
||||
else
|
||||
v = (SETTINGS *)malloc( sizeof( *v ) );
|
||||
|
||||
v->symbol = newstr( symbol );
|
||||
v->value = value;
|
||||
v->next = head;
|
||||
head = v;
|
||||
}
|
||||
else if( append )
|
||||
{
|
||||
v->value = list_append( v->value, value );
|
||||
}
|
||||
else
|
||||
{
|
||||
list_free( v->value );
|
||||
v->value = value;
|
||||
}
|
||||
|
||||
/* Return (new) head of list. */
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/*
|
||||
* pushsettings() - set all target specific variables
|
||||
*/
|
||||
|
||||
void
|
||||
pushsettings( SETTINGS *v )
|
||||
{
|
||||
for( ; v; v = v->next )
|
||||
v->value = var_swap( v->symbol, v->value );
|
||||
}
|
||||
|
||||
/*
|
||||
* popsettings() - reset target specific variables to their pre-push values
|
||||
*/
|
||||
|
||||
void
|
||||
popsettings( SETTINGS *v )
|
||||
{
|
||||
pushsettings( v ); /* just swap again */
|
||||
}
|
||||
|
||||
/*
|
||||
* freesettings() - delete a settings list
|
||||
*/
|
||||
|
||||
void
|
||||
freesettings( SETTINGS *v )
|
||||
{
|
||||
while( v )
|
||||
{
|
||||
SETTINGS *n = v->next;
|
||||
|
||||
freestr( v->symbol );
|
||||
list_free( v->value );
|
||||
v->next = settings_freelist;
|
||||
settings_freelist = v;
|
||||
|
||||
v = n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* donerules() - free TARGET tables
|
||||
*/
|
||||
|
||||
void
|
||||
donerules()
|
||||
{
|
||||
hashdone( targethash );
|
||||
while ( settings_freelist )
|
||||
{
|
||||
SETTINGS* n = settings_freelist->next;
|
||||
free( settings_freelist );
|
||||
settings_freelist = n;
|
||||
}
|
||||
}
|
||||
|
||||
argument_list* args_new()
|
||||
{
|
||||
argument_list* r = malloc( sizeof(argument_list) );
|
||||
r->reference_count = 0;
|
||||
lol_init(r->data);
|
||||
return r;
|
||||
}
|
||||
|
||||
void args_refer( argument_list* a )
|
||||
{
|
||||
++a->reference_count;
|
||||
}
|
||||
|
||||
void args_free( argument_list* a )
|
||||
{
|
||||
if (--a->reference_count <= 0)
|
||||
{
|
||||
lol_free(a->data);
|
||||
free(a);
|
||||
}
|
||||
}
|
||||
|
||||
void actions_refer(rule_actions* a)
|
||||
{
|
||||
++a->reference_count;
|
||||
}
|
||||
|
||||
void actions_free(rule_actions* a)
|
||||
{
|
||||
if (--a->reference_count <= 0)
|
||||
{
|
||||
freestr(a->command);
|
||||
list_free(a->bindlist);
|
||||
free(a);
|
||||
}
|
||||
}
|
||||
|
||||
void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure )
|
||||
{
|
||||
if ( args )
|
||||
args_refer( args );
|
||||
if ( rule->arguments )
|
||||
args_free( rule->arguments );
|
||||
rule->arguments = args;
|
||||
|
||||
if ( procedure )
|
||||
parse_refer( procedure );
|
||||
if ( rule->procedure )
|
||||
parse_free( rule->procedure );
|
||||
rule->procedure = procedure;
|
||||
}
|
||||
|
||||
static RULE* global_rule( char* rulename, module* m )
|
||||
{
|
||||
char global_name[4096] = "";
|
||||
strncat(global_name, m->name, sizeof(global_name) - 1);
|
||||
strncat(global_name, rulename, sizeof(global_name) - 1);
|
||||
return enter_rule( global_name, root_module() );
|
||||
}
|
||||
|
||||
RULE* new_rule_body( module* m, char* rulename, argument_list* args, PARSE* procedure )
|
||||
{
|
||||
RULE* local = enter_rule( rulename, m );
|
||||
RULE* global = global_rule( rulename, m );
|
||||
procedure->module = m;
|
||||
procedure->rulename = copystr( global->name );
|
||||
set_rule_body( local, args, procedure );
|
||||
set_rule_body( global, args, procedure );
|
||||
|
||||
return local;
|
||||
}
|
||||
|
||||
static void set_rule_actions( RULE* rule, rule_actions* actions )
|
||||
{
|
||||
if ( actions )
|
||||
actions_refer( actions );
|
||||
if ( rule->actions )
|
||||
actions_free( rule->actions );
|
||||
rule->actions = actions;
|
||||
|
||||
}
|
||||
|
||||
static rule_actions* actions_new( char* command, LIST* bindlist, int flags )
|
||||
{
|
||||
rule_actions* result = malloc(sizeof(rule_actions));
|
||||
result->command = copystr( command );
|
||||
result->bindlist = bindlist;
|
||||
result->flags = flags;
|
||||
result->reference_count = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
RULE* new_rule_actions( module* m, char* rulename, char* command, LIST* bindlist, int flags )
|
||||
{
|
||||
RULE* local = enter_rule( rulename, m );
|
||||
RULE* global = global_rule( rulename, m );
|
||||
set_rule_actions( local, actions_new( command, bindlist, flags ) );
|
||||
set_rule_actions( global, local->actions );
|
||||
return local;
|
||||
}
|
||||
|
||||
RULE *bindrule( char *rulename, module* m )
|
||||
{
|
||||
RULE rule, *r = &rule;
|
||||
r->name = rulename;
|
||||
|
||||
if ( hashcheck( m->rules, (HASHDATA **)&r ) )
|
||||
return r;
|
||||
else
|
||||
return enter_rule( rulename, root_module() );
|
||||
}
|
||||
|
||||
RULE* import_rule( RULE* source, module* m, char* name )
|
||||
{
|
||||
RULE* dest = enter_rule( name, m );
|
||||
set_rule_body( dest, source->arguments, source->procedure );
|
||||
set_rule_actions( dest, source->actions );
|
||||
return dest;
|
||||
}
|
||||
216
historic/jam/src/rules.h
Normal file
216
historic/jam/src/rules.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
#ifndef RULES_DWA_20011020_H
|
||||
# define RULES_DWA_20011020_H
|
||||
|
||||
# include "modules.h"
|
||||
|
||||
/*
|
||||
* rules.h - targets, rules, and related information
|
||||
*
|
||||
* This file describes the structures holding the targets, rules, and
|
||||
* related information accumulated by interpreting the statements
|
||||
* of the jam files.
|
||||
*
|
||||
* The following are defined:
|
||||
*
|
||||
* RULE - a generic jam rule, the product of RULE and ACTIONS
|
||||
* ACTIONS - a chain of ACTIONs
|
||||
* ACTION - a RULE instance with targets and sources
|
||||
* SETTINGS - variables to set when executing a TARGET's ACTIONS
|
||||
* TARGETS - a chain of TARGETs
|
||||
* TARGET - a file or "thing" that can be built
|
||||
*
|
||||
* 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET.
|
||||
* 04/12/94 (seiwald) - actionlist() now just appends a single action.
|
||||
* 06/01/94 (seiwald) - new 'actions existing' does existing sources
|
||||
* 12/20/94 (seiwald) - NOTIME renamed NOTFILE.
|
||||
* 01/19/95 (seiwald) - split DONTKNOW into CANTFIND/CANTMAKE.
|
||||
* 02/02/95 (seiwald) - new LEAVES modifier on targets.
|
||||
* 02/14/95 (seiwald) - new NOUPDATE modifier on targets.
|
||||
*/
|
||||
|
||||
typedef struct _rule RULE;
|
||||
typedef struct _target TARGET;
|
||||
typedef struct _targets TARGETS;
|
||||
typedef struct _action ACTION;
|
||||
typedef struct _actions ACTIONS;
|
||||
typedef struct _settings SETTINGS ;
|
||||
|
||||
/* RULE - a generic jam rule, the product of RULE and ACTIONS */
|
||||
|
||||
/* A rule's argument list */
|
||||
struct argument_list
|
||||
{
|
||||
int reference_count;
|
||||
LOL data[1];
|
||||
};
|
||||
|
||||
/* The build actions corresponding to a rule */
|
||||
struct rule_actions
|
||||
{
|
||||
int reference_count;
|
||||
char* command; /* command string from ACTIONS */
|
||||
LIST* bindlist;
|
||||
int flags; /* modifiers on ACTIONS */
|
||||
|
||||
# define RULE_NEWSRCS 0x01 /* $(>) is updated sources only */
|
||||
# define RULE_TOGETHER 0x02 /* combine actions on single target */
|
||||
# define RULE_IGNORE 0x04 /* ignore return status of executes */
|
||||
# define RULE_QUIETLY 0x08 /* don't mention it unless verbose */
|
||||
# define RULE_PIECEMEAL 0x10 /* split exec so each $(>) is small */
|
||||
# define RULE_EXISTING 0x20 /* $(>) is pre-exisitng sources only */
|
||||
};
|
||||
|
||||
typedef struct rule_actions rule_actions;
|
||||
typedef struct argument_list argument_list;
|
||||
|
||||
struct _rule {
|
||||
char *name;
|
||||
PARSE *procedure; /* parse tree from RULE */
|
||||
argument_list* arguments; /* argument checking info, or NULL for unchecked */
|
||||
rule_actions* actions; /* build actions, or NULL for no actions */
|
||||
} ;
|
||||
|
||||
/* ACTIONS - a chain of ACTIONs */
|
||||
|
||||
struct _actions {
|
||||
ACTIONS *next;
|
||||
ACTIONS *tail; /* valid only for head */
|
||||
ACTION *action;
|
||||
} ;
|
||||
|
||||
/* ACTION - a RULE instance with targets and sources */
|
||||
|
||||
struct _action {
|
||||
RULE *rule;
|
||||
TARGETS *targets;
|
||||
TARGETS *sources; /* aka $(>) */
|
||||
char running; /* has been started */
|
||||
char status; /* see TARGET status */
|
||||
} ;
|
||||
|
||||
/* SETTINGS - variables to set when executing a TARGET's ACTIONS */
|
||||
|
||||
struct _settings {
|
||||
SETTINGS *next;
|
||||
char *symbol; /* symbol name for var_set() */
|
||||
LIST *value; /* symbol value for var_set() */
|
||||
} ;
|
||||
|
||||
/* TARGETS - a chain of TARGETs */
|
||||
|
||||
struct _targets {
|
||||
TARGETS *next;
|
||||
TARGETS *tail; /* valid only for head */
|
||||
TARGET *target;
|
||||
} ;
|
||||
|
||||
/* TARGET - a file or "thing" that can be built */
|
||||
|
||||
struct _target {
|
||||
char *name;
|
||||
char *boundname; /* if search() relocates target */
|
||||
ACTIONS *actions; /* rules to execute, if any */
|
||||
SETTINGS *settings; /* variables to define */
|
||||
|
||||
char flags; /* status info */
|
||||
|
||||
# define T_FLAG_TEMP 0x01 /* TEMPORARY applied */
|
||||
# define T_FLAG_NOCARE 0x02 /* NOCARE applied */
|
||||
# define T_FLAG_NOTFILE 0x04 /* NOTFILE applied */
|
||||
# define T_FLAG_TOUCHED 0x08 /* ALWAYS applied or -t target */
|
||||
# define T_FLAG_LEAVES 0x10 /* LEAVES applied */
|
||||
# define T_FLAG_NOUPDATE 0x20 /* NOUPDATE applied */
|
||||
|
||||
/* this flag was added to support a new builting rule named "FAIL_EXPECTED" */
|
||||
/* it is used to indicate that the result of running a given action should */
|
||||
/* be inverted (i.e. ok <=> fail). This is useful to launch certain test */
|
||||
/* runs from a Jamfile.. */
|
||||
/* */
|
||||
# define T_FLAG_FAIL_EXPECTED 0x40 /* FAIL_EXPECTED applied */
|
||||
|
||||
char binding; /* how target relates to real file */
|
||||
|
||||
# define T_BIND_UNBOUND 0 /* a disembodied name */
|
||||
# define T_BIND_MISSING 1 /* couldn't find real file */
|
||||
# define T_BIND_PARENTS 2 /* using parent's timestamp */
|
||||
# define T_BIND_EXISTS 3 /* real file, timestamp valid */
|
||||
|
||||
TARGETS *deps[2]; /* dependencies, with possible
|
||||
* duplicates. Element 1 holds
|
||||
* dependencies generated by INCLUDES */
|
||||
|
||||
# define T_DEPS_DEPENDS 0 /* due to DEPENDS */
|
||||
# define T_DEPS_INCLUDES 1 /* due to INCLUDES */
|
||||
|
||||
time_t time; /* update time */
|
||||
time_t leaf; /* update time of leaf sources */
|
||||
time_t htime; /* header's time */
|
||||
time_t hleaf; /* update time of leaf headers */
|
||||
|
||||
char fate; /* make0()'s diagnosis */
|
||||
char hfate; /* collected fate for headers */
|
||||
|
||||
# define T_FATE_INIT 0 /* nothing done to target */
|
||||
# define T_FATE_MAKING 1 /* make0(target) on stack */
|
||||
|
||||
# define T_FATE_STABLE 2 /* target didn't need updating */
|
||||
# define T_FATE_NEWER 3 /* target newer than parent */
|
||||
|
||||
# define T_FATE_SPOIL 4 /* >= SPOIL rebuilds parents */
|
||||
# define T_FATE_ISTMP 4 /* unneeded temp target oddly present */
|
||||
|
||||
# define T_FATE_BUILD 5 /* >= BUILD rebuilds target */
|
||||
# define T_FATE_TOUCHED 5 /* manually touched with -t */
|
||||
# define T_FATE_MISSING 6 /* is missing, needs updating */
|
||||
# define T_FATE_OUTDATED 7 /* is out of date, needs updating */
|
||||
# define T_FATE_UPDATE 8 /* deps updated, needs updating */
|
||||
|
||||
# define T_FATE_BROKEN 9 /* >= BROKEN ruins parents */
|
||||
# define T_FATE_CANTFIND 9 /* no rules to make missing target */
|
||||
# define T_FATE_CANTMAKE 10 /* can't find dependents */
|
||||
|
||||
char progress; /* tracks make1() progress */
|
||||
|
||||
# define T_MAKE_INIT 0 /* make1(target) not yet called */
|
||||
# define T_MAKE_ONSTACK 1 /* make1(target) on stack */
|
||||
# define T_MAKE_ACTIVE 2 /* make1(target) in make1b() */
|
||||
# define T_MAKE_RUNNING 3 /* make1(target) running commands */
|
||||
# define T_MAKE_DONE 4 /* make1(target) done */
|
||||
|
||||
char status; /* execcmd() result */
|
||||
|
||||
int asynccnt; /* child deps outstanding */
|
||||
TARGETS *parents; /* used by make1() for completion */
|
||||
char *cmds; /* type-punned command list */
|
||||
} ;
|
||||
|
||||
RULE *bindrule( char *rulename, module* );
|
||||
|
||||
RULE* import_rule( RULE* source, module* m, char* name );
|
||||
RULE* new_rule_body( module* m, char* rulename, argument_list* args, PARSE* procedure );
|
||||
RULE* new_rule_actions( module* m, char* rulename, char* command, LIST* bindlist, int flags );
|
||||
TARGET *bindtarget( char *targetname );
|
||||
void touchtarget( char *t );
|
||||
TARGETS *targetlist( TARGETS *chain, LIST *targets );
|
||||
TARGETS *targetentry( TARGETS *chain, TARGET *target );
|
||||
ACTIONS *actionlist( ACTIONS *chain, ACTION *action );
|
||||
SETTINGS *addsettings( SETTINGS *head, int append, char *symbol, LIST *value );
|
||||
void pushsettings( SETTINGS *v );
|
||||
void popsettings( SETTINGS *v );
|
||||
void freesettings( SETTINGS *v );
|
||||
void donerules();
|
||||
|
||||
argument_list* args_new();
|
||||
void args_refer( argument_list* );
|
||||
void args_free( argument_list* );
|
||||
|
||||
void actions_refer(rule_actions*);
|
||||
void actions_free(rule_actions*);
|
||||
|
||||
#endif // RULES_DWA_20011020_H
|
||||
374
historic/jam/src/scan.c
Normal file
374
historic/jam/src/scan.c
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "scan.h"
|
||||
# include "jamgram.h"
|
||||
# include "jambase.h"
|
||||
# include "newstr.h"
|
||||
|
||||
/*
|
||||
* scan.c - the jam yacc scanner
|
||||
*
|
||||
* 12/26/93 (seiwald) - bump buf in yylex to 10240 - yuk.
|
||||
* 09/16/94 (seiwald) - check for overflows, unmatched {}'s, etc.
|
||||
* Also handle tokens abutting EOF by remembering
|
||||
* to return EOF now matter how many times yylex()
|
||||
* reinvokes yyline().
|
||||
* 02/11/95 (seiwald) - honor only punctuation keywords if SCAN_PUNCT.
|
||||
* 07/27/95 (seiwald) - Include jamgram.h after scan.h, so that YYSTYPE is
|
||||
* defined before Linux's yacc tries to redefine it.
|
||||
*/
|
||||
|
||||
struct keyword {
|
||||
char *word;
|
||||
int type;
|
||||
} keywords[] = {
|
||||
# include "jamgramtab.h"
|
||||
{ 0, 0 }
|
||||
} ;
|
||||
|
||||
struct include {
|
||||
struct include *next; /* next serial include file */
|
||||
char *string; /* pointer into current line */
|
||||
char **strings; /* for yyfparse() -- text to parse */
|
||||
FILE *file; /* for yyfparse() -- file being read */
|
||||
char *fname; /* for yyfparse() -- file name */
|
||||
int line; /* line counter for error messages */
|
||||
char buf[ 512 ]; /* for yyfparse() -- line buffer */
|
||||
} ;
|
||||
|
||||
static struct include *incp = 0; /* current file; head of chain */
|
||||
|
||||
static int scanmode = SCAN_NORMAL;
|
||||
static int anyerrors = 0;
|
||||
static char *symdump( YYSTYPE *s );
|
||||
|
||||
# define BIGGEST_TOKEN 10240 /* no single token can be larger */
|
||||
|
||||
/*
|
||||
* Set parser mode: normal, string, or keyword
|
||||
*/
|
||||
|
||||
void
|
||||
yymode( int n )
|
||||
{
|
||||
scanmode = n;
|
||||
}
|
||||
|
||||
void
|
||||
yyerror( char *s )
|
||||
{
|
||||
if( incp )
|
||||
printf( "%s: line %d: ", incp->fname, incp->line );
|
||||
|
||||
printf( "%s at %s\n", s, symdump( &yylval ) );
|
||||
|
||||
++anyerrors;
|
||||
}
|
||||
|
||||
int
|
||||
yyanyerrors()
|
||||
{
|
||||
return anyerrors != 0;
|
||||
}
|
||||
|
||||
void
|
||||
yyfparse( char *s )
|
||||
{
|
||||
struct include *i = (struct include *)malloc( sizeof( *i ) );
|
||||
|
||||
/* Push this onto the incp chain. */
|
||||
|
||||
i->string = "";
|
||||
i->strings = 0;
|
||||
i->file = 0;
|
||||
i->fname = copystr( s );
|
||||
i->line = 0;
|
||||
i->next = incp;
|
||||
incp = i;
|
||||
|
||||
/* If the filename is "+", it means use the internal jambase. */
|
||||
|
||||
if( !strcmp( s, "+" ) )
|
||||
i->strings = jambase;
|
||||
}
|
||||
|
||||
/*
|
||||
* yyline() - read new line and return first character
|
||||
*
|
||||
* Fabricates a continuous stream of characters across include files,
|
||||
* returning EOF at the bitter end.
|
||||
*/
|
||||
|
||||
int
|
||||
yyline()
|
||||
{
|
||||
struct include *i = incp;
|
||||
|
||||
if( !incp )
|
||||
return EOF;
|
||||
|
||||
/* Once we start reading from the input stream, we reset the */
|
||||
/* include insertion point so that the next include file becomes */
|
||||
/* the head of the list. */
|
||||
|
||||
/* If there is more data in this line, return it. */
|
||||
|
||||
if( *i->string )
|
||||
return *i->string++;
|
||||
|
||||
/* If we're reading from an internal string list, go to the */
|
||||
/* next string. */
|
||||
|
||||
if( i->strings )
|
||||
{
|
||||
if( !*i->strings )
|
||||
goto next;
|
||||
|
||||
i->line++;
|
||||
i->string = *(i->strings++);
|
||||
return *i->string++;
|
||||
}
|
||||
|
||||
/* If necessary, open the file */
|
||||
|
||||
if( !i->file )
|
||||
{
|
||||
FILE *f = stdin;
|
||||
|
||||
if( strcmp( i->fname, "-" ) && !( f = fopen( i->fname, "r" ) ) )
|
||||
perror( i->fname );
|
||||
|
||||
i->file = f;
|
||||
}
|
||||
|
||||
/* If there's another line in this file, start it. */
|
||||
|
||||
if( i->file && fgets( i->buf, sizeof( i->buf ), i->file ) )
|
||||
{
|
||||
i->line++;
|
||||
i->string = i->buf;
|
||||
return *i->string++;
|
||||
}
|
||||
|
||||
next:
|
||||
/* This include is done. */
|
||||
/* Free it up and return EOF so yyparse() returns to parse_file(). */
|
||||
|
||||
incp = i->next;
|
||||
|
||||
/* Close file, free name */
|
||||
|
||||
if( i->file && i->file != stdin )
|
||||
fclose( i->file );
|
||||
freestr( i->fname );
|
||||
free( (char *)i );
|
||||
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/*
|
||||
* yylex() - set yylval to current token; return its type
|
||||
*
|
||||
* Macros to move things along:
|
||||
*
|
||||
* yychar() - return and advance character; invalid after EOF
|
||||
* yyprev() - back up one character; invalid before yychar()
|
||||
*
|
||||
* yychar() returns a continuous stream of characters, until it hits
|
||||
* the EOF of the current include file.
|
||||
*/
|
||||
|
||||
# define yychar() ( *incp->string ? *incp->string++ : yyline() )
|
||||
# define yyprev() ( incp->string-- )
|
||||
|
||||
int
|
||||
yylex()
|
||||
{
|
||||
int c;
|
||||
char buf[BIGGEST_TOKEN];
|
||||
char *b = buf;
|
||||
|
||||
if( !incp )
|
||||
goto eof;
|
||||
|
||||
/* Get first character (whitespace or of token) */
|
||||
|
||||
c = yychar();
|
||||
|
||||
if( scanmode == SCAN_STRING )
|
||||
{
|
||||
/* If scanning for a string (action's {}'s), look for the */
|
||||
/* closing brace. We handle matching braces, if they match! */
|
||||
|
||||
int nest = 1;
|
||||
|
||||
while( c != EOF && b < buf + sizeof( buf ) )
|
||||
{
|
||||
if( c == '{' )
|
||||
nest++;
|
||||
|
||||
if( c == '}' && !--nest )
|
||||
break;
|
||||
|
||||
*b++ = c;
|
||||
|
||||
c = yychar();
|
||||
}
|
||||
|
||||
/* We ate the ending brace -- regurgitate it. */
|
||||
|
||||
if( c != EOF )
|
||||
yyprev();
|
||||
|
||||
/* Check obvious errors. */
|
||||
|
||||
if( b == buf + sizeof( buf ) )
|
||||
{
|
||||
yyerror( "action block too big" );
|
||||
goto eof;
|
||||
}
|
||||
|
||||
if( nest )
|
||||
{
|
||||
yyerror( "unmatched {} in action block" );
|
||||
goto eof;
|
||||
}
|
||||
|
||||
*b = 0;
|
||||
yylval.type = STRING;
|
||||
yylval.string = newstr( buf );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
char *b = buf;
|
||||
int inquote = 0;
|
||||
int literal = 0;
|
||||
int hasquote = 0;
|
||||
struct keyword *k;
|
||||
|
||||
/* Eat white space */
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Skip past white space */
|
||||
|
||||
while( c != EOF && isspace( c ) )
|
||||
c = yychar();
|
||||
|
||||
/* Not a comment? Swallow up comment line. */
|
||||
|
||||
if( c != '#' )
|
||||
break;
|
||||
while( ( c = yychar() ) != EOF && c != '\n' )
|
||||
;
|
||||
}
|
||||
|
||||
/* c now points to the first character of a token. */
|
||||
|
||||
if( c == EOF )
|
||||
goto eof;
|
||||
|
||||
/* look for white space to delimit word */
|
||||
/* "'s get stripped but preserve white space */
|
||||
|
||||
while( b < buf + sizeof( buf ) )
|
||||
{
|
||||
if( literal )
|
||||
*b++ = c, literal = 0;
|
||||
else if( c == '\\' )
|
||||
literal++;
|
||||
else if( c == '"' )
|
||||
inquote = !inquote, hasquote++;
|
||||
else
|
||||
*b++ = c;
|
||||
|
||||
if( ( c = yychar() ) == EOF || !inquote && isspace( c ) )
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check obvious errors. */
|
||||
|
||||
if( b == buf + sizeof( buf ) )
|
||||
{
|
||||
yyerror( "string too big" );
|
||||
goto eof;
|
||||
}
|
||||
|
||||
if( inquote )
|
||||
{
|
||||
yyerror( "unmatched \" in string" );
|
||||
goto eof;
|
||||
}
|
||||
|
||||
/* We looked ahead a character - back up. */
|
||||
|
||||
if( c != EOF )
|
||||
yyprev();
|
||||
|
||||
/* scan token table */
|
||||
/* don't scan if it's "anything", $anything, */
|
||||
/* or an alphabetic when were looking for punctuation */
|
||||
|
||||
*b = 0;
|
||||
yylval.type = ARG;
|
||||
|
||||
if( !hasquote &&
|
||||
*buf != '$' &&
|
||||
!( isalpha( *buf ) && scanmode == SCAN_PUNCT ) )
|
||||
{
|
||||
for( k = keywords; k->word; k++ )
|
||||
if( *buf == *k->word && !strcmp( k->word, buf ) )
|
||||
{
|
||||
yylval.type = k->type;
|
||||
yylval.string = k->word; /* used by symdump */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( yylval.type == ARG )
|
||||
yylval.string = newstr( buf );
|
||||
}
|
||||
|
||||
if( DEBUG_SCAN )
|
||||
printf( "scan %s\n", symdump( &yylval ) );
|
||||
|
||||
return yylval.type;
|
||||
|
||||
eof:
|
||||
yylval.type = EOF;
|
||||
return yylval.type;
|
||||
}
|
||||
|
||||
static char *
|
||||
symdump( YYSTYPE *s )
|
||||
{
|
||||
static char buf[ BIGGEST_TOKEN + 20 ];
|
||||
|
||||
switch( s->type )
|
||||
{
|
||||
case EOF:
|
||||
sprintf( buf, "EOF" );
|
||||
break;
|
||||
case 0:
|
||||
sprintf( buf, "unknown symbol %s", s->string );
|
||||
break;
|
||||
case ARG:
|
||||
sprintf( buf, "argument %s", s->string );
|
||||
break;
|
||||
case STRING:
|
||||
sprintf( buf, "string \"%s\"", s->string );
|
||||
break;
|
||||
default:
|
||||
sprintf( buf, "keyword %s", s->string );
|
||||
break;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
52
historic/jam/src/scan.h
Normal file
52
historic/jam/src/scan.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* scan.h - the jam yacc scanner
|
||||
*
|
||||
* External functions:
|
||||
*
|
||||
* yyerror( char *s ) - print a parsing error message
|
||||
* yyfparse( char *s ) - scan include file s
|
||||
* yylex() - parse the next token, returning its type
|
||||
* yymode() - adjust lexicon of scanner
|
||||
* yyparse() - declaration for yacc parser
|
||||
* yyanyerrors() - indicate if any parsing errors occured
|
||||
*
|
||||
* The yymode() function is for the parser to adjust the lexicon of the
|
||||
* scanner. Aside from normal keyword scanning, there is a mode to
|
||||
* handle action strings (look only for the closing }) and a mode to
|
||||
* ignore most keywords when looking for a punctuation keyword. This
|
||||
* allows non-punctuation keywords to be used in lists without quoting.
|
||||
*/
|
||||
|
||||
/*
|
||||
* YYSTYPE - value of a lexical token
|
||||
*/
|
||||
|
||||
# define YYSTYPE YYSYMBOL
|
||||
|
||||
typedef struct _YYSTYPE {
|
||||
int type;
|
||||
char *string;
|
||||
PARSE *parse;
|
||||
LIST *list;
|
||||
int number;
|
||||
} YYSTYPE;
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
void yymode( int n );
|
||||
void yyerror( char *s );
|
||||
int yyanyerrors();
|
||||
void yyfparse( char *s );
|
||||
int yyline();
|
||||
int yylex();
|
||||
int yyparse();
|
||||
|
||||
# define SCAN_NORMAL 0 /* normal parsing */
|
||||
# define SCAN_STRING 1 /* look only for matching } */
|
||||
# define SCAN_PUNCT 2 /* only punctuation keywords */
|
||||
144
historic/jam/src/search.c
Normal file
144
historic/jam/src/search.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "search.h"
|
||||
# include "timestamp.h"
|
||||
# include "filesys.h"
|
||||
# include "variable.h"
|
||||
# include "newstr.h"
|
||||
# include "compile.h"
|
||||
# include "strings.h"
|
||||
# include <string.h>
|
||||
|
||||
static void call_bind_rule(
|
||||
char* target_,
|
||||
char* boundname_ )
|
||||
{
|
||||
LIST* bind_rule = var_get( "BINDRULE" );
|
||||
if( bind_rule )
|
||||
{
|
||||
/* No guarantee that target is an allocated string, so be on the
|
||||
* safe side */
|
||||
char* target = copystr( target_ );
|
||||
|
||||
/* Likewise, don't rely on implementation details of newstr.c: allocate
|
||||
* a copy of boundname */
|
||||
char* boundname = copystr( boundname_ );
|
||||
if( boundname && target )
|
||||
{
|
||||
/* Prepare the argument list */
|
||||
FRAME frame[1];
|
||||
frame_init( frame );
|
||||
|
||||
/* First argument is the target name */
|
||||
lol_add( frame->args, list_new( L0, target ) );
|
||||
|
||||
lol_add( frame->args, list_new( L0, boundname ) );
|
||||
if( lol_get( frame->args, 1 ) )
|
||||
evaluate_rule( bind_rule->string, frame );
|
||||
|
||||
/* Clean up */
|
||||
frame_free( frame );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( boundname )
|
||||
freestr( boundname );
|
||||
if( target )
|
||||
freestr( target );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* search.c - find a target along $(SEARCH) or $(LOCATE)
|
||||
*/
|
||||
|
||||
char *
|
||||
search(
|
||||
char *target,
|
||||
time_t *time )
|
||||
{
|
||||
FILENAME f[1];
|
||||
LIST *varlist;
|
||||
string buf[1];
|
||||
int found = 0;
|
||||
char *boundname = 0;
|
||||
|
||||
string_new( buf );
|
||||
/* Parse the filename */
|
||||
|
||||
file_parse( target, f );
|
||||
|
||||
f->f_grist.ptr = 0;
|
||||
f->f_grist.len = 0;
|
||||
|
||||
if( varlist = var_get( "LOCATE" ) )
|
||||
{
|
||||
f->f_root.ptr = varlist->string;
|
||||
f->f_root.len = strlen( varlist->string );
|
||||
|
||||
file_build( f, buf, 1 );
|
||||
|
||||
if( DEBUG_SEARCH )
|
||||
printf( "locate %s: %s\n", target, buf->value );
|
||||
|
||||
timestamp( buf->value, time );
|
||||
found = 1;
|
||||
}
|
||||
else if( varlist = var_get( "SEARCH" ) )
|
||||
{
|
||||
while( varlist )
|
||||
{
|
||||
f->f_root.ptr = varlist->string;
|
||||
f->f_root.len = strlen( varlist->string );
|
||||
|
||||
string_truncate( buf, 0 );
|
||||
file_build( f, buf, 1 );
|
||||
|
||||
if( DEBUG_SEARCH )
|
||||
printf( "search %s: %s\n", target, buf->value );
|
||||
|
||||
timestamp( buf->value, time );
|
||||
|
||||
if( *time )
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
varlist = list_next( varlist );
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
/* Look for the obvious */
|
||||
/* This is a questionable move. Should we look in the */
|
||||
/* obvious place if SEARCH is set? */
|
||||
|
||||
f->f_root.ptr = 0;
|
||||
f->f_root.len = 0;
|
||||
|
||||
string_truncate( buf, 0 );
|
||||
file_build( f, buf, 1 );
|
||||
|
||||
if( DEBUG_SEARCH )
|
||||
printf( "search %s: %s\n", target, buf->value );
|
||||
|
||||
timestamp( buf->value, time );
|
||||
}
|
||||
|
||||
boundname = newstr( buf->value );
|
||||
string_free( buf );
|
||||
|
||||
/* prepare a call to BINDRULE if the variable is set */
|
||||
call_bind_rule( target, boundname );
|
||||
|
||||
return boundname;
|
||||
}
|
||||
11
historic/jam/src/search.h
Normal file
11
historic/jam/src/search.h
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* search.h - find a target along $(SEARCH) or $(LOCATE)
|
||||
*/
|
||||
|
||||
char *search( char *target, time_t *time );
|
||||
142
historic/jam/src/strings.c
Normal file
142
historic/jam/src/strings.c
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "strings.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void assert_invariants( string* self )
|
||||
{
|
||||
assert( self->size < self->capacity );
|
||||
assert( ( self->capacity <= sizeof(self->opt) ) == ( self->value == self->opt ) );
|
||||
assert( strlen( self->value ) == self->size );
|
||||
}
|
||||
#else
|
||||
# define assert_invariants(x) do {} while (0)
|
||||
#endif
|
||||
|
||||
void string_new( string* s )
|
||||
{
|
||||
s->value = s->opt;
|
||||
s->size = 0;
|
||||
s->capacity = sizeof(s->opt);
|
||||
s->opt[0] = 0;
|
||||
assert_invariants( s );
|
||||
}
|
||||
|
||||
void string_free( string* s )
|
||||
{
|
||||
assert_invariants( s );
|
||||
if ( s->value != s->opt )
|
||||
free( s->value );
|
||||
}
|
||||
|
||||
static void string_reserve_internal( string* self, size_t capacity )
|
||||
{
|
||||
if ( self->value == self->opt )
|
||||
{
|
||||
self->value = malloc( capacity );
|
||||
self->value[0] = 0;
|
||||
strcat( self->value, self->opt );
|
||||
}
|
||||
else
|
||||
{
|
||||
self->value = realloc( self->value, capacity );
|
||||
}
|
||||
self->capacity = capacity;
|
||||
}
|
||||
|
||||
void string_reserve( string* self, size_t capacity )
|
||||
{
|
||||
assert_invariants( self );
|
||||
if ( capacity <= self->capacity )
|
||||
return;
|
||||
string_reserve_internal( self, capacity );
|
||||
assert_invariants( self );
|
||||
}
|
||||
|
||||
static void extend_full( string* self, char* start, char *finish )
|
||||
{
|
||||
size_t new_size = self->capacity + ( finish - start );
|
||||
size_t new_capacity = self->capacity;
|
||||
size_t old_size = self->capacity;
|
||||
while ( new_capacity < new_size + 1)
|
||||
new_capacity <<= 1;
|
||||
string_reserve_internal( self, new_capacity );
|
||||
memcpy( self->value + old_size, start, new_size - old_size );
|
||||
self->value[new_size] = 0;
|
||||
self->size = new_size;
|
||||
}
|
||||
|
||||
void string_append( string* self, char* rhs )
|
||||
{
|
||||
char* p = self->value + self->size;
|
||||
char* end = self->value + self->capacity;
|
||||
assert_invariants( self );
|
||||
|
||||
while ( *rhs && p != end)
|
||||
*p++ = *rhs++;
|
||||
|
||||
if ( p != end )
|
||||
{
|
||||
*p = 0;
|
||||
self->size = p - self->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
extend_full( self, rhs, rhs + strlen(rhs) );
|
||||
}
|
||||
assert_invariants( self );
|
||||
}
|
||||
|
||||
void string_append_range( string* self, char* start, char* finish )
|
||||
{
|
||||
char* p = self->value + self->size;
|
||||
char* end = self->value + self->capacity;
|
||||
assert_invariants( self );
|
||||
|
||||
while ( p != end && start != finish )
|
||||
*p++ = *start++;
|
||||
|
||||
if ( p != end )
|
||||
{
|
||||
*p = 0;
|
||||
self->size = p - self->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
extend_full( self, start, finish );
|
||||
}
|
||||
assert_invariants( self );
|
||||
}
|
||||
|
||||
void string_copy( string* s, char* rhs )
|
||||
{
|
||||
string_new( s );
|
||||
string_append( s, rhs );
|
||||
}
|
||||
|
||||
void string_truncate( string* self, size_t n )
|
||||
{
|
||||
assert_invariants( self );
|
||||
assert( n <= self->capacity );
|
||||
self->value[self->size = n] = 0;
|
||||
assert_invariants( self );
|
||||
}
|
||||
|
||||
void string_pop_back( string* self )
|
||||
{
|
||||
string_truncate( self, self->size - 1 );
|
||||
}
|
||||
|
||||
void string_push_back( string* self, char x )
|
||||
{
|
||||
assert_invariants( self );
|
||||
string_append_range( self, &x, &x + 1 );
|
||||
assert_invariants( self );
|
||||
}
|
||||
|
||||
char string_back( string* self )
|
||||
{
|
||||
assert_invariants( self );
|
||||
return self->value[self->size - 1];
|
||||
}
|
||||
25
historic/jam/src/strings.h
Normal file
25
historic/jam/src/strings.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef STRINGS_DWA20011024_H
|
||||
# define STRINGS_DWA20011024_H
|
||||
|
||||
# include <stddef.h>
|
||||
|
||||
typedef struct string
|
||||
{
|
||||
char* value;
|
||||
unsigned long size;
|
||||
unsigned long capacity;
|
||||
char opt[32];
|
||||
} string;
|
||||
|
||||
void string_new( string* );
|
||||
void string_copy( string*, char* );
|
||||
void string_free( string* );
|
||||
void string_append( string*, char* );
|
||||
void string_append_range( string*, char*, char* );
|
||||
void string_push_back( string* s, char x );
|
||||
void string_reserve( string*, size_t );
|
||||
void string_truncate( string*, size_t );
|
||||
void string_pop_back( string* );
|
||||
char string_back( string* );
|
||||
|
||||
#endif // STRINGS_DWA20011024_H
|
||||
92
historic/jam/src/subst.c
Normal file
92
historic/jam/src/subst.c
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <stddef.h>
|
||||
#include "regexp.h"
|
||||
#include "hash.h"
|
||||
|
||||
#include "newstr.h"
|
||||
#include "lists.h"
|
||||
#include "parse.h"
|
||||
#include "compile.h"
|
||||
#include "frames.h"
|
||||
|
||||
struct regex_entry
|
||||
{
|
||||
const char* pattern;
|
||||
regexp* regex;
|
||||
};
|
||||
typedef struct regex_entry regex_entry;
|
||||
|
||||
static struct hash* regex_hash;
|
||||
|
||||
regexp* regex_compile( const char* pattern )
|
||||
{
|
||||
regex_entry entry, *e = &entry;
|
||||
entry.pattern = pattern;
|
||||
|
||||
if ( !regex_hash )
|
||||
regex_hash = hashinit(sizeof(regex_entry), "regex");
|
||||
|
||||
if ( hashenter( regex_hash, (HASHDATA **)&e ) )
|
||||
e->regex = regcomp( (char*)pattern );
|
||||
|
||||
return e->regex;
|
||||
}
|
||||
|
||||
LIST*
|
||||
builtin_subst(
|
||||
PARSE *parse,
|
||||
FRAME *frame )
|
||||
{
|
||||
LIST* result = L0;
|
||||
LIST* arg1 = lol_get( frame->args, 0 );
|
||||
|
||||
if ( arg1 && list_next(arg1) && list_next(list_next(arg1)) )
|
||||
{
|
||||
|
||||
const char* source = arg1->string;
|
||||
const char* pattern = list_next(arg1)->string;
|
||||
regexp* repat = regex_compile( pattern );
|
||||
|
||||
if ( regexec( repat, (char*)source) )
|
||||
{
|
||||
LIST* subst = list_next(arg1);
|
||||
|
||||
while ((subst = list_next(subst)) != L0)
|
||||
{
|
||||
# define BUFLEN 4096
|
||||
char buf[BUFLEN + 1];
|
||||
const char* in = subst->string;
|
||||
char* out = buf;
|
||||
|
||||
for ( in = subst->string; *in && out < buf + BUFLEN; ++in )
|
||||
{
|
||||
if ( *in == '\\' || *in == '$' )
|
||||
{
|
||||
++in;
|
||||
if ( *in == 0 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if ( *in >= '0' && *in <= '9' )
|
||||
{
|
||||
unsigned n = *in - '0';
|
||||
const size_t srclen = repat->endp[n] - repat->startp[n];
|
||||
const size_t remaining = buf + BUFLEN - out;
|
||||
const size_t len = srclen < remaining ? srclen : remaining;
|
||||
memcpy( out, repat->startp[n], len );
|
||||
out += len;
|
||||
continue;
|
||||
}
|
||||
/* fall through and copy the next character */
|
||||
}
|
||||
*out++ = *in;
|
||||
}
|
||||
*out = 0;
|
||||
|
||||
result = list_new( result, newstr( buf ) );
|
||||
#undef BUFLEN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
211
historic/jam/src/timestamp.c
Normal file
211
historic/jam/src/timestamp.c
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "hash.h"
|
||||
# include "filesys.h"
|
||||
# include "timestamp.h"
|
||||
# include "newstr.h"
|
||||
# include "strings.h"
|
||||
|
||||
/*
|
||||
* timestamp.c - get the timestamp of a file or archive member
|
||||
*
|
||||
* 09/22/00 (seiwald) - downshift names on OS2, too
|
||||
*/
|
||||
|
||||
/*
|
||||
* BINDING - all known files
|
||||
*/
|
||||
|
||||
typedef struct _binding BINDING;
|
||||
|
||||
struct _binding {
|
||||
char *name;
|
||||
short flags;
|
||||
|
||||
# define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
|
||||
|
||||
short progress;
|
||||
|
||||
# define BIND_INIT 0 /* never seen */
|
||||
# define BIND_NOENTRY 1 /* timestamp requested but file never found */
|
||||
# define BIND_SPOTTED 2 /* file found but not timed yet */
|
||||
# define BIND_MISSING 3 /* file found but can't get timestamp */
|
||||
# define BIND_FOUND 4 /* file found and time stamped */
|
||||
|
||||
time_t time; /* update time - 0 if not exist */
|
||||
} ;
|
||||
|
||||
static struct hash *bindhash = 0;
|
||||
static void time_enter( char *target, int found, time_t time );
|
||||
|
||||
static char *time_progress[] =
|
||||
{
|
||||
"INIT",
|
||||
"NOENTRY",
|
||||
"SPOTTED",
|
||||
"MISSING",
|
||||
"FOUND"
|
||||
} ;
|
||||
|
||||
|
||||
/*
|
||||
* timestamp() - return timestamp on a file, if present
|
||||
*/
|
||||
|
||||
void
|
||||
timestamp(
|
||||
char *target,
|
||||
time_t *time )
|
||||
{
|
||||
FILENAME f1, f2;
|
||||
BINDING binding, *b = &binding;
|
||||
string buf[1];
|
||||
|
||||
# ifdef DOWNSHIFT_PATHS
|
||||
string path;
|
||||
char *p;
|
||||
|
||||
string_copy( &path, target );
|
||||
p = path.value;
|
||||
|
||||
do
|
||||
*p = tolower( *p );
|
||||
while( *p++ );
|
||||
|
||||
target = path.value;
|
||||
# endif
|
||||
string_new( buf );
|
||||
|
||||
if( !bindhash )
|
||||
bindhash = hashinit( sizeof( BINDING ), "bindings" );
|
||||
|
||||
/* Quick path - is it there? */
|
||||
|
||||
b->name = target;
|
||||
b->time = b->flags = 0;
|
||||
b->progress = BIND_INIT;
|
||||
|
||||
if( hashenter( bindhash, (HASHDATA **)&b ) )
|
||||
b->name = newstr( target ); /* never freed */
|
||||
|
||||
if( b->progress != BIND_INIT )
|
||||
goto afterscanning;
|
||||
|
||||
b->progress = BIND_NOENTRY;
|
||||
|
||||
/* Not found - have to scan for it */
|
||||
|
||||
file_parse( target, &f1 );
|
||||
|
||||
/* Scan directory if not already done so */
|
||||
|
||||
{
|
||||
BINDING binding, *b = &binding;
|
||||
|
||||
f2 = f1;
|
||||
f2.f_grist.len = 0;
|
||||
file_parent( &f2 );
|
||||
file_build( &f2, buf, 0 );
|
||||
|
||||
b->name = buf->value;
|
||||
b->time = b->flags = 0;
|
||||
b->progress = BIND_INIT;
|
||||
|
||||
if( hashenter( bindhash, (HASHDATA **)&b ) )
|
||||
b->name = newstr( buf->value ); /* never freed */
|
||||
|
||||
if( !( b->flags & BIND_SCANNED ) )
|
||||
{
|
||||
file_dirscan( buf->value, time_enter );
|
||||
b->flags |= BIND_SCANNED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan archive if not already done so */
|
||||
|
||||
if( f1.f_member.len )
|
||||
{
|
||||
BINDING binding, *b = &binding;
|
||||
|
||||
f2 = f1;
|
||||
f2.f_grist.len = 0;
|
||||
f2.f_member.len = 0;
|
||||
string_truncate( buf, 0 );
|
||||
file_build( &f2, buf, 0 );
|
||||
|
||||
b->name = buf->value;
|
||||
b->time = b->flags = 0;
|
||||
b->progress = BIND_INIT;
|
||||
|
||||
if( hashenter( bindhash, (HASHDATA **)&b ) )
|
||||
b->name = newstr( buf->value ); /* never freed */
|
||||
|
||||
if( !( b->flags & BIND_SCANNED ) )
|
||||
{
|
||||
file_archscan( buf->value, time_enter );
|
||||
b->flags |= BIND_SCANNED;
|
||||
}
|
||||
}
|
||||
|
||||
afterscanning:
|
||||
|
||||
if( b->progress == BIND_SPOTTED )
|
||||
{
|
||||
if( file_time( b->name, &b->time ) < 0 )
|
||||
b->progress = BIND_MISSING;
|
||||
else
|
||||
b->progress = BIND_FOUND;
|
||||
}
|
||||
|
||||
*time = b->progress == BIND_FOUND ? b->time : 0;
|
||||
string_free( buf );
|
||||
# ifdef DOWNSHIFT_PATHS
|
||||
string_free( &path );
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
time_enter(
|
||||
char *target,
|
||||
int found,
|
||||
time_t time )
|
||||
{
|
||||
BINDING binding, *b = &binding;
|
||||
|
||||
# ifdef DOWNSHIFT_PATHS
|
||||
char path[ MAXJPATH ];
|
||||
char *p = path;
|
||||
|
||||
do *p++ = tolower( *target );
|
||||
while( *target++ );
|
||||
|
||||
target = path;
|
||||
# endif
|
||||
|
||||
b->name = target;
|
||||
b->flags = 0;
|
||||
|
||||
if( hashenter( bindhash, (HASHDATA **)&b ) )
|
||||
b->name = newstr( target ); /* never freed */
|
||||
|
||||
b->time = time;
|
||||
b->progress = found ? BIND_FOUND : BIND_SPOTTED;
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "time ( %s ) : %s\n", target, time_progress[b->progress] );
|
||||
}
|
||||
|
||||
/*
|
||||
* donestamps() - free timestamp tables
|
||||
*/
|
||||
|
||||
void
|
||||
donestamps()
|
||||
{
|
||||
hashdone( bindhash );
|
||||
}
|
||||
12
historic/jam/src/timestamp.h
Normal file
12
historic/jam/src/timestamp.h
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* timestamp.h - get the timestamp of a file or archive member
|
||||
*/
|
||||
|
||||
void timestamp( char *target, time_t *time );
|
||||
void donestamps();
|
||||
344
historic/jam/src/variable.c
Normal file
344
historic/jam/src/variable.c
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "variable.h"
|
||||
# include "expand.h"
|
||||
# include "hash.h"
|
||||
# include "filesys.h"
|
||||
# include "newstr.h"
|
||||
# include "strings.h"
|
||||
|
||||
/*
|
||||
* variable.c - handle jam multi-element variables
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* var_defines() - load a bunch of variable=value settings
|
||||
* var_string() - expand a string with variables in it
|
||||
* var_get() - get value of a user defined symbol
|
||||
* var_set() - set a variable in jam's user defined symbol table
|
||||
* var_swap() - swap a variable's value with the given one
|
||||
* var_done() - free variable tables
|
||||
*
|
||||
* Internal routines:
|
||||
*
|
||||
* var_enter() - make new var symbol table entry, returning var ptr
|
||||
* var_dump() - dump a variable to stdout
|
||||
*
|
||||
* 04/13/94 (seiwald) - added shorthand L0 for null list pointer
|
||||
* 08/23/94 (seiwald) - Support for '+=' (append to variable)
|
||||
* 01/22/95 (seiwald) - split environment variables at blanks or :'s
|
||||
* 05/10/95 (seiwald) - split path variables at SPLITPATH (not :)
|
||||
* 09/11/00 (seiwald) - defunct var_list() removed
|
||||
*/
|
||||
|
||||
static struct hash *varhash = 0;
|
||||
|
||||
/*
|
||||
* VARIABLE - a user defined multi-value variable
|
||||
*/
|
||||
|
||||
typedef struct _variable VARIABLE ;
|
||||
|
||||
struct _variable {
|
||||
char *symbol;
|
||||
LIST *value;
|
||||
} ;
|
||||
|
||||
static VARIABLE *var_enter( char *symbol );
|
||||
static void var_dump( char *symbol, LIST *value, char *what );
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* var_defines() - load a bunch of variable=value settings
|
||||
*
|
||||
* If variable name ends in PATH, split value at :'s.
|
||||
* Otherwise, split at blanks.
|
||||
*/
|
||||
|
||||
void
|
||||
var_defines( char **e )
|
||||
{
|
||||
string buf[1];
|
||||
|
||||
string_new( buf );
|
||||
|
||||
for( ; *e; e++ )
|
||||
{
|
||||
char *val;
|
||||
|
||||
/* Just say "no": windows defines this in the env, */
|
||||
/* but we don't want it to override our notion of OS. */
|
||||
|
||||
if( !strcmp( *e, "OS=Windows_NT" ) )
|
||||
continue;
|
||||
|
||||
# ifdef OS_MAC
|
||||
/* On the mac (MPW), the var=val is actually var\0val */
|
||||
/* Think different. */
|
||||
|
||||
if( ( val = strchr( *e, '=' ) ) || ( val = *e + strlen( *e ) ) )
|
||||
# else
|
||||
if( val = strchr( *e, '=' ) )
|
||||
# endif
|
||||
{
|
||||
LIST *l = L0;
|
||||
char *pp, *p;
|
||||
# ifdef OS_MAC
|
||||
char split = ',';
|
||||
# else
|
||||
char split = ' ';
|
||||
# endif
|
||||
/* Split *PATH at :'s, not spaces */
|
||||
|
||||
if( val - 4 >= *e )
|
||||
{
|
||||
if( !strncmp( val - 4, "PATH", 4 ) ||
|
||||
!strncmp( val - 4, "Path", 4 ) ||
|
||||
!strncmp( val - 4, "path", 4 ) )
|
||||
split = SPLITPATH;
|
||||
}
|
||||
|
||||
/* Do the split */
|
||||
|
||||
for( pp = val + 1; p = strchr( pp, split ); pp = p + 1 )
|
||||
{
|
||||
string_append_range( buf, pp, p );
|
||||
l = list_new( l, newstr( buf->value ) );
|
||||
string_truncate( buf, 0 );
|
||||
}
|
||||
|
||||
l = list_new( l, newstr( pp ) );
|
||||
|
||||
/* Get name */
|
||||
string_append_range( buf, *e, val );
|
||||
var_set( buf->value, l, VAR_SET );
|
||||
string_truncate( buf, 0 );
|
||||
}
|
||||
}
|
||||
string_free( buf );
|
||||
}
|
||||
|
||||
/*
|
||||
* var_string() - expand a string with variables in it
|
||||
*
|
||||
* Copies in to out; doesn't modify targets & sources.
|
||||
*/
|
||||
|
||||
int
|
||||
var_string(
|
||||
char *in,
|
||||
char *out,
|
||||
int outsize,
|
||||
LOL *lol )
|
||||
{
|
||||
char *out0 = out;
|
||||
char *oute = out + outsize - 1;
|
||||
|
||||
while( *in )
|
||||
{
|
||||
char *lastword;
|
||||
int dollar = 0;
|
||||
|
||||
/* Copy white space */
|
||||
|
||||
while( isspace( *in ) )
|
||||
{
|
||||
if( out >= oute )
|
||||
return -1;
|
||||
|
||||
*out++ = *in++;
|
||||
}
|
||||
|
||||
lastword = out;
|
||||
|
||||
/* Copy non-white space, watching for variables */
|
||||
|
||||
while( *in && !isspace( *in ) )
|
||||
{
|
||||
if( out >= oute )
|
||||
return -1;
|
||||
|
||||
if( in[0] == '$' && in[1] == '(' )
|
||||
dollar++;
|
||||
|
||||
*out++ = *in++;
|
||||
}
|
||||
|
||||
/* If a variable encountered, expand it and and embed the */
|
||||
/* space-separated members of the list in the output. */
|
||||
|
||||
if( dollar )
|
||||
{
|
||||
LIST *l;
|
||||
|
||||
l = var_expand( L0, lastword, out, lol, 0 );
|
||||
|
||||
out = lastword;
|
||||
|
||||
for( ; l; l = list_next( l ) )
|
||||
{
|
||||
int so = strlen( l->string );
|
||||
|
||||
if( out + so >= oute )
|
||||
return -1;
|
||||
|
||||
strcpy( out, l->string );
|
||||
out += so;
|
||||
*out++ = ' ';
|
||||
}
|
||||
|
||||
list_free( l );
|
||||
}
|
||||
}
|
||||
|
||||
if( out >= oute )
|
||||
return -1;
|
||||
|
||||
*out++ = '\0';
|
||||
|
||||
return out - out0;
|
||||
}
|
||||
|
||||
/*
|
||||
* var_get() - get value of a user defined symbol
|
||||
*
|
||||
* Returns NULL if symbol unset.
|
||||
*/
|
||||
|
||||
LIST *
|
||||
var_get( char *symbol )
|
||||
{
|
||||
VARIABLE var, *v = &var;
|
||||
|
||||
v->symbol = symbol;
|
||||
|
||||
if( varhash && hashcheck( varhash, (HASHDATA **)&v ) )
|
||||
{
|
||||
if( DEBUG_VARGET )
|
||||
var_dump( v->symbol, v->value, "get" );
|
||||
return v->value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* var_set() - set a variable in jam's user defined symbol table
|
||||
*
|
||||
* 'flag' controls the relationship between new and old values of
|
||||
* the variable: SET replaces the old with the new; APPEND appends
|
||||
* the new to the old; DEFAULT only uses the new if the variable
|
||||
* was previously unset.
|
||||
*
|
||||
* Copies symbol. Takes ownership of value.
|
||||
*/
|
||||
|
||||
void
|
||||
var_set(
|
||||
char *symbol,
|
||||
LIST *value,
|
||||
int flag )
|
||||
{
|
||||
VARIABLE *v = var_enter( symbol );
|
||||
|
||||
if( DEBUG_VARSET )
|
||||
var_dump( symbol, value, "set" );
|
||||
|
||||
switch( flag )
|
||||
{
|
||||
case VAR_SET:
|
||||
/* Replace value */
|
||||
list_free( v->value );
|
||||
v->value = value;
|
||||
break;
|
||||
|
||||
case VAR_APPEND:
|
||||
/* Append value */
|
||||
v->value = list_append( v->value, value );
|
||||
break;
|
||||
|
||||
case VAR_DEFAULT:
|
||||
/* Set only if unset */
|
||||
if( !v->value )
|
||||
v->value = value;
|
||||
else
|
||||
list_free( value );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* var_swap() - swap a variable's value with the given one
|
||||
*/
|
||||
|
||||
LIST *
|
||||
var_swap(
|
||||
char *symbol,
|
||||
LIST *value )
|
||||
{
|
||||
VARIABLE *v = var_enter( symbol );
|
||||
LIST *oldvalue = v->value;
|
||||
|
||||
if( DEBUG_VARSET )
|
||||
var_dump( symbol, value, "set" );
|
||||
|
||||
v->value = value;
|
||||
|
||||
return oldvalue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* var_enter() - make new var symbol table entry, returning var ptr
|
||||
*/
|
||||
|
||||
static VARIABLE *
|
||||
var_enter( char *symbol )
|
||||
{
|
||||
VARIABLE var, *v = &var;
|
||||
|
||||
if( !varhash )
|
||||
varhash = hashinit( sizeof( VARIABLE ), "variables" );
|
||||
|
||||
v->symbol = symbol;
|
||||
v->value = 0;
|
||||
|
||||
if( hashenter( varhash, (HASHDATA **)&v ) )
|
||||
v->symbol = newstr( symbol ); /* never freed */
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
* var_dump() - dump a variable to stdout
|
||||
*/
|
||||
|
||||
static void
|
||||
var_dump(
|
||||
char *symbol,
|
||||
LIST *value,
|
||||
char *what )
|
||||
{
|
||||
printf( "%s %s = ", what, symbol );
|
||||
list_print( value );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
* var_done() - free variable tables
|
||||
*/
|
||||
|
||||
void
|
||||
var_done()
|
||||
{
|
||||
hashdone( varhash );
|
||||
}
|
||||
25
historic/jam/src/variable.h
Normal file
25
historic/jam/src/variable.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 1993, 2000 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* variable.h - handle jam multi-element variables
|
||||
*/
|
||||
|
||||
void var_defines( char **e );
|
||||
int var_string( char *in, char *out, int outsize, LOL *lol );
|
||||
LIST * var_get( char *symbol );
|
||||
void var_set( char *symbol, LIST *value, int flag );
|
||||
LIST * var_swap( char *symbol, LIST *value );
|
||||
void var_done();
|
||||
|
||||
/*
|
||||
* Defines for var_set().
|
||||
*/
|
||||
|
||||
# define VAR_SET 0 /* override previous value */
|
||||
# define VAR_APPEND 1 /* append to previous value */
|
||||
# define VAR_DEFAULT 2 /* set only if no previous value */
|
||||
|
||||
89
historic/jam/src/yyacc
Normal file
89
historic/jam/src/yyacc
Normal file
@@ -0,0 +1,89 @@
|
||||
#!/bin/sh
|
||||
|
||||
# yyacc - yacc wrapper
|
||||
#
|
||||
# Allows tokens to be written as `literal` and then automatically
|
||||
# substituted with #defined tokens.
|
||||
#
|
||||
# Usage:
|
||||
# yyacc file.y filetab.h file.yy
|
||||
#
|
||||
# inputs:
|
||||
# file.yy yacc grammar with ` literals
|
||||
#
|
||||
# outputs:
|
||||
# file.y yacc grammar
|
||||
# filetab.h array of string <-> token mappings
|
||||
#
|
||||
# 3-13-93
|
||||
# Documented and p moved in sed command (for some reason,
|
||||
# s/x/y/p doesn't work).
|
||||
# 10-12-93
|
||||
# Take basename as second argument.
|
||||
# 12-31-96
|
||||
# reversed order of args to be compatible with GenFile rule
|
||||
|
||||
outy=${1?}
|
||||
outh=${2?}
|
||||
in=${3?}
|
||||
out=`basename $in .yy`
|
||||
|
||||
T=/tmp/yy$$
|
||||
trap 'rm -f $T.*' 0
|
||||
|
||||
sed '
|
||||
: 1
|
||||
/`/{
|
||||
h
|
||||
s/[^`]*`\([^`]*\)`.*/\1/
|
||||
p
|
||||
g
|
||||
s/[^`]*`[^`]*`//
|
||||
b 1
|
||||
}
|
||||
d
|
||||
' $in | sort -u | sed '
|
||||
h
|
||||
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
|
||||
s/:/_COLON/
|
||||
s/!/_BANG/
|
||||
s/&&/_AMPERAMPER/
|
||||
s/&/_AMPER/
|
||||
s/+/_PLUS/
|
||||
s/||/_BARBAR/
|
||||
s/|/_BAR/
|
||||
s/;/_SEMIC/
|
||||
s/-/_MINUS/
|
||||
s/</_LANGLE/
|
||||
s/>/_RANGLE/
|
||||
s/\./_PERIOD/
|
||||
s/?/_QUESTION/
|
||||
s/=/_EQUALS/
|
||||
s/,/_COMMA/
|
||||
s/\[/_LBRACKET/
|
||||
s/]/_RBRACKET/
|
||||
s/{/_LBRACE/
|
||||
s/}/_RBRACE/
|
||||
s/(/_LPAREN/
|
||||
s/)/_RPAREN/
|
||||
s/FILE/_FILE_/
|
||||
G
|
||||
s/\n/ /
|
||||
' > $T.1
|
||||
|
||||
sed '
|
||||
s:^\(.*\) \(.*\)$:s/`\2`/\1/g:
|
||||
s:\.:\\.:g
|
||||
s:\[:\\[:g
|
||||
' $T.1 > $T.s
|
||||
|
||||
rm -f $outy $outh
|
||||
|
||||
(
|
||||
sed 's:^\(.*\) \(.*\)$:%token \1:' $T.1
|
||||
sed -f $T.s $in
|
||||
) > $outy
|
||||
|
||||
(
|
||||
sed 's:^\(.*\) \(.*\)$: { "\2", \1 },:' $T.1
|
||||
) > $outh
|
||||
30
jam_src/Build.com
Executable file
30
jam_src/Build.com
Executable file
@@ -0,0 +1,30 @@
|
||||
! Bootstrap build script for Jam
|
||||
$ cc command.c
|
||||
$ cc compile.c
|
||||
$ cc expand.c
|
||||
$ cc execvms.c
|
||||
$ cc filevms.c
|
||||
$ cc glob.c
|
||||
$ cc hash.c
|
||||
$ cc headers.c
|
||||
$ cc jambase.c
|
||||
$ cc lists.c
|
||||
$ cc make.c
|
||||
$ cc make1.c
|
||||
$ cc newstr.c
|
||||
$ cc option.c
|
||||
$ cc parse.c
|
||||
$ cc pathvms.c
|
||||
$ cc regexp.c
|
||||
$ cc rules.c
|
||||
$ cc scan.c
|
||||
$ cc search.c
|
||||
$ cc timestamp.c
|
||||
$ cc variable.c
|
||||
$ cc jam.c
|
||||
$ cc jamgram.c
|
||||
$ link/exe=jam.exe command.obj, compile.obj, execvms.obj, expand.obj, -
|
||||
filevms.obj, glob.obj, hash.obj, headers.obj, lists.obj, make.obj, -
|
||||
make1.obj, newstr.obj, option.obj, parse.obj, pathvms.obj, regexp.obj, -
|
||||
rules.obj, scan.obj, search.obj, timestamp.obj, variable.obj, jam.obj, -
|
||||
jamgram.obj, jambase.obj
|
||||
47
jam_src/Build.mpw
Normal file
47
jam_src/Build.mpw
Normal file
@@ -0,0 +1,47 @@
|
||||
# This line must be set manually to the CodeWarrior Pro 5 installation.
|
||||
# Good luck!
|
||||
|
||||
set CW "malyn_apps:CodeWarrior Pro 5:MetroWerks CodeWarrior"
|
||||
|
||||
set -e MWCincludes "{CW}:MacOS Support:Universal:Interfaces:CIncludes,{CW}:MacOS Support:OpenTransport:Open Tpt Client Developer:Includes:CIncludes,{CW}:MacOS Support:Headers:Apple MPW,{CW}:MSL:MSL_C:MSL_Common:Include,{CW}:MSL:MSL_C++:MSL_Common:Include,{CW}:MSL:MSL_C:MSL_MacOS:Include"
|
||||
|
||||
mwcppc -o :bin.mac:command.o -nomapcr -w off command.c
|
||||
mwcppc -o :bin.mac:compile.o -nomapcr -w off compile.c
|
||||
mwcppc -o :bin.mac:execmac.o -nomapcr -w off execmac.c
|
||||
mwcppc -o :bin.mac:filemac.o -nomapcr -w off filemac.c
|
||||
mwcppc -o :bin.mac:pathmac.o -nomapcr -w off pathmac.c
|
||||
mwcppc -o :bin.mac:jamgram.o -nomapcr -w off jamgram.c
|
||||
mwcppc -o :bin.mac:expand.o -nomapcr -w off expand.c
|
||||
mwcppc -o :bin.mac:glob.o -nomapcr -w off glob.c
|
||||
mwcppc -o :bin.mac:hash.o -nomapcr -w off hash.c
|
||||
mwcppc -o :bin.mac:headers.o -nomapcr -w off headers.c
|
||||
mwcppc -o :bin.mac:lists.o -nomapcr -w off lists.c
|
||||
mwcppc -o :bin.mac:make.o -nomapcr -w off make.c
|
||||
mwcppc -o :bin.mac:make1.o -nomapcr -w off make1.c
|
||||
mwcppc -o :bin.mac:newstr.o -nomapcr -w off newstr.c
|
||||
mwcppc -o :bin.mac:option.o -nomapcr -w off option.c
|
||||
mwcppc -o :bin.mac:parse.o -nomapcr -w off parse.c
|
||||
mwcppc -o :bin.mac:regexp.o -nomapcr -w off regexp.c
|
||||
mwcppc -o :bin.mac:rules.o -nomapcr -w off rules.c
|
||||
mwcppc -o :bin.mac:scan.o -nomapcr -w off scan.c
|
||||
mwcppc -o :bin.mac:search.o -nomapcr -w off search.c
|
||||
mwcppc -o :bin.mac:timestamp.o -nomapcr -w off timestamp.c
|
||||
mwcppc -o :bin.mac:variable.o -nomapcr -w off variable.c
|
||||
|
||||
mwlinkppc -library -o :bin.mac:libjam.lib :bin.mac:command.o :bin.mac:compile.o :bin.mac:execmac.o :bin.mac:filemac.o :bin.mac:pathmac.o :bin.mac:jamgram.o :bin.mac:expand.o :bin.mac:glob.o :bin.mac:hash.o :bin.mac:headers.o :bin.mac:lists.o :bin.mac:make.o :bin.mac:make1.o :bin.mac:newstr.o :bin.mac:option.o :bin.mac:parse.o :bin.mac:regexp.o :bin.mac:rules.o :bin.mac:scan.o :bin.mac:search.o :bin.mac:timestamp.o :bin.mac:variable.o
|
||||
mwcppc -o :bin.mac:mkjambase.o -nomapcr -w off mkjambase.c
|
||||
|
||||
mwlinkppc -o :bin.mac:mkjambase -mpwtool -warn :bin.mac:mkjambase.o "{CW}:MacOS Support:Universal:Libraries:StubLibraries:Interfacelib" "{CW}:MacOS Support:Universal:Libraries:StubLibraries:ThreadsLib" "{CW}:MacOS Support:Universal:Libraries:StubLibraries:Mathlib" "{CW}:MacOS Support:Libraries:Apple MPW PPC:PPCToolLibs.o" "{CW}:MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib" "{CW}:MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib"
|
||||
mwcppc -o :bin.mac:jam.o -nomapcr -w off jam.c
|
||||
|
||||
:bin.mac:mkjambase jambase.c Jambase
|
||||
|
||||
mwcppc -o :bin.mac:jambase.o -nomapcr -w off jambase.c
|
||||
|
||||
mwlinkppc -o :bin.mac:jam -mpwtool -warn :bin.mac:jam.o :bin.mac:jambase.o :bin.mac:libjam.lib "{CW}:MacOS Support:Universal:Libraries:StubLibraries:Interfacelib" "{CW}:MacOS Support:Universal:Libraries:StubLibraries:ThreadsLib" "{CW}:MacOS Support:Universal:Libraries:StubLibraries:Mathlib" "{CW}:MacOS Support:Libraries:Apple MPW PPC:PPCToolLibs.o" "{CW}:MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib" "{CW}:MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
120
jam_src/INSTALL
Normal file
120
jam_src/INSTALL
Normal file
@@ -0,0 +1,120 @@
|
||||
I. Compiling FT Jam:
|
||||
--------------------
|
||||
|
||||
1. With a previous version of Jam:
|
||||
----------------------------------
|
||||
|
||||
The easiest way to compile Jam is to use a previous version of the
|
||||
program. If you already have one installed on your system, simply
|
||||
type "jam" in this directory.
|
||||
|
||||
This will create a new executable named "jam" or "jam.exe", located
|
||||
in a new system-dependent directory, whose name can be:
|
||||
|
||||
bin.ntx86\jam.exe
|
||||
bin.linux86\jam
|
||||
etc..
|
||||
|
||||
|
||||
2. Without jam:
|
||||
---------------
|
||||
|
||||
If you don't have a jam binary installed, you can still compile the
|
||||
program using one of these methods:
|
||||
|
||||
- on Unix systems, simply type "make" to use the "Makefile" provided
|
||||
in this directory. This should work flawlessly
|
||||
|
||||
- on other systems, you can also modify the content of "Makefile"
|
||||
to adapt it to your OS. Simply uncomment the lines specific to
|
||||
your system, and invoke your make tool
|
||||
|
||||
|
||||
Note that the Makefile is used to build a boot-strap version of jam,
|
||||
called "jam0". Once it is built, the "jam0" executable is called to
|
||||
re-build itself.
|
||||
|
||||
If this second pass doesn't work, this is probably because you didn't
|
||||
set some environment variable that indicates which compiler to use to
|
||||
Jam. Read the Jam documentation for more information on this..
|
||||
|
||||
|
||||
|
||||
3. With toolset-specific makefiles:
|
||||
-----------------------------------
|
||||
|
||||
You can also use one of the Makefiles located in the "builds"
|
||||
directory. Here's what you need to type on the command line,
|
||||
depending on your system and compiler:
|
||||
|
||||
|
||||
a. Windows + Visual C++:
|
||||
|
||||
set VISUALC=/install/path/to/visual/compiler
|
||||
set JAM_TOOLSET=VISUALC
|
||||
nmake -f builds\win32-visualc.mk
|
||||
|
||||
|
||||
b. Windows + Borland C++: (be sure to use the Borland "make" tool)
|
||||
|
||||
set BORLANDC=/install/path/to/borland/compiler
|
||||
set JAM_TOOLSET=BORLANDC
|
||||
make -fbuilds\win32-visualc.mk
|
||||
|
||||
|
||||
c. Windows + Mingw (gcc):
|
||||
|
||||
set BORLANDC=/install/path/to/borland/compiler
|
||||
set JAM_TOOLSET=BORLANDC
|
||||
make -f builds\win32-visualc.mk
|
||||
|
||||
|
||||
WE DO NOT PROVIDE PROJECT FILES FOR ANY SPECIFIC COMPILER/TOOLSET
|
||||
|
||||
|
||||
|
||||
|
||||
II. Installation:
|
||||
-----------------
|
||||
|
||||
For now, we do not provide any sophisticated
|
||||
installation pass. Simply copy the new jam executable
|
||||
to any directory in your current path.. and start
|
||||
using it !!
|
||||
|
||||
|
||||
III. Default files:
|
||||
-------------------
|
||||
|
||||
All default files for Jam are compiled within the
|
||||
executable itself.
|
||||
|
||||
There are no special configuration directory to
|
||||
place global or user preferences. Until further
|
||||
notice, all defaults can only be changed by using
|
||||
command line switches and setting environment
|
||||
variables..
|
||||
|
||||
|
||||
IV. Windows and OS/2 Binary packages:
|
||||
-------------------------------------
|
||||
|
||||
It's possible to create zip files of the binaries
|
||||
on Windows and OS/2 system by following these simple
|
||||
steps (you need to have the "zip" utility in your
|
||||
path !!):
|
||||
|
||||
1. build jam
|
||||
2. strip the jam.exe executable in bin.ntx86 when
|
||||
possible
|
||||
3. call "jam package"
|
||||
|
||||
you should see a file named "ftjam-xxxxx-win32.zip"
|
||||
or "ftjam-xxxxx-os2.zip" in the current directory,
|
||||
as well as "ftjam-xxxxx.zip" (containing the sources)
|
||||
|
||||
|
||||
Good luck,
|
||||
|
||||
|
||||
- David Turner, 28 Jul 2001
|
||||
1201
jam_src/Jam.html
Normal file
1201
jam_src/Jam.html
Normal file
File diff suppressed because it is too large
Load Diff
2288
jam_src/Jambase
Normal file
2288
jam_src/Jambase
Normal file
File diff suppressed because it is too large
Load Diff
881
jam_src/Jambase.html
Normal file
881
jam_src/Jambase.html
Normal file
@@ -0,0 +1,881 @@
|
||||
<HTML>
|
||||
<TITLE>
|
||||
Jambase Reference
|
||||
</TITLE>
|
||||
<BODY>
|
||||
<CENTER>
|
||||
<a href=http://www.perforce.com/jam/jam.html>
|
||||
Jam/MR
|
||||
</a>
|
||||
<H1>
|
||||
<A NAME="TOP">
|
||||
Jambase Reference
|
||||
</A>
|
||||
</H1>
|
||||
</CENTER>
|
||||
<P>
|
||||
Jambase is a base set of Jam/MR rules which
|
||||
provide roughly make(1)-like functionality for
|
||||
<a href="Jam.html"><b>jam</b></A>, the Jam/MR executable program.
|
||||
This document, which started out as the Jambase(5) man page,
|
||||
is a reference guide to the
|
||||
<A href="#RULES">rules</A>,
|
||||
<A href="#PSEUDOTARGETS">pseudotargets</A>,
|
||||
and <A href="#VARS">variables</A>
|
||||
defined in Jambase for use in Jamfiles.
|
||||
<P>
|
||||
For further information see:
|
||||
<UL>
|
||||
<LI>
|
||||
<a href="Jamfile.html">Using Jamfiles and Jambase</A>
|
||||
<LI>
|
||||
<a href="Jam.html">The Jam/MR Executable Program</A>
|
||||
</UL>
|
||||
<P>
|
||||
Jam/MR documentation and source are available from the
|
||||
<A HREF=http://public.perforce.com/public/index.html>Perforce Public Depot</a>.
|
||||
For detailed information about any of the rules summarized below,
|
||||
see the
|
||||
<A HREF=http://public.perforce.com/public/jam/src/Jambase>Jambase</a>
|
||||
file itself.
|
||||
<HR>
|
||||
<H2>
|
||||
<A NAME="RULES">
|
||||
Jambase Rules
|
||||
</A>
|
||||
</H2>
|
||||
<P>
|
||||
<B>As</B> <I>obj.o</I> : <I>source.s</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Assemble the file <I>source.s.</I> Called by the Object
|
||||
rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>Bulk</B> <I>directory</I> : <I>sources</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Copies <I>sources</I> into <I>directory.</I>
|
||||
</BLOCKQUOTE>
|
||||
<B>Cc</B> <I>object</I> : <I>source</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compile the file <I>source</I> into <I>object,</I> using the C
|
||||
compiler $(CC), its flags $(CCFLAGS) and $(OPTIM),
|
||||
and the header file directories $(HDRS). Called by
|
||||
the Object rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>C++</B> <I>obj.o</I> : <I>source.cc</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compile the C++ source file <I>source.cc.</I> Called by
|
||||
the Object rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>Chmod</B> <I>target</I> ;
|
||||
<BLOCKQUOTE>
|
||||
<I>(Unix and VMS only.)</I>
|
||||
Change file permissions on <I>target</I> to
|
||||
target-specific $(MODE) value set by Link, File,
|
||||
Install*, and Shell rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<B>Clean</B> <I>clean</I> : <I>targets</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Removes existing <I>targets</I> when <I>clean</I> is built.
|
||||
clean is not a dependency of all, and must be built
|
||||
explicitly for targets to be removed.
|
||||
</BLOCKQUOTE>
|
||||
<B>File</B> <I>target</I> : <I>source</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Copies <I>source</I> into <I>target.</I>
|
||||
</BLOCKQUOTE>
|
||||
<B>Fortran</B> <I>obj.o</I> : <I>source.f</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compile the Fortran source file <I>source.f.</I> Called
|
||||
by the Object rule.
|
||||
</BLOCKQUOTE>
|
||||
<P>
|
||||
<B>GenFile</B> <I>target</I> : <I>image</I> <I>sources</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Runs the command "<I>image</I> <I>target</I> <I>sources</I>"
|
||||
to create <I>target</I> from <I>sources</I> and
|
||||
<I>image</I>. (where <I>image</I> is an
|
||||
executable built by the Main rule.)
|
||||
</BLOCKQUOTE>
|
||||
<B>HardLink</B> <I>target</I> : <I>source</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Makes <I>target</I> a hard link to <I>source,</I> if it isn't one
|
||||
already. (Unix only.)
|
||||
</BLOCKQUOTE>
|
||||
<B>HdrRule</B> <I>source</I> : <I>headers</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Arranges the proper dependencies when the file
|
||||
<I>source</I> includes the files <I>headers</I> through the
|
||||
"#include" C preprocessor directive.
|
||||
<P>
|
||||
This rule is not intended to be called explicitly.
|
||||
It is called automatically during header scanning on
|
||||
sources handled by the Object rule (e.g., sources in
|
||||
Main or Library rules).
|
||||
</BLOCKQUOTE>
|
||||
<B>InstallBin</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Copy <I>sources</I> into <I>dir</I> with mode
|
||||
$(EXEMODE).
|
||||
</BLOCKQUOTE>
|
||||
<B>InstallLib</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Copy <I>sources</I> into <I>dir</I> with mode
|
||||
$(FILEMODE).
|
||||
</BLOCKQUOTE>
|
||||
<B>InstallMan</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Copy <I>sources</I> into the appropriate subdirectory
|
||||
of <I>dir</I> with mode $(FILEMODE). The subdirectory
|
||||
is man<I>s,</I> where <I>s</I> is the suffix of
|
||||
each of sources.
|
||||
</BLOCKQUOTE>
|
||||
<B>InstallShell</B> <I>dir</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Copy <I>sources</I> into <I>dir</I> with mode
|
||||
$(SHELLMODE).
|
||||
</BLOCKQUOTE>
|
||||
<B>Lex</B> <I>source.c</I> : <I>source.l</I> ; <BLOCKQUOTE>
|
||||
Process the lex(1) source file <I>source.l</I> and
|
||||
rename the lex.yy.c to <I>source.c.</I> Called by
|
||||
the Object rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>Library</B> <I>library</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Compiles <I>sources</I> and archives them into
|
||||
<I>library.</I> The intermediate <I>objects</I>
|
||||
are deleted. Calls Objects and LibraryFromObjects.
|
||||
<P>
|
||||
If Library is invoked with no suffix on <I>library</I>,
|
||||
the $(SUFLIB) suffix is used.
|
||||
</BLOCKQUOTE>
|
||||
<B>LibraryFromObjects</B> <I>library</I> : <I>objects</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Archives <I>objects</I> into <I>library.</I> The
|
||||
<I>objects</I> are then deleted.
|
||||
<P>
|
||||
If <I>library</I> has no suffix, the $(SUFLIB) suffix is used.
|
||||
</BLOCKQUOTE>
|
||||
<B>Link</B> <I>image</I> : <I>objects</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Links <I>image</I> from <I>objects</I> and sets
|
||||
permissions on <I>image</I> to $(EXEMODE).
|
||||
<I>Image</I> must be actual filename; suffix is not
|
||||
supplied.
|
||||
Called by Main.
|
||||
|
||||
</BLOCKQUOTE>
|
||||
<B>LinkLibraries</B> <I>image</I> : <I>libraries</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Makes <I>image</I> depend on <I>libraries</I> and
|
||||
includes them during the linking.
|
||||
<P>
|
||||
<I>Image</I> may be referenced without a suffix in this
|
||||
rule invocation; LinkLibraries supplies the suffix.
|
||||
</BLOCKQUOTE>
|
||||
<B>Main</B> <I>image</I> : <I>sources</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compiles <I>sources</I> and links them into <I>image.</I>
|
||||
Calls Objects and MainFromObjects.
|
||||
<P>
|
||||
<I>Image</I> may be referenced without a suffix in this
|
||||
rule invocation; Main supplies the suffix.
|
||||
</BLOCKQUOTE>
|
||||
<B>MainFromObjects</B> <I>image</I> : <I>objects</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Links <I>objects</I> into <I>image.</I> Dependency
|
||||
of exe. MainFromObjects supplies the suffix on <I>image</I>
|
||||
filename.
|
||||
</BLOCKQUOTE>
|
||||
<B>MakeLocate</B> <I>target</I> : <I>dir</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Creates <I>dir</I> and causes <I>target</I> to be built
|
||||
into <I>dir</I>.
|
||||
</BLOCKQUOTE>
|
||||
<B>MkDir</B> <I>dir</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Creates <I>dir</I> and its parent directories.
|
||||
</BLOCKQUOTE>
|
||||
<B>Object</B> <I>object</I> : <I>source</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Compiles a <I>single</I> source file source into
|
||||
<I>object.</I> The Main and Library rules use
|
||||
this rule to compile source files.
|
||||
<P>
|
||||
Causes <I>source</I> to be scanned for "#include"
|
||||
directives and calls HdrRule to make all included
|
||||
files dependedencies of <I>object</I>.
|
||||
<P>
|
||||
Calls one of the following rules to do the actual
|
||||
compiling, depending on the suffix of source:
|
||||
<PRE>
|
||||
*.c: Cc
|
||||
*.cc: C++
|
||||
*.cpp: C++
|
||||
*.C: C++
|
||||
*.l: Lex
|
||||
*.y: Yacc
|
||||
*.*: UserObject
|
||||
</PRE>
|
||||
</BLOCKQUOTE>
|
||||
<B>ObjectC++Flags</B> <I>source</I> : <I>flags</I> ;
|
||||
<BR>
|
||||
<B>ObjectCcFlags</B> <I>source</I> : <I>flags</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Add <I>flags</I> to the source-specific
|
||||
value of $(CCFLAGS) or $(C++FLAGS) when compiling <I>source.</I>
|
||||
Any file suffix on <I>source</I> is ignored.
|
||||
</BLOCKQUOTE>
|
||||
<B>ObjectHdrs</B> <I>source</I> : <I>dirs</I> ; <BLOCKQUOTE>
|
||||
Add <I>dirs</I> to the source-specific value of
|
||||
$(HDRS) when scanning and compiling <I>source.</I>
|
||||
Any file suffix on <I>source</I> is ignored.
|
||||
</BLOCKQUOTE>
|
||||
<B>Objects</B> <I>sources</I> ; <BLOCKQUOTE>
|
||||
For each source file in <I>sources,</I> calls
|
||||
Object to compile the source file into a similarly
|
||||
named object file.
|
||||
</BLOCKQUOTE>
|
||||
<B>RmTemps</B> <I>targets</I> : <I>sources</I> ; <BLOCKQUOTE>
|
||||
Marks <I>sources</I> as temporary with the TEMPORARY
|
||||
rule, and deletes <I>sources</I> once <I>targets</I>
|
||||
are built. Must be the last rule invoked on
|
||||
<I>targets.</I> Used internally by LibraryFromObjects rule.
|
||||
</BLOCKQUOTE>
|
||||
<B>Setuid</B> <I>images</I> ; <BLOCKQUOTE>
|
||||
Sets the setuid bit on each of <I>images</I> after
|
||||
linking. (Unix only.)
|
||||
|
||||
</BLOCKQUOTE>
|
||||
<B>SubDir</B> <I>VAR d1 ... dn</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Sets up housekeeping for the source files located
|
||||
in <I><CODE>$(VAR)/d1/.../dn</CODE></I>:
|
||||
<UL>
|
||||
<LI>Reads in rules file associated with <I>VAR</I>,
|
||||
if it hasn't already been read.
|
||||
<LI>Initializes variables for search paths,
|
||||
output directories, compiler
|
||||
flags, and grist, using <I>d1 ... dn</I> tokens.
|
||||
</UL>
|
||||
<P>
|
||||
<I>VAR</I> is the name of a variable;
|
||||
<I>d1</I> thru <I>dn</I> are elements
|
||||
of a directory path.
|
||||
</BLOCKQUOTE>
|
||||
<B>SubDirC++Flags</B> <I>flags</I> ;
|
||||
<BR>
|
||||
<B>SubDirCcFlags</B> <I>flags</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Adds <I>flags</I> to the compiler flags for source files
|
||||
in SubDir's directory.
|
||||
</BLOCKQUOTE>
|
||||
<B>SubDirHdrs</B> <I>paths</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Adds <I>paths</I> to the header search paths for source files
|
||||
in SubDir's directory.
|
||||
</BLOCKQUOTE>
|
||||
<B>SubInclude</B> <I>VAR d1 ... dn</I> ;
|
||||
<BLOCKQUOTE>
|
||||
Reads the Jamfile in <I><CODE>$(VAR)/d1/.../dn/</CODE></I>.
|
||||
</BLOCKQUOTE>
|
||||
<B>Shell</B> <I>image</I> : <I>source</I> ; <BLOCKQUOTE>
|
||||
Copies <I>source</I> into the executable sh(1)
|
||||
script <I>image.</I> Ensures that the first line of
|
||||
the script is $(SHELLHEADER) (default #!/bin/sh).
|
||||
</BLOCKQUOTE>
|
||||
<B>Undefines</B> <I>images</I> : <I>symbols</I> ; <BLOCKQUOTE>
|
||||
Adds flags to mark <I>symbols</I> as undefined
|
||||
on link command for <I>images</I>.
|
||||
<I>Images</I> may be referenced unsuffixed; the
|
||||
Undefines rule supplies the suffix.
|
||||
</BLOCKQUOTE>
|
||||
<B>UserObject</B> <I>object</I> : <I>source</I> ; <BLOCKQUOTE>
|
||||
This rule is called by Object for source
|
||||
files with unknown suffixes, and should be defined
|
||||
in Jamrules
|
||||
with a user-provided rule to handle the source file
|
||||
types not handled by the Object rule.
|
||||
The Jambase UserObject rule merely issues a
|
||||
complaint when it encounters <I>source</I> with
|
||||
files suffixes it does not recognize.
|
||||
</BLOCKQUOTE>
|
||||
<B>Yacc</B> <I>source.c</I> : <I>source.y</I> ; <BLOCKQUOTE>
|
||||
Process the yacc(1) file <I>source.y</I> and renamed
|
||||
the resulting y.tab.c and y.tab.h to <I>source.c.</I>
|
||||
Produces a y.tab.h and renames it to <I>source.h.</I>
|
||||
Called by the <B>Object</B> rule.
|
||||
</BLOCKQUOTE>
|
||||
<P>
|
||||
<HR>
|
||||
<A NAME="PSEUDOTARGETS">
|
||||
<H3>
|
||||
Jambase Pseudotargets
|
||||
</H3>
|
||||
</A>
|
||||
<P>
|
||||
There are two kinds of Jam targets: file targets and pseudotargets.
|
||||
File targets are objects that can be found in the filesystem.
|
||||
Pseudotargets are symbolic, and usually represent other targets.
|
||||
Most Jambase rules that define file targets also define pseudotargets
|
||||
which are dependent on types of file targets. The Jambase pseudotargets
|
||||
are:
|
||||
<CENTER>
|
||||
<TABLE CELLPADDING=5%>
|
||||
<TR><TD>exe
|
||||
<TD>Executables linked by the Main or MainFromObjects rules
|
||||
|
||||
<TR><TD>lib
|
||||
<TD>Libraries created by the Library or LibraryFromObjects rules
|
||||
|
||||
<TR><TD>obj
|
||||
<TD>Compiled objects used to create Main or Library targets
|
||||
|
||||
<TR><TD>dirs
|
||||
<TD>Directories where target files are written
|
||||
|
||||
<TR><TD>file
|
||||
<TD>Files copied by File and Bulk rules
|
||||
|
||||
<TR><TD>shell
|
||||
<TD>Files copied by Shell rule
|
||||
|
||||
<TR><TD>clean
|
||||
<TD>Removal of built targets (except files copied by Install* rules)
|
||||
|
||||
<TR><TD>install
|
||||
<TD>Files copied by Install* rules
|
||||
|
||||
<TR><TD>uninstall
|
||||
<TD>Removal of targets copied by Install* rules
|
||||
|
||||
</TABLE>
|
||||
</CENTER>
|
||||
<P>
|
||||
In addition, Jambase makes the <b>jam</b> default target "all"
|
||||
depend on "exe", "lib", "obj", "files", and "shell".
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
<A NAME="VARS">
|
||||
<H3>
|
||||
Jambase Variables
|
||||
</H3>
|
||||
</A>
|
||||
<P>
|
||||
Most of the following variables have default values for
|
||||
each platform; refer to the Jambase file to see what those
|
||||
defaults are.
|
||||
<P>
|
||||
ALL_LOCATE_TARGET
|
||||
<BLOCKQUOTE>
|
||||
Alternative location of built targets. By default,
|
||||
Jambase rules locate built targets in the source
|
||||
tree. By setting $(ALL_LOCATE_TARGET)
|
||||
in Jamrules, you can cause <b>jam</b>
|
||||
to write built targets to a location outside
|
||||
the source tree.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
AR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The archive command used to update Library
|
||||
and LibraryFromObjects targets.
|
||||
</BLOCKQUOTE>
|
||||
AS
|
||||
<BLOCKQUOTE>
|
||||
The assembler for As rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
ASFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Flags handed to the assembler for As.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
AWK
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The name of awk interpreter, used when copying a
|
||||
shell script for the Shell rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
BCCROOT
|
||||
<BLOCKQUOTE>
|
||||
Selects Borland compile and link actions on NT.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
BINDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Not longer used.
|
||||
(I.e., used only for backward compatibility with the
|
||||
obsolete INSTALLBIN rule.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CC
|
||||
|
||||
<BLOCKQUOTE>
|
||||
C compiler used for Cc rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CCFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Compile flags for Cc rule targets.
|
||||
The Cc rule sets target-specific $(CCFLAGS)
|
||||
values on its targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
C++
|
||||
|
||||
<BLOCKQUOTE>
|
||||
C++ compiler used for C++ rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
C++FLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Compile flags for C++ rule targets.
|
||||
The C++ rule sets target-specific $(C++FLAGS)
|
||||
values on its targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CHMOD
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Program (usually chmod(1)) used to set file
|
||||
permissions for Chmod rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CP
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The file copy program, used by File and Install* rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CRELIB
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, causes the Library rule to invoke the CreLib
|
||||
rule on the target library before attempting to archive
|
||||
any members, so that the library can be created if
|
||||
needed.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
CW
|
||||
|
||||
<BLOCKQUOTE>
|
||||
On Macintosh, the root of the Code Warrior Pro 5 directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
DOT
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The operating system-specific name for the current directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
DOTDOT
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The operating system-specific name for the parent directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
EXEMODE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Permissions for executables linked with Link, Main,
|
||||
and MainFromObjects, on platforms with a Chmod action.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
FILEMODE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Permissions for files copied by File or Bulk,
|
||||
on platforms with a Chmod action.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
FORTRAN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The Fortran compiler used by Fortran rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
FORTRANFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Fortran compiler flags for Fortran rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
GROUP
|
||||
|
||||
<BLOCKQUOTE>
|
||||
<I>(Unix only.)</I>
|
||||
The group owner for Install* rule targets.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRGRIST
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, used by the HdrRule to distinguish header files
|
||||
with the same name in diffrent directories.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRPATTERN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
A regular expression pattern that matches
|
||||
C preprocessor "#include" directives in source files
|
||||
and returns the name of the included file.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRRULE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Name of the rule to invoke with the results of header file
|
||||
scanning. Default is "HdrRule".
|
||||
<P>
|
||||
This is a jam-special variable. If both HDRRULE and HDRSCAN
|
||||
are set on a target,
|
||||
that target will be scanned for lines
|
||||
matching $(HDRSCAN), and $(HDDRULE) will be
|
||||
invoked on included files found in the matching $(HDRSCAN) lines.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Directories to be searched for header files.
|
||||
This is used by the Object rule to:
|
||||
<UL>
|
||||
<LI>set up search paths for finding files returned
|
||||
by header scans
|
||||
<LI>add -I flags on compile commands
|
||||
</UL>
|
||||
(See STDHDRS.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRSCAN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Regular expression pattern to use for header file
|
||||
scanning. The Object rule sets this to $(HDRPATTERN).
|
||||
This is a jam-special variable; see HDRRULE.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
HDRSEARCH
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Used by the HdrRule to fix the list of directories where
|
||||
header files can be found for a given source file.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
JAMFILE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Default is "Jamfile"; the name of the user-written
|
||||
rules file found in each source directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
JAMRULES
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Default is "Jamrules"; the name of a rule definition
|
||||
file to be read in at the first SubDir rule invocation.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
KEEPOBJS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, tells the LibraryFromObjects rule not to delete
|
||||
object files once they are archived.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LEX
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The lex(1) command and flags.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LIBDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Not longer used.
|
||||
(I.e., used only for backward compatibility with the
|
||||
obsolete INSTALLLIB rule.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LINK
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The linker. Defaults to $(CC).
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LINKFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Flags handed to the linker. Defaults to $(CCFLAGS).
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LINKLIBS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
List of external libraries to link with. The target image
|
||||
does not depend on these libraries.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The hard link command for HardLink rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LOCATE_SOURCE
|
||||
<BLOCKQUOTE>
|
||||
Used to set the location of generated source files.
|
||||
The Yacc, Lex, and GenFile rules set LOCATE on
|
||||
their targets to $(LOCATE_SOURCE).
|
||||
$(LOCATE_SOURCE) is initialized by the SubDir rule
|
||||
to the source directory itself.
|
||||
(Also, see ALL_LOCATE_TARGET.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
LOCATE_TARGET
|
||||
<BLOCKQUOTE>
|
||||
Used to set the location of built binary targets.
|
||||
The Object rule, and hence the Main and Library rules,
|
||||
set LOCATE on their targets to $(LOCATE_TARGET).
|
||||
$(LOCATE_TARGET) is initialized by the
|
||||
SubDir rule to the source directory itself.
|
||||
(See ALL_LOCATE_TARGET.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
MANDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Not longer used.
|
||||
(I.e., used only for backward compatibility with the
|
||||
obsolete INSTALLMAN rule.)
|
||||
</BLOCKQUOTE>
|
||||
|
||||
MKDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The 'create directory' command used for the MkDir
|
||||
rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
MODE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The target-specific file mode (permissions) for targets
|
||||
of the Shell, Setuid, Link, and Install* rules.
|
||||
Used by the Chmod action; hence relevant to NT and VMS
|
||||
only.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
MSVC
|
||||
<BLOCKQUOTE>
|
||||
Selects Microsoft Visual C 16-bit compile & link
|
||||
actions on NT.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
MSVCNT
|
||||
<BLOCKQUOTE>
|
||||
Selects Microsoft Visual C NT compile & link
|
||||
actions on NT.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
||||
MV
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The file rename command and options.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
NEEDLIBS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The list of libraries used when linking an executable.
|
||||
Used by the Link rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
NOARSCAN
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, indicates that library members' timestamps can't
|
||||
be found, and prevents the individual objects from being
|
||||
deleted, so that their timestamps can be used instead.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
NOARUPDATE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, indicates that libraries can't be updated, but only
|
||||
created whole.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
OPTIM
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The C compiler flag for optimization, used by Cc and C++
|
||||
rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
OSFULL
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The concatenation of $(OS)$(OSVER)$(OSPLAT), used when jam
|
||||
builds itself to determine the target binary directory.
|
||||
$(OS) and $(OSPLAT) are determined by jam at its compile
|
||||
time (in jam.h). $(OSVER) can optionally be set by the user.
|
||||
|
||||
</BLOCKQUOTE>
|
||||
|
||||
OWNER
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The owner of installed files. Used by Install* rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
RANLIB
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The name of the ranlib command. If set, causes
|
||||
the Ranlib action to be applied after the
|
||||
Archive action to targets of the Library rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
RELOCATE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If set, tells the Cc rule to move the output object
|
||||
file to its target directory because the cc command
|
||||
has a broken -o option.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
RM
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The command and options to remove a file.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SEARCH_SOURCE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The directory to find sources listed with Main,
|
||||
Library, Object, Bulk, File, Shell, InstallBin,
|
||||
InstallLib, and InstallMan rules. This works by
|
||||
setting the jam-special variable SEARCH to the
|
||||
value of $(SEARCH_SOURCE) for each of the rules'
|
||||
sources. The SubDir rule initializes SEARCH_SOURCE
|
||||
for each directory.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SHELLHEADER
|
||||
|
||||
<BLOCKQUOTE>
|
||||
A string inserted to the first line of every file
|
||||
created by the Shell rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SHELLMODE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Permissions for files installed by Shell rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SOURCE_GRIST
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Set by the SubDir to a value derived from the
|
||||
directory name, and used by Objects and related
|
||||
rules as 'grist' to perturb file names.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
STDHDRS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
Directories where headers can be found without
|
||||
resorting to using the flag to the C compiler.
|
||||
The $(STDHDRS) directories are used to find
|
||||
headers during scanning, but are not passed to the
|
||||
compiler commands as -I paths.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SUBDIR
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The path from the current directory to the directory
|
||||
last named by the SubDir rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
TOP
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The path from the current directory to the directory
|
||||
that has the Jamrules file. Used by the SubDir rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SUFEXE
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The suffix for executable files, if none provided.
|
||||
Used by the Main rule.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SUFLIB
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The suffix for libraries. Used by the Library and
|
||||
related rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
SUFOBJ
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The suffix for object files. Used by the Objects
|
||||
and related rules.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
UNDEFFLAG
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The flag prefixed to each symbol for the Undefines
|
||||
rule (i.e., the compiler flag for undefined symbols).
|
||||
</BLOCKQUOTE>
|
||||
|
||||
WATCOM
|
||||
<BLOCKQUOTE>
|
||||
Selects Watcom compile and link actions on OS2.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
YACC
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The yacc(1) command.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
YACCFILES
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The base filename generated by yacc(1).
|
||||
</BLOCKQUOTE>
|
||||
|
||||
YACCFLAGS
|
||||
|
||||
<BLOCKQUOTE>
|
||||
The yacc(1) command flags.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P>
|
||||
<HR>
|
||||
<A HREF="#TOP">Back to top.</A>
|
||||
<P>
|
||||
Copyright 1997, 2000 Perforce Software, Inc.
|
||||
<BR>
|
||||
Comments to <A HREF="mailto:info@perforce.com">info@perforce.com</A>
|
||||
<BR>
|
||||
Last updated: Dec 31, 2000
|
||||
<BR>
|
||||
$Id$
|
||||
</BODY>
|
||||
</HTML>
|
||||
227
jam_src/Jamfile
Normal file
227
jam_src/Jamfile
Normal file
@@ -0,0 +1,227 @@
|
||||
#
|
||||
# Jamfile to build Jam (a make(1)-like program)
|
||||
#
|
||||
# There are no user-serviceable parts in this file.
|
||||
#
|
||||
# Put executables in platform-specific subdirectory.
|
||||
|
||||
# compile without assertions by default
|
||||
CCFLAGS ?= -DNDEBUG ;
|
||||
|
||||
if $(VMS) { LOCATE_TARGET ?= [.binvms] ; }
|
||||
else if $(MAC) { LOCATE_TARGET ?= :bin.mac ; }
|
||||
else { LOCATE_TARGET ?= bin.$(OSFULL[1]:L) ; }
|
||||
|
||||
# Leave generated source in current directory; it would be nice to use
|
||||
# these lines below to build the source into the platform-specific
|
||||
# directory, but getting scan.c to include the right jambase.h is
|
||||
# hard: with ""'s, it always gets the bootstrap version; with <>'s,
|
||||
# it won't find the bootstrap version.
|
||||
|
||||
# SEARCH_SOURCE ?= $(LOCATE_TARGET) $(DOT) ;
|
||||
# LOCATE_SOURCE ?= $(LOCATE_TARGET) ;
|
||||
|
||||
#
|
||||
# We have some different files for UNIX, VMS, and NT.
|
||||
#
|
||||
|
||||
if $(NT) {
|
||||
code = execnt.c filent.c pathunix.c ;
|
||||
if $(OSTYPE) = cygwin
|
||||
{
|
||||
YACC ?= bison -t -d -l -v --yacc ;
|
||||
YACCFILES = y.tab ;
|
||||
}
|
||||
}
|
||||
else if $(OS2)
|
||||
{
|
||||
# special case for OS/2. When building Jam with GCC/EMX
|
||||
# we need to use the "fileunix.c" file
|
||||
#
|
||||
# when we build it with other toolsets, we use "fileos2.c"
|
||||
#
|
||||
code = execunix.c pathunix.c ;
|
||||
if $(TOOLSET) = EMX
|
||||
{
|
||||
CCFLAGS += -D__OS2__ ;
|
||||
code += fileunix.c ;
|
||||
}
|
||||
else
|
||||
{
|
||||
code += fileos2.c ;
|
||||
}
|
||||
}
|
||||
else if $(VMS) { code = execvms.c filevms.c pathvms.c ; }
|
||||
else if $(MAC) { code = execmac.c filemac.c pathmac.c ; }
|
||||
else { code = execunix.c fileunix.c pathunix.c ; }
|
||||
|
||||
# We have to signal jam.h for these
|
||||
|
||||
if $(OS) = NT
|
||||
{
|
||||
if $(TOOLSET) = MINGW || $(TOOLSET) = LCC
|
||||
{
|
||||
CCFLAGS += -DNT ;
|
||||
}
|
||||
else
|
||||
{
|
||||
CCFLAGS += /DNT ;
|
||||
}
|
||||
}
|
||||
|
||||
# Do we know yacc?
|
||||
|
||||
if $(YACC) { code += jamgram.y ; }
|
||||
else { code += jamgram.c ; }
|
||||
|
||||
#
|
||||
# Build the jamgram.y from the jamgram.yy
|
||||
# yyacc is a slippery script that makes grammars a little
|
||||
# easier to read/maintain.
|
||||
#
|
||||
|
||||
if ( $(UNIX) || $(NT) ) && $(YACC)
|
||||
{
|
||||
local SUFEXE = ; # yyacc is a script with no suffix - this handles cygwin
|
||||
GenFile jamgram.y jamgramtab.h : ./yyacc jamgram.yy ;
|
||||
}
|
||||
|
||||
#
|
||||
# How to build the compiled in jambase.
|
||||
#
|
||||
|
||||
Main mkjambase : mkjambase.c ;
|
||||
|
||||
#
|
||||
# The guts of the Jamfile: how to build Jam
|
||||
#
|
||||
|
||||
Main jam : jam.c jambase.c ;
|
||||
LinkLibraries jam : libjam.a ;
|
||||
GenFile jambase.c : mkjambase$(SUFEXE) Jambase ;
|
||||
|
||||
Library libjam.a :
|
||||
command.c compile.c $(code) expand.c glob.c
|
||||
hash.c headers.c hdrmacro.c lists.c make.c make1.c newstr.c
|
||||
option.c parse.c regexp.c rules.c scan.c search.c subst.c
|
||||
timestamp.c variable.c modules.c strings.c filesys.c ;
|
||||
|
||||
|
||||
if $(BINDIR) { InstallBin $(BINDIR) : jam ; }
|
||||
|
||||
#
|
||||
# Distribution making from here on out.
|
||||
#
|
||||
|
||||
ALLSOURCE =
|
||||
Build.com Build.mpw Jam.html Jambase Jambase.html Jamfile
|
||||
Jamfile.html Makefile Porting README RELNOTES command.c command.h
|
||||
compile.c compile.h execcmd.h execmac.c execunix.c execnt.c execvms.c
|
||||
expand.c expand.h filemac.c filent.c fileos2.c filesys.h fileunix.c
|
||||
filevms.c glob.c hash.c hash.h hdrmacro.c hdrmacro.h headers.c
|
||||
headers.h jam.c jam.h jambase.c jambase.h jamgram.c jamgram.h
|
||||
jamgram.y jamgram.yy jamgramtab.h lists.c lists.h make.c make.h
|
||||
make1.c mkjambase.c modules.c newstr.c newstr.h option.c option.h parse.c
|
||||
parse.h patchlevel.h pathmac.c pathunix.c pathvms.c regexp.c regexp.h
|
||||
rules.c rules.h scan.c scan.h search.c search.h strings.c subst.c timestamp.c
|
||||
timestamp.h variable.c variable.h filesys.c filesys.h yyacc
|
||||
INSTALL
|
||||
common.mk
|
||||
builds/win32-visualc.mk
|
||||
builds/win32-borlandc.mk
|
||||
builds/win32-gcc.mk
|
||||
;
|
||||
|
||||
|
||||
rule Binary
|
||||
{
|
||||
NotFile package ;
|
||||
Depends package : $(<) ;
|
||||
|
||||
DEPENDS $(<) : $(>) ;
|
||||
|
||||
switch $(<)
|
||||
{
|
||||
case *-win32.zip : Zip-Exe $(<) : $(>) ;
|
||||
case *-os2.zip : Zip-Exe $(<) : $(>) ;
|
||||
case *-linux-libc6.tar : GZip-Exe $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rule Package
|
||||
{
|
||||
NotFile package ;
|
||||
Depends package : $(<) ;
|
||||
|
||||
DEPENDS $(<) : $(>) ;
|
||||
|
||||
switch $(<)
|
||||
{
|
||||
case *.tar : { Tar-Gz $(<) : $(>) ; Tar-Bz2 $(<) : $(>) ; }
|
||||
case *.zip : Zip $(<) : $(>) ;
|
||||
}
|
||||
}
|
||||
|
||||
VERSION = ftjam-2.3.5 ;
|
||||
|
||||
|
||||
actions Tar-Gz
|
||||
{
|
||||
ln -s . $(VERSION)
|
||||
tar cvhf $(<) $(VERSION)/$(>)
|
||||
rm $(VERSION)
|
||||
gzip -9 $(<)
|
||||
}
|
||||
|
||||
actions Tar-Bz2
|
||||
{
|
||||
ln -s . $(VERSION)
|
||||
tar cvhf $(<) $(VERSION)/$(>)
|
||||
rm $(VERSION)
|
||||
bzip2 -9 $(<)
|
||||
}
|
||||
|
||||
|
||||
actions Zip
|
||||
{
|
||||
zip -9r $(<) $(>)
|
||||
}
|
||||
|
||||
actions Zip-Exe
|
||||
{
|
||||
zip -9j $(<) $(LOCATE_TARGET)\jam.exe
|
||||
}
|
||||
|
||||
actions GZip-Exe
|
||||
{
|
||||
ln -s $(LOCATE_TARGET)/jam jam
|
||||
strip jam
|
||||
tar chf $(<) jam
|
||||
rm -f jam
|
||||
gzip -9 $(<)
|
||||
}
|
||||
|
||||
|
||||
|
||||
if $(NT)
|
||||
{
|
||||
Binary $(VERSION)-win32.zip : $(ALLSOURCE) ;
|
||||
Package $(VERSION).zip : $(ALLSOURCE) ;
|
||||
}
|
||||
else if $(OS2)
|
||||
{
|
||||
Binary $(VERSION)-os2.zip : $(ALLSOURCE) ;
|
||||
Package $(VERSION).zip : $(ALLSOURCE) ;
|
||||
}
|
||||
else if $(OS) = LINUX
|
||||
{
|
||||
# how can we detect the C library version reliably ??
|
||||
# for now, this should only be used for convenience
|
||||
# purposes, until we add .rpm and .deb support in..
|
||||
|
||||
Binary $(VERSION)-linux-libc6.tar : jam ;
|
||||
|
||||
Package $(VERSION).tar : $(ALLSOURCE) ;
|
||||
Package $(VERSION).zip : $(ALLSOURCE) ;
|
||||
}
|
||||
1450
jam_src/Jamfile.html
Normal file
1450
jam_src/Jamfile.html
Normal file
File diff suppressed because it is too large
Load Diff
88
jam_src/Makefile
Normal file
88
jam_src/Makefile
Normal file
@@ -0,0 +1,88 @@
|
||||
# The following Makefile will build Jam on Unix systems
|
||||
# You can also modify it to compile the program on other
|
||||
# systems, or also use one of the specific Makefiles
|
||||
# located in the "builds" directory
|
||||
#
|
||||
|
||||
CC = cc
|
||||
TARGET = -o jam0
|
||||
CFLAGS =
|
||||
|
||||
# Borland C++ on Windows
|
||||
#CC = bcc32
|
||||
#TARGET = -ejam0
|
||||
#CFLAGS = /DNT -w- -q
|
||||
|
||||
# Special flavors - uncomment appropriate lines
|
||||
|
||||
# NCR seems to have a broken readdir() -- use gnu
|
||||
#CC = gcc
|
||||
|
||||
# AIX needs -lbsd, and has no identifying cpp symbol
|
||||
# Use _AIX41 if you're not on 3.2 anymore.
|
||||
#LINKLIBS = -lbsd
|
||||
#CFLAGS = -D_AIX
|
||||
|
||||
# NT (with Microsoft compiler)
|
||||
# Use FATFS if building on a DOS FAT file system
|
||||
#Lib = $(MSVCNT)/lib
|
||||
#Include = $(MSVCNT)/include
|
||||
#CC = cl /nologo
|
||||
#CFLAGS = -I $(Include) -DNT
|
||||
#TARGET = /Fejam0
|
||||
#LINKLIBS = $(Lib)/oldnames.lib $(Lib)/kernel32.lib $(Lib)/libc.lib
|
||||
|
||||
# BeOS - Metroworks CodeWarrior
|
||||
#CC = mwcc
|
||||
#Include = /NewDisk/develop/headers/posix
|
||||
#CFLAGS = -I $(Include)
|
||||
|
||||
# BeOS - gcc
|
||||
#CC = gcc
|
||||
#LINKLIBS = -lnet
|
||||
|
||||
# Interix - gcc
|
||||
#CC = gcc
|
||||
|
||||
# Cygwin - gcc & cygwin
|
||||
#CC = gcc
|
||||
#CFLAGS = -D__cygwin__
|
||||
|
||||
# MingW - gcc on Win32
|
||||
#
|
||||
#CC = gcc
|
||||
#CFLAGS = -DNT
|
||||
|
||||
# MPEIX
|
||||
#CC = gcc
|
||||
#CFLAGS = -I/usr/include -D_POSIX_SOURCE
|
||||
|
||||
# QNX rtp (neutrino)
|
||||
#CC = gcc
|
||||
|
||||
|
||||
#
|
||||
#SOURCES = \
|
||||
# command.c compile.c execnt.c execunix.c execvms.c expand.c \
|
||||
# filent.c fileos2.c fileunix.c filevms.c glob.c hash.c \
|
||||
# hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c \
|
||||
# newstr.c option.c parse.c pathunix.c pathvms.c regexp.c \
|
||||
# rules.c scan.c search.c subst.c timestamp.c variable.c
|
||||
|
||||
# for Unix systems
|
||||
#
|
||||
# we need to ensure that "jambase.c" has write permissions, since it is
|
||||
# going to be re-generated from "Jambase".
|
||||
#
|
||||
all: jam0
|
||||
chmod a+w jambase.c
|
||||
./jam0
|
||||
|
||||
# for other systems
|
||||
#all: jam0
|
||||
# jam0
|
||||
|
||||
include common.mk
|
||||
|
||||
#jam0:
|
||||
# $(CC) $(TARGET) $(CFLAGS) $(SOURCES) $(LINKLIBS)
|
||||
68
jam_src/Porting
Normal file
68
jam_src/Porting
Normal file
@@ -0,0 +1,68 @@
|
||||
Notes on porting Jam - revised 12/31/2000
|
||||
|
||||
1) Working out system dependencies in the Jam code.
|
||||
|
||||
Jam's OS footprint is fairly small. For OS independent work Jam
|
||||
liberally uses standard libc functions like stdio, malloc, and
|
||||
string. The OS dependent interfaces are:
|
||||
|
||||
From filesys.h:
|
||||
|
||||
file_parse() - split a file name into dir/base/suffix/member
|
||||
file_build() - build a filename given dir/base/suffix/member
|
||||
file_dirscan() - scan a directory for files
|
||||
file_archscan() - scan an archive for files
|
||||
file_time() - get the timestamp of a file, if not already
|
||||
done by file_dirscan().
|
||||
|
||||
From execcmd.h:
|
||||
|
||||
execcmd() - execute a shell script
|
||||
execwait() - wait for any outstanding execcmd()'s.
|
||||
|
||||
The current implementations are:
|
||||
|
||||
filemac.c - mac MPW
|
||||
filent.c - NT
|
||||
fileos2.c - OS/2
|
||||
fileunix.c - all UNIX
|
||||
filevms.c - VMS
|
||||
|
||||
execmac.c - mac MPW
|
||||
execunix.c - UNIX, OS/2, NT
|
||||
execvms.c - VMS
|
||||
|
||||
2) Defining OSMAJOR, OSMINOR in jam.h
|
||||
|
||||
So that the Jambase and Jamfile know their host, Jam defines $(OS)
|
||||
to be something useful for each platform. Make sure that there is
|
||||
code in jam.h to generate a useful value for $(OS), and key it off
|
||||
the platform specific C-preprocessor symbol. If the C-preprocessor
|
||||
doesn't itself defines such a symbol, add a define to the Makefile.
|
||||
|
||||
In addition to $(OS), you can also set $(OSPLAT) if the OS runs on
|
||||
multiple platforms (like Linux or NT).
|
||||
|
||||
3) Working out system dependencies in the Jambase
|
||||
|
||||
With the value of $(OS) available, the Jambase can be extended to
|
||||
support special variables or rules for new platforms. See the
|
||||
current support for VMS, NT, and Mac.
|
||||
|
||||
4) Yacc troubles
|
||||
|
||||
The generated files jamgram.h and jamgram.c are distributed for the
|
||||
poor souls without yacc.
|
||||
|
||||
5) Known problematic systems:
|
||||
|
||||
- Pyramid has no malloc.h, memory.h
|
||||
|
||||
- Encore has no stdlib.h
|
||||
|
||||
- Bull DPX has sys/file.h problems
|
||||
|
||||
6) Send the results back.
|
||||
|
||||
If you do porting work, the result can be integrated into future
|
||||
releases if you send it back to the author's address in the README.
|
||||
157
jam_src/README
Normal file
157
jam_src/README
Normal file
@@ -0,0 +1,157 @@
|
||||
This is the FreeType version of Jam. For more information, please see
|
||||
http://www.freetype.org/jam/index.html
|
||||
|
||||
The complete and detailed list of changes is available at:
|
||||
http://www.freetype.org/jam/changes.html
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Jam/MR (aka "jam - make(1) redux")
|
||||
|
||||
/+\
|
||||
+\ Copyright 1993, 2000 Christopher Seiwald.
|
||||
\+/
|
||||
|
||||
This is Release 2.3 of Jam/MR, a make-like program.
|
||||
|
||||
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.
|
||||
|
||||
FEATURES
|
||||
|
||||
-> Jam is a make(1) replacement that makes building simple things
|
||||
simple and building complicated things manageable.
|
||||
|
||||
-> Jam's language is expressive, making Jamfiles (c.f. Makefiles)
|
||||
compact. Here's a sample:
|
||||
|
||||
Main smail : main.c map.c resolve.c deliver.c
|
||||
misc.c parser.y alias.c pw.c headers.c
|
||||
scanner.l getpath.c str.c ;
|
||||
|
||||
This builds "smail" from a dozen source files. Jam handles
|
||||
header file dependencies automatically and on-the-fly.
|
||||
|
||||
-> Jam is very portable: it runs on UNIX, VMS, Mac, and NT.
|
||||
Most Jamfiles themselves are portable, like the sample above.
|
||||
|
||||
-> Jam is unintrusive: it is small, it has negligible CPU
|
||||
overhead, and it doesn't create any of its own funny files
|
||||
(c.f. Odin, nmake, SunOS make).
|
||||
|
||||
-> Jam can build large projects spread across many directories
|
||||
in one pass, without recursing, tracking the relationships
|
||||
among all files. Jam can do this with multiple, concurrent
|
||||
processes.
|
||||
|
||||
-> Jam isn't under the blinkin GNU copyright, so you can
|
||||
incorporate it into commercial products.
|
||||
|
||||
|
||||
INFORMATION GUIDE
|
||||
|
||||
Jam.html jam command usage
|
||||
|
||||
Jambase.html Reference for the Jambase boilerplate file.
|
||||
|
||||
Jamfile.html Easy reading on creating a Jamfile and using jam.
|
||||
|
||||
Jamlang.html The Jam language description.
|
||||
|
||||
RELNOTES Release 2.3 release notes.
|
||||
|
||||
Porting Notes on porting jam to wildcat platforms.
|
||||
|
||||
README This file. Includes installation instructions.
|
||||
|
||||
jam.c Contains the jam command's main() as well as an
|
||||
introduction to the code, for serious hackers.
|
||||
|
||||
|
||||
INSTALLING
|
||||
|
||||
The Makefile (UNIX, NT), build.com (VMS), Build.mpw (Mac MPW) are
|
||||
for bootstrapping. Once jam is built, it can rebuild itself.
|
||||
|
||||
UNIX
|
||||
|
||||
Build jam with make(1) on:
|
||||
|
||||
Platform $(OS)
|
||||
-------------------------
|
||||
AIX AIX *
|
||||
BSD/386 1.0 BSDI
|
||||
COHERENT/386 COHERENT
|
||||
DGUX 5.4 DGUX
|
||||
FreeBSD FREEBSD
|
||||
HPUX 9.0 HPUX
|
||||
IRIX 5.0 IRIX
|
||||
Linux LINUX
|
||||
NEXTSTEP 3.2 NEXT
|
||||
OSF/1 OSF
|
||||
PTX V2.1.0 PTX
|
||||
Solaris 2 SOLARIS *
|
||||
SunOS4.1 SUNOS
|
||||
Ultrix 4.2 ULTRIX
|
||||
BeOS BEOS *
|
||||
|
||||
* requires editing Makefile
|
||||
|
||||
Windows
|
||||
|
||||
Build jam with nmake on:
|
||||
|
||||
Platform $(OS)
|
||||
-------------------------
|
||||
NT NT *
|
||||
OS/2 OS2 *
|
||||
|
||||
The NT MAXLINE (command line length) is still set in jam.h to
|
||||
996, which was apparently the NT 3.5 limit. On 4.0, the limit
|
||||
is somewhere around 10K. For now, you can increase MAXLINE in
|
||||
jam.h so that a jam running on 4.0 will use the full command
|
||||
line length, but that jam.exe will fail miserably on the older OS.
|
||||
|
||||
On NT, a variable must be set before invoking jam to tell
|
||||
it where the C compiler lives. The name of this variable
|
||||
depends on which compiler you are using:
|
||||
|
||||
BCCROOT: The Borland C compiler
|
||||
MSVCNT: The Microsoft Compiler 5.0 (for NT)
|
||||
MSVC: The Microsoft Compiler 1.5 (for Windows)
|
||||
|
||||
Only MSVCNT has really been tested and is known to work.
|
||||
|
||||
Macintosh
|
||||
|
||||
Build jam with Build.mpw on:
|
||||
|
||||
Platform $(OS)
|
||||
-------------------------
|
||||
Macintosh MAC
|
||||
|
||||
You'll need to edit Build.mpw to set CW.
|
||||
|
||||
VMS
|
||||
|
||||
Build jam with @build.com on:
|
||||
|
||||
Platform $(OS)
|
||||
-------------------------
|
||||
VMS 5.4 VMS
|
||||
OPENVMS OPENVMS
|
||||
|
||||
Comments to the author!
|
||||
|
||||
November, 1993 - release 1.0
|
||||
March, 1995 - release 2.0
|
||||
February, 1996 - release 2.1
|
||||
November, 1997 - release 2.2
|
||||
December, 2000 - release 2.3
|
||||
|
||||
Christopher Seiwald
|
||||
|
||||
seiwald@perforce.com
|
||||
754
jam_src/RELNOTES
Normal file
754
jam_src/RELNOTES
Normal file
@@ -0,0 +1,754 @@
|
||||
Release notes for FTJam 2.3.5 (previous release was named "20010626")
|
||||
|
||||
0. Bugs fixed since 20010626:
|
||||
|
||||
DEBUG OUTPUT FORMATTING: indentation was "wrapped" when too many levels
|
||||
were reached, making debugging extremly difficult
|
||||
|
||||
1. Release info:
|
||||
|
||||
FTJam 2.3.5 (based on Jam 2.3.2)
|
||||
July 30, 2001
|
||||
VERSION 2.3.5
|
||||
PATCHLEVEL 3
|
||||
|
||||
2. Compatibility
|
||||
|
||||
FTJam 2.3.5 is upward compatible with Jam 2.3 and 2.2
|
||||
Only a few new builtin rules were added, and some small bugs fixed
|
||||
|
||||
3. Changes since 20010626:
|
||||
|
||||
Added a new builtin named FAIL_EXPECTED. It is used to invert the result
|
||||
of a given action. Used by the Boost.Build sub-system.
|
||||
|
||||
============================================================================
|
||||
============================================================================
|
||||
|
||||
|
||||
Release notes for Jam/MR 2.3
|
||||
(aka Jam - make(1) redux)
|
||||
|
||||
0. Bugs fixed since 2.3.1
|
||||
|
||||
PATCHLEVEL 2 - 3/12/2001
|
||||
|
||||
NOCARE changed back: it once again does not applies to targets
|
||||
with sources and/or actions. In 2.3 it was changed to apply to
|
||||
such targets, but that broke header file builds: files that are
|
||||
#included get marked with NOCARE, but if they have source or
|
||||
actions, they still should get built.
|
||||
|
||||
1. Release info:
|
||||
|
||||
Jam/MR 2.3
|
||||
November 16, 2000
|
||||
VERSION 2.3
|
||||
PATCHLEVEL 1
|
||||
|
||||
2. Compatibility
|
||||
|
||||
Jam 2.3 is upward compatible with Jam 2.2.
|
||||
|
||||
The Jam 2.3 language is a superset of the 2.2 language;
|
||||
Jamfiles, Jambase, and other rulesets used in 2.2 can be used
|
||||
with the 2.3 language support.
|
||||
|
||||
3. Changes since 2.2
|
||||
|
||||
3.1. Changes to Jam Language
|
||||
|
||||
Rules now can have values, which can expanded into a list with
|
||||
the new "[ rule args ... ]" syntax. A rule's value is the value
|
||||
of its last statement, though only the following statements have
|
||||
values: if (value of the leg chosen), switch (ditto), set (value
|
||||
of the resulting variable), return (its arguments). Note that
|
||||
'return' doesn't actually return. This support is EXPERIEMENTAL
|
||||
and otherwise undocumented. (2.3.1)
|
||||
|
||||
Because of the new way lists are processed, if a rule has no
|
||||
targets a warning message is no longer issued.
|
||||
|
||||
NOCARE now applies to targets with sources and/or actions,
|
||||
rather than just those without.
|
||||
|
||||
3.2. Jambase Changes
|
||||
|
||||
The HDRPATTERN variable now allows for leading blanks before
|
||||
the #include, to keep up with ANSI. By john@nanaon-sha.co.jp
|
||||
(John Belmonte) (2.2.3).
|
||||
|
||||
HDRPATTERN has been adjusted to avoid mistaking cases like:
|
||||
|
||||
# include <time.h> /* could be <sys/time.h> */
|
||||
|
||||
MkDir now NOUPDATE's $(DOT), so that there are no dependencies
|
||||
on the current directory's timestamp. By john@nanaon-sha.co.jp
|
||||
(John Belmonte).
|
||||
|
||||
The old mock functions like makeDirName, which assigned their
|
||||
results to the variable named as their first argument, have
|
||||
been replaced with real functions using the new [] synxtax.
|
||||
E.g. "makeDirName foo : bar ola" is now "foo = [ fDirName bar ]"
|
||||
|
||||
Install now always does a cp/chmod/etc, rather than using
|
||||
the system's install(1), which invariably seems broken.
|
||||
|
||||
3.3. Jam internal code changes
|
||||
|
||||
$JAMUNAME is set on UNIX. (2.2.4).
|
||||
|
||||
Jam ANSI-fied (2.3.0).
|
||||
|
||||
jam.h now defines a bunch of symbols used by the other source
|
||||
files, so as minimize compiler- and platform-specific ifdefs.
|
||||
|
||||
OSVER is no longer set by jam.h (it was only set for AIX).
|
||||
Jam does not depend on this variable at all, except to set
|
||||
$(OSFULL), which is used to determine jam's build directory.
|
||||
If the user needs to distinguish between various revs of
|
||||
OSs, he must set OSVER in the environment.
|
||||
|
||||
4. Fixed bugs
|
||||
|
||||
Redefining a rule while it was executing could cause jam to
|
||||
crash. Reference counts are now used to prevent that, thanks
|
||||
to Matt Armstrong.
|
||||
|
||||
Logic for computing chunk size when executing PIECEMEAL rules
|
||||
has been reworked to be a little more accurate, without danger
|
||||
of overflow, at the cost of being a little more compute intensive.
|
||||
Instead of computing an estimate chunksize in the (now gone)
|
||||
make1chunk(), make1cmds() now just goes full bore and tries to
|
||||
use all args. When that fails, it backs off by 10% of the source
|
||||
args until the command fits. It takes a little bit more compute
|
||||
time compared to the old logic, but when you're executing actions
|
||||
to build all of Shinola it's still pretty small in the scheme
|
||||
of things.
|
||||
|
||||
The NT handle leak in execunix.c has been fixed, thanks to
|
||||
Gurusamy Sarathy. (2.2.1).
|
||||
|
||||
5. Porting
|
||||
|
||||
Platforms newly supported or updated:
|
||||
|
||||
AmigaOS (with gcc), courtesy of Alain Penders (2.2.2).
|
||||
|
||||
Beos
|
||||
|
||||
CYGWIN 1.1.4, courtesy of John Belmonte <john@nanaon-sha.co.jp>.
|
||||
|
||||
IBM AS400 via Visual Age on NT (primitive)
|
||||
|
||||
IBM OS/390 Unix System Services
|
||||
|
||||
Linux SuSE on OS390
|
||||
|
||||
Linux Mips, ARM
|
||||
|
||||
Lynx
|
||||
|
||||
HPUX 11, IA64
|
||||
|
||||
Mac OS X Server, courtesy of Jeff_Sickel@sickel.com (2.2.5).
|
||||
|
||||
Mac Rhapsody
|
||||
|
||||
MPE IX 6.0
|
||||
|
||||
NetBSD
|
||||
|
||||
QNX RTP (QNX 6.0)
|
||||
|
||||
Siemens Sinix
|
||||
|
||||
UNICOS
|
||||
|
||||
VMS 6.2, 7.1
|
||||
|
||||
Windows NT IA64
|
||||
|
||||
5.1. NT Porting Notes
|
||||
|
||||
Always create tmp .bat file for actions if JAMSHELL is set.
|
||||
That way, if JAMSHELL is a .bat file itself, it can handle
|
||||
single-command actions with more than 9 cmd line args.
|
||||
|
||||
COMSPEC is no longer examined: cmd.exe is always used
|
||||
instead. Only cmd.exe can execute the Jambase rules anyhow.
|
||||
|
||||
Jam can be built with Borland C++ 5.5.
|
||||
|
||||
OS2 fixes: InstallBin now works. Filenames are now downshifted,
|
||||
so mixed case works better there, too. file_dirscan() can now scan
|
||||
the root ("c:\" or "\") directory, which it couldn't handle before.
|
||||
|
||||
var_defines now ignores OS=Windows_NT, because it conflicts
|
||||
with Jam's setting of OS (to NT).
|
||||
|
||||
5.2. Mac OS 8/9 Notes
|
||||
|
||||
The support for Mac is curious at best. It runs under MPW.
|
||||
|
||||
It requires CodeWarrior Pro 5, but no longer requires GUSI.
|
||||
|
||||
Use Build.mpw to bootstrap the build.
|
||||
|
||||
The Mac specific definitions in the Jambase are not intended
|
||||
to be of general purpose, but are sufficient to have Jam build
|
||||
itself.
|
||||
|
||||
===============================================================================
|
||||
===============================================================================
|
||||
|
||||
|
||||
Release Notes for Jam 2.2
|
||||
|
||||
1. Release info:
|
||||
|
||||
Jam 2.2
|
||||
October 22, 1997
|
||||
VERSION 2.2
|
||||
PATCHLEVEL 1
|
||||
|
||||
2. Compatibility
|
||||
|
||||
Jam 2.2 is a roll-up of 'Jam - make(1) redux' release 2.1+.
|
||||
Most of the changes described below were available before this,
|
||||
in the jam.2.1.plus.tar ball.
|
||||
|
||||
The Jam 2.2 language is a superset of the 2.1 language;
|
||||
Jamfiles, Jambase, and other rulesets used in 2.1 can be used
|
||||
with the 2.2 language support.
|
||||
|
||||
See 'Jambase Changes', below, to see if your Jamfiles need any
|
||||
changes to work with the 2.2 Jambase.
|
||||
|
||||
|
||||
3. Changes Since 2.1
|
||||
|
||||
New product name: Jam. (Executable program is still named 'jam'.)
|
||||
|
||||
Documentation rewritten; HTML versions supplied.
|
||||
|
||||
|
||||
3.1 Changes to Jam Language (See Jamlang.html)
|
||||
|
||||
Rules may now have more fields than just $(<) and $(>).
|
||||
|
||||
Local variables are now supported.
|
||||
|
||||
The expression 'if $(A) in $(B)' is now supported.
|
||||
|
||||
New variable modifiers :U and :L result in uppercased or lowercased
|
||||
values.
|
||||
|
||||
New variable modifier :P reliably results in parent directory
|
||||
of either a file or directory. (Previously, :D was used, but on VMS
|
||||
:D of a directory name is just the directory name.)
|
||||
|
||||
The :S variable modifier now results in the _last_ suffix if a
|
||||
filename has more than one dot (.) in it.
|
||||
|
||||
New predefined $(JAMDATE) variable is initialized at runtime for
|
||||
simple date stamping.
|
||||
|
||||
New predefined variables $(OSVER) and $(OSPLAT) are used to
|
||||
distinguish among operating system versions and hardware platforms,
|
||||
when possible.
|
||||
|
||||
New 'bind' qualifier on action definitions allows variables
|
||||
other than $(<) and $(>) to be bound with SEARCH and LOCATE paths.
|
||||
|
||||
Action buffer size is no longer limited by MAXCMD. Instead, each
|
||||
line in an action is limited by MAXLINE, defined for each OS, and
|
||||
the entire action size is limited by CMDBUF.
|
||||
|
||||
|
||||
3.2 Jambase Changes (See Jamfile.html)
|
||||
|
||||
Jambase has been reworked to incorporate new language features.
|
||||
|
||||
A handful of new utility rules has been added: makeString,
|
||||
makeDirName, etc.
|
||||
|
||||
New HDRGRIST variable in Jambase allows for headers with the same
|
||||
name to be distinguished.
|
||||
|
||||
LOCATE_TARGET now has a new flavor, LOCATE_SOURCE, that is used by
|
||||
rules that generate source files (e.g., Yacc and Lex).
|
||||
|
||||
Header file includes now happen in the proper order. The limit of
|
||||
10 include files has been eliminated.
|
||||
|
||||
The old "Install" rule is no longer available. Use InstallBin,
|
||||
InstallFile, InstallLib, InstallMan, or InstallShell instead.
|
||||
|
||||
|
||||
3.3 'jam' Changes (See Jam.html)
|
||||
|
||||
'jam' can now be built as a stand-alone program, with Jambase
|
||||
compiled into the executable. An external or alternate Jambase can
|
||||
still be referenced explicitly with -f.
|
||||
|
||||
On command failure, 'jam' now emits the text of the command that
|
||||
failed. This is a compromise between the normal -d1 behavior (where
|
||||
commands were never seen) and -d2 (where commands are always seen).
|
||||
|
||||
'jam' now exits non-zero if it doesn't have a total success. A parse
|
||||
error, sources that can't be found, and targets that can't be built
|
||||
all generate non-zero exit status.
|
||||
|
||||
The debugging levels (-d flags) have been slightly redefined.
|
||||
|
||||
The supplied Jamfile now builds 'jam' into a platform specific
|
||||
subdirectory. This lets you use the same source directory to
|
||||
build 'jam' for more than one platform.
|
||||
|
||||
The supplied Jamfile does not rebuild generated source files by
|
||||
default. (They are supplied with the distribution.) See Jamfile
|
||||
for more information.
|
||||
|
||||
|
||||
4. Fixed Bugs
|
||||
|
||||
The 'include' bug has finally been fixed, so that include
|
||||
statements take effect exactly when they are executed,
|
||||
rather than after the current statement block. This also
|
||||
corrects the problem where an 'include' within an 'if'
|
||||
block would wind up including the file one token after the
|
||||
'if' block's closing brace. Credit goes to Thomas Woods
|
||||
for suggesting that the parse tree generation and parse
|
||||
tree execution be paired in their own loop, rather than
|
||||
having the parser execute the tree directly.
|
||||
|
||||
The setting and extracting of grist has been regularized:
|
||||
normally, if you set a component of a filename (using the
|
||||
:DBSMG= modifiers), you are supposed to include the delimiters
|
||||
that set off the component: that is, you say "$(x:S=.suffix)",
|
||||
including the ".". But with grist it was inconsistent
|
||||
between setting and getting: setting grist required no
|
||||
<>'s, while getting grist included them. Getting grist
|
||||
continues to return the <>'s, but now setting grist can
|
||||
either include them (the new way) or not (the old way).
|
||||
|
||||
'actions together' now suppresses duplicate sources from
|
||||
showing up in $(>).
|
||||
|
||||
Accessing variables whose names contained ['s (as happens with
|
||||
MkDir on VMS) wasn't working, because it treated the [ as an
|
||||
array subscript. Now [ and ] are, like :, handled specially so
|
||||
that they can appear in variable values.
|
||||
|
||||
The 'if' statement now compares all elements in expressions;
|
||||
previously, it only compared the first element of each list.
|
||||
|
||||
If a command line in an action is longer than MAXLINE (formerly
|
||||
MAXCMD), 'jam' now issues an error and exits rather than dumping
|
||||
core.
|
||||
|
||||
If a Jamfile ended without a trailing newline, jam dumped core.
|
||||
This has been fixed.
|
||||
|
||||
|
||||
5. Porting
|
||||
|
||||
See jam.h for the definitive list of supported platforms.
|
||||
Since 2.1, support has been added for:
|
||||
|
||||
Macintosh MPW
|
||||
Alpha VMS
|
||||
Alpha NT
|
||||
NT PowerPC
|
||||
BeOS
|
||||
MVS OE
|
||||
UNIXWARE
|
||||
QNX
|
||||
SINIX (Nixdorf)
|
||||
OS/2
|
||||
Interactive UNIX (ISC), courtesy of Matthew Newhook
|
||||
|
||||
|
||||
5.1 NT Support Fixes
|
||||
|
||||
The NT command executor now handles multiple line actions, by writing
|
||||
multi-line actions to a batch file and executing that.
|
||||
|
||||
Targets are universally lowercased on NT. (Matthew Newhook)
|
||||
|
||||
Concurrent process support is fully enabled for NT.
|
||||
(Gurusamy Sarathy <gsar@engin.umich.edu>)
|
||||
|
||||
Path handling: Jam now knows that the directory component of "D:\"
|
||||
is "D:\", just as on unix it knows that the directory component of
|
||||
"/" is "/". It also now successfully gets the timestamp for "D:\"
|
||||
or just plain "\".
|
||||
|
||||
|
||||
5.2 VMS Support Fixes
|
||||
|
||||
VMS support is much, much better now. The path name manipulation
|
||||
routines (in pathvms.c) were more or less rewritten, and they now
|
||||
handle the vagaries of combining directory and file names properly.
|
||||
|
||||
Targets are universally lowercased on VMS.
|
||||
|
||||
Multi-line command blocks on VMS are now executed in a single system()
|
||||
call rather than separate ones for each line, so that actions can
|
||||
be DCL scripts.
|
||||
|
||||
===============================================================================
|
||||
===============================================================================
|
||||
|
||||
|
||||
Release notes for Jam 2.1.
|
||||
|
||||
1. Release info:
|
||||
Jam 2.1
|
||||
February 1, 1996
|
||||
VERSION 2.1
|
||||
PATCHLEVEL 0
|
||||
|
||||
2. Porting
|
||||
|
||||
Linux is now supported.
|
||||
|
||||
FREEBSD is now supported.
|
||||
|
||||
SCO ("M_XENIX") now supported.
|
||||
|
||||
NCR now supported.
|
||||
|
||||
NEXT support from karthy@dannug.dk (Karsten Thygesen)
|
||||
|
||||
DECC support from zinser@axp614.gsi.de (Martin P.J. Zinser)
|
||||
|
||||
I have changes for OS/2, but no way to test them. Volunteers?
|
||||
I have VMS multiprocess support, but no way to test it. Volunteers?
|
||||
|
||||
2.1. NT Support fixes.
|
||||
|
||||
The NT support is considerably more real than it was in 2.0.
|
||||
Filent.c had its syntax error corrected, it no longer skips the
|
||||
first entry when scanning directories, and it handles string
|
||||
tables in archives (for long object file names).
|
||||
|
||||
The Jambase was changed a bit to support the various C/C++
|
||||
compilers on NT, although it has only been thorougly tested
|
||||
with MSVC20.
|
||||
|
||||
You still need to set MSVCNT or BCCROOT to the root of the
|
||||
the compiler's directory tree, and you'll get an error if you
|
||||
don't set it (rather than getting a pile of mysterious errors).
|
||||
|
||||
2.2. Other porting fixes.
|
||||
|
||||
SPLITPATH now set up for UNIX (:), NT (;), VMS (,)
|
||||
|
||||
Jambase support for Solaris works better now: the location of
|
||||
AR is hardwired to /usr/ccs/bin/ar and it knowns "install"
|
||||
doesn't take -c. Solaris -- how the mighty have fallen.
|
||||
|
||||
To handle Linux's wacko yacc, jamgram.h is now included after
|
||||
scan.h so that YYSTYPE is define.
|
||||
|
||||
3. Jambase Changes (see Jamfile.html)
|
||||
|
||||
SubDir now computes the root directory for the source tree, if
|
||||
the variable naming the root directory isn't set in the environment.
|
||||
It counts the number of directory elements leading from the root
|
||||
to the current directory (as passed to SubDir) and uses that many
|
||||
"../"'s to identify the root. This means that to use SubDir you
|
||||
no longer have to have anything special set in the environment.
|
||||
|
||||
InstallFile is now an alias for InstallLib.
|
||||
|
||||
'first' is now dependency of all pseudo-targets (all, files,
|
||||
exe, lib, shell), so that jamming any of these pseudo-targets
|
||||
also builds any dependencies of 'first'.
|
||||
|
||||
The File rule definition in the Jambase was missing an &.
|
||||
|
||||
The File rule now calls the Clean rule, so that installed files
|
||||
get cleaned.
|
||||
|
||||
4. Jam changes (see Jam.html)
|
||||
|
||||
Variables may now be set on the command line with -svar=value.
|
||||
|
||||
Targets marked with NOUPDATE are now immune to the -a (anyhow)
|
||||
flag. Previously, the MkDir rule would try to recreate directories
|
||||
that already exist when jam was invoked with -a.
|
||||
|
||||
A new variable, $(JAMVERSION), joins the small list of built-in
|
||||
variables. It it set to the release of jam, currently "2.1".
|
||||
|
||||
If an actions fails, jam now deletes the target(s). It won't
|
||||
delete libraries or other targets that are composites. This is
|
||||
now consistent with jam's behavior on interrupts (it deletes the
|
||||
targets).
|
||||
|
||||
Jam had a nasty bug when setting multiple variables to the same
|
||||
value: if the first two variable names were the same, the variable
|
||||
value got trashed. This also affected "on target" variables if
|
||||
the first two targets were the same. For example:
|
||||
|
||||
FOO on bar.c bar.c foo.c = a b c ;
|
||||
|
||||
This would mangle the value of FOO for bar.c and foo.c. This has
|
||||
been fixed.
|
||||
|
||||
Jam would generate bogus numbers when reporting the number of
|
||||
targets updated after an interrupt. It now is more careful about
|
||||
counting.
|
||||
|
||||
The debugging flag -d has been extended. In addition to supporting
|
||||
-dx (turn on debugging for all levels up to x) there is also now
|
||||
-d+x (turn on debugging at only level x). The default output
|
||||
level is -d1 (-or d2 if -n is given); this can be turned off with
|
||||
-d0. The debug levels are listed in jam.1 and jam.h.
|
||||
|
||||
The parsing debug output now uses indenting to indicate when
|
||||
one rule invokes another.
|
||||
|
||||
===============================================================================
|
||||
===============================================================================
|
||||
|
||||
|
||||
Release notes for Jam 2.0.
|
||||
|
||||
1. Release info:
|
||||
Jam 2.0
|
||||
March 10, 1994
|
||||
VERSION 2.0
|
||||
PATCHLEVEL 5
|
||||
|
||||
2. Porting
|
||||
|
||||
Windows/NT is now (crudely) supported, courtesy of Brett Taylor
|
||||
and Laura Wingerd.
|
||||
|
||||
COHERENT/386 is now supported, courtesy of Fred Smith.
|
||||
|
||||
Solaris archive string table for long archive names is now
|
||||
supported, thanks to Mike Matrigali.
|
||||
|
||||
3. Compatibility
|
||||
|
||||
Jam 2.0 syntax is a superset of Jam 1.0 syntax, and thus it can
|
||||
interpret a Jam 1.0 Jambase.
|
||||
|
||||
The Jam 2.0 Jambase is a superset of the Jam 1.0 Jambase, and
|
||||
thus it can include a Jamfile written for Jam 1.0.
|
||||
|
||||
4. Changes from Jam 1.0 to Jam 2.0
|
||||
|
||||
4.1. Documentation changes
|
||||
|
||||
New Jamfile.5 manual page, with lots of examples and easy
|
||||
reading. It replaces both the old "Examples" file as well as
|
||||
the old Jambase.5 manual page.
|
||||
|
||||
jam.1 edited by Stephen W. Liddle and Diane Holt.
|
||||
|
||||
4.2. Jambase Changes (see Jamfile.5)
|
||||
|
||||
4.2.1. New rules:
|
||||
|
||||
There are new rules to make handling subdirectories easier:
|
||||
SubDir, SubInclude, SubDirCcFlags, SubDirHdrs.
|
||||
|
||||
There are new rules to handle file-specific CCFLAGS and HDRS:
|
||||
ObjectCcFlags and ObjectHdrs.
|
||||
|
||||
Misc new rules: HardLink, InstallShell, MkDir.
|
||||
|
||||
New rule "clean" that deletes exactly what jam has built, and
|
||||
"uninstall" that deletes exactly what was installed.
|
||||
|
||||
New rules for handling suffixes .s, .f, .cc, .cpp, .C.
|
||||
|
||||
4.2.2. Old rules:
|
||||
|
||||
The InstallBin, Lib, Man, and the new Shell rules now take the
|
||||
destination directory as the target and the files to be copied
|
||||
as sources. These rules formerly took the files to be copied
|
||||
as targets, and used built-in destination directories of
|
||||
$(BINDIR), $(LIBDIR), $(MANDIR), and $(BINDIR).
|
||||
|
||||
The InstallBin, Lib, Man, and Shell rules use the install(1)
|
||||
program now, instead of doing their own copying.
|
||||
|
||||
The Cc rule now uses -o when possible, rather than moving the
|
||||
result. Some platforms (Pyramid?) have a broken -o.
|
||||
|
||||
Jambase rules taking libraries, objects, and executables now
|
||||
all ignore the suffixes provided and use the one defined in the
|
||||
Jambase for the platform.
|
||||
|
||||
Stupid yyacc support moved out of Jambase, as jam is its only
|
||||
likely user.
|
||||
|
||||
Jambase now purturbs library sources with a "grist" of
|
||||
SOURCE_GRIST.
|
||||
|
||||
4.2.3. Misc:
|
||||
|
||||
The names of the default rules defined in Jambase have been
|
||||
lowercased and un-abbreviated, to be more imake(1) like.
|
||||
|
||||
The Jambase has been reorganized and sorted, with VMS and NT
|
||||
support moved in from their own files.
|
||||
|
||||
The Jambase has been relocated on UNIX from /usr/local/lib/jam
|
||||
to /usr/local/lib.
|
||||
|
||||
4.3. Jam changes (see jam.1)
|
||||
|
||||
4.3.1. Flags:
|
||||
|
||||
New -a (anyhow) flag: means build everything.
|
||||
|
||||
New -j<x> flag: run jobs in parallel.
|
||||
|
||||
Old -t now rebuilds the touched target, rather that just the
|
||||
target's parents.
|
||||
|
||||
-n now implies -d2, so that you see what's happening. The
|
||||
debug level can be subsequently overridden.
|
||||
|
||||
New -v to dump version.
|
||||
|
||||
4.3.2. Rules:
|
||||
|
||||
New ALWAYS rule behaves like -t: always builds target.
|
||||
|
||||
New EXIT rule makes it possible to raise a fatal error.
|
||||
|
||||
New LEAVES rule which say target depends only on the update
|
||||
times of the leaf sources.
|
||||
|
||||
New NOUPDATE rule says built targets only if they don't exist.
|
||||
|
||||
NOTIME has been renamed NOTFILE, to more accurately reflect its
|
||||
meaning (it says a target is not to be bound to a file).
|
||||
|
||||
4.3.3. Variables:
|
||||
|
||||
New special variable JAMSHELL: argv template for command execution
|
||||
shell.
|
||||
|
||||
Variables, both normal and target-specific, can have their
|
||||
value appended with the syntax "var += value" or "var on target
|
||||
+= value".
|
||||
|
||||
"?=" is now synonymous with "default =".
|
||||
|
||||
Imported enviroment variable values are now split at blanks
|
||||
(:'s if the variable name ends in PATH), so that they become
|
||||
proper list values.
|
||||
|
||||
4.3.4. Misc:
|
||||
|
||||
Files to be sourced with "include" are now bound first, so
|
||||
$(SEARCH) and $(LOCATE) affect them. They still can't be
|
||||
built, though.
|
||||
|
||||
New modifier on "actions": "existing" causes $(>) to expand
|
||||
only those files that currently exist.
|
||||
|
||||
4.3.5. Bug fixes:
|
||||
|
||||
When scanning tokens known to be argument lists (such as the
|
||||
arguments to rule invocations and variable assignment), the
|
||||
parser now tells the scanner to ignore alphabetic keywords, as
|
||||
all such lists terminate with punctuation keywords (like : or
|
||||
;). This way, alphabetic keywords don't need to be quoted when
|
||||
they appear as arguments.
|
||||
|
||||
The scanner has been fixed to handle oversized tokens,
|
||||
unterminated quotes, unterminated action blocks, and tokens
|
||||
abutting EOF (i.e. a token with no white space before EOF).
|
||||
|
||||
The progress report "...on xth target..." used to count all
|
||||
targets, rather than just those with updating actions. Since
|
||||
the original pronouncement of targets to be udpated included
|
||||
only those with updating actions, the progress report has been
|
||||
changed to match.
|
||||
|
||||
'If' conditionals now must be single arguments. Previously,
|
||||
they could be zero or more arguments, which didn't make much
|
||||
sense, and made things like 'foo == bar' true. The comparison
|
||||
operator is '=', and '==' just looked like the second of three
|
||||
arguments in the unary "non-empty argument list" conditional.
|
||||
|
||||
Header files indirectly including themselves were mistakenly
|
||||
reported as being dependent on themselves. Recursing through
|
||||
header file dependencies is now done after determining the fate
|
||||
of the target.
|
||||
|
||||
The variable expansion support was expanding $(X)$(UNDEF) as if
|
||||
it were $(X). It now expands to an empty list, like it
|
||||
should.
|
||||
|
||||
The UNIX version of file_build() didn't handle "dir/.suffix"
|
||||
right. Now it does.
|
||||
|
||||
The VMS command buffer was assumed to be as large as 1024 bytes,
|
||||
which isn't the case everywhere as it is related to some weird
|
||||
quota. It has been lowered to 256.
|
||||
|
||||
$(>) and $(<) wouldn't expand in action blocks if the targets
|
||||
were marked with NOTIME. Now they expand properly.
|
||||
|
||||
Malloc() return values are now checked.
|
||||
|
||||
The variable expansion routine var_expand() is now a little
|
||||
faster, by taking a few often needed shortcuts.
|
||||
|
||||
The VMS version of file_build() used the wrong length when
|
||||
re-rooting file names that already had directory compoents.
|
||||
This was fixed.
|
||||
|
||||
Various tracing adjustments were made.
|
||||
|
||||
5. Limitations/Known Bugs
|
||||
|
||||
The new Windows/NT support has only been marginally tested. It
|
||||
is dependent on certain variables being set depending on which
|
||||
compiler you are using. You'll need to look in the file
|
||||
Jambase and see what variables are expected to be set.
|
||||
|
||||
The VMS support has been tested, courtesy of the DEC guest
|
||||
machine, but has not been hammered fully in release 2.0. It
|
||||
was used quite a bit in Jam 1.0.
|
||||
|
||||
Jam clean when there is nothing to clean claims it is updating
|
||||
a target.
|
||||
|
||||
Because the include statement works by pushing a new file in
|
||||
the input stream of the scanner rather than recursively
|
||||
invoking the parser on the new file, multiple include
|
||||
statements in a rule's procedure causes the files to be
|
||||
included in reverse order.
|
||||
|
||||
If the include statement appears inside an if block, the
|
||||
parser's attempt to find the else will cause the text of the
|
||||
included file to appear after the first token following the
|
||||
statement block. This is rarely what is intended.
|
||||
|
||||
In a rule's actions, only $(<) and $(>) refer to the bound file
|
||||
names: all other variable references get the unbound names.
|
||||
This is a pain for $(NEEDLIBS), because it means that library
|
||||
path can't be bound using $(SEARCH) and $(LOCATE).
|
||||
|
||||
With the -j flag, errors from failed commands can get
|
||||
staggeringly mixed up. Also, because targets tend to get built
|
||||
in a quickest-first ordering, dependency information must be
|
||||
quite exact. Finally, beware of parallelizing commands that
|
||||
drop fixed-named files into the current directory, like yacc(1)
|
||||
does.
|
||||
|
||||
A poorly set $(JAMSHELL) is likely to result in silent
|
||||
failure.
|
||||
84
jam_src/command.c
Normal file
84
jam_src/command.c
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 1993, 1995 Christopher Seiwald.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/*
|
||||
* command.c - maintain lists of commands
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "variable.h"
|
||||
# include "rules.h"
|
||||
|
||||
# include "command.h"
|
||||
# include <limits.h>
|
||||
|
||||
/*
|
||||
* cmd_new() - return a new CMD or 0 if too many args
|
||||
*/
|
||||
|
||||
CMD *
|
||||
cmd_new(
|
||||
RULE *rule,
|
||||
LIST *targets,
|
||||
LIST *sources,
|
||||
LIST *shell )
|
||||
{
|
||||
CMD *cmd = (CMD *)malloc( sizeof( CMD ) );
|
||||
/* lift line-length limitation entirely when JAMSHELL is just "%" */
|
||||
int expand_line = ( shell && !strcmp(shell->string,"%") && !list_next(shell) );
|
||||
int max_line = MAXLINE;
|
||||
int allocated = -1;
|
||||
|
||||
cmd->rule = rule;
|
||||
cmd->shell = shell;
|
||||
cmd->next = 0;
|
||||
|
||||
lol_init( &cmd->args );
|
||||
lol_add( &cmd->args, targets );
|
||||
lol_add( &cmd->args, sources );
|
||||
cmd->buf = 0;
|
||||
|
||||
do
|
||||
{
|
||||
free(cmd->buf); /* free any buffer from previous iteration */
|
||||
|
||||
cmd->buf = (char*)malloc(max_line + 1);
|
||||
|
||||
if (cmd->buf == 0)
|
||||
break;
|
||||
|
||||
allocated = var_string( rule->actions->command, cmd->buf, max_line, &cmd->args );
|
||||
|
||||
max_line = max_line * 2;
|
||||
}
|
||||
while( expand_line && allocated < 0 && max_line < INT_MAX / 2 );
|
||||
|
||||
/* Bail if the result won't fit in MAXLINE */
|
||||
/* We don't free targets/sources/shell if bailing. */
|
||||
if( allocated < 0 )
|
||||
{
|
||||
cmd_free( cmd );
|
||||
cmd = 0;
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* cmd_free() - free a CMD
|
||||
*/
|
||||
|
||||
void
|
||||
cmd_free( CMD *cmd )
|
||||
{
|
||||
lol_free( &cmd->args );
|
||||
list_free( cmd->shell );
|
||||
free( cmd->buf );
|
||||
free( (char *)cmd );
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user