2
0
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:
Dave Abrahams
2001-11-06 15:36:16 +00:00
parent 34b817bf52
commit 49ba2cf8dd
174 changed files with 47522 additions and 0 deletions

30
historic/jam/src/Build.com Executable file
View 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

View 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
View 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

File diff suppressed because it is too large Load Diff

2288
historic/jam/src/Jambase Normal file

File diff suppressed because it is too large Load Diff

View 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
View 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) ;
}

File diff suppressed because it is too large Load Diff

88
historic/jam/src/Makefile Normal file
View 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
View 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
View 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
View 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.

View 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 );
}

View 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)

View 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

File diff suppressed because it is too large Load Diff

View 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
View 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 %*

View 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"

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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__ */

View 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, '>' );
}
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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;
}

View 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
View 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 );
}

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

View 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
View 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
View 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; }
;

View 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
View 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
View 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
View 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
View 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
View 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 );
}

View 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" %*

View 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" %*

View 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"

View 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;
}

View 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 );
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

31
historic/jam/src/regexp.h Normal file
View 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
View 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 = &target;
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
View 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
View 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
View 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
View 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
View 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
View 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];
}

View 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
View 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;
}

View 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 );
}

View 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
View 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 );
}

View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

2288
jam_src/Jambase Normal file

File diff suppressed because it is too large Load Diff

881
jam_src/Jambase.html Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

88
jam_src/Makefile Normal file
View 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
View 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
View 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
View 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
View 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