mirror of
https://github.com/boostorg/build.git
synced 2026-02-15 00:52:16 +00:00
Merge Boost Jam 3.1.17 release to Boost release.
[SVN r50535]
This commit is contained in:
@@ -18,9 +18,10 @@ if $(NT)
|
||||
}
|
||||
SLASH ?= / ;
|
||||
|
||||
# Glob for patterns in the directories starting from the given
|
||||
# start directory, up to and including the root of the file-system.
|
||||
# We stop globbing as soon as we find at least one match.
|
||||
|
||||
# Glob for patterns in the directories starting from the given start directory,
|
||||
# up to and including the root of the file-system. We stop globbing as soon as
|
||||
# we find at least one match.
|
||||
#
|
||||
rule find-to-root ( dir : patterns + )
|
||||
{
|
||||
@@ -33,6 +34,7 @@ rule find-to-root ( dir : patterns + )
|
||||
return $(globs) ;
|
||||
}
|
||||
|
||||
|
||||
# This global will hold the location of the user's boost-build.jam file.
|
||||
.boost-build-file = ;
|
||||
|
||||
@@ -42,16 +44,16 @@ rule find-to-root ( dir : patterns + )
|
||||
# Remember the value of $(BOOST_BUILD_PATH) supplied to us by the user.
|
||||
BOOST_BUILD_PATH.user-value = $(BOOST_BUILD_PATH) ;
|
||||
|
||||
# On Unix only, when BOOST_BUILD_PATH is not supplied by user, put
|
||||
# sensible default value. This allowes Boost.Build to work without
|
||||
# any environment variables, which is good in itself and also
|
||||
# required by Debian Policy.
|
||||
# On Unix only, when BOOST_BUILD_PATH is not supplied by the user, set it to a
|
||||
# sensible default value. This allows Boost.Build to work without any
|
||||
# environment variables, which is good in itself and also required by the Debian
|
||||
# Policy.
|
||||
if ! $(BOOST_BUILD_PATH) && $(UNIX)
|
||||
{
|
||||
BOOST_BUILD_PATH = /usr/share/boost-build ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
rule _poke ( module-name ? : variables + : value * )
|
||||
{
|
||||
module $(<)
|
||||
@@ -60,41 +62,37 @@ rule _poke ( module-name ? : variables + : value * )
|
||||
}
|
||||
}
|
||||
|
||||
# This rule can be invoked from an optional user's boost-build.jam
|
||||
# file to both indicate where to find the build system files, and to
|
||||
# load them. The path indicated is relative to the location of the
|
||||
# boost-build.jam file.
|
||||
|
||||
# This rule can be invoked from an optional user's boost-build.jam file to both
|
||||
# indicate where to find the build system files, and to load them. The path
|
||||
# indicated is relative to the location of the boost-build.jam file.
|
||||
#
|
||||
rule boost-build ( dir ? )
|
||||
{
|
||||
if $(.bootstrap-file)
|
||||
{
|
||||
EXIT "Error: Illegal attempt to re-bootstrap the build system by invoking" ;
|
||||
ECHO "Error: Illegal attempt to re-bootstrap the build system by invoking" ;
|
||||
ECHO ;
|
||||
ECHO " 'boost-build" $(dir) ";'" ;
|
||||
ECHO ;
|
||||
EXIT "Please consult the documentation at 'http://www.boost.org'." ;
|
||||
}
|
||||
|
||||
# Add the given directory to the path so we can find the build
|
||||
# system. If dir is empty, has no effect.
|
||||
#
|
||||
|
||||
# Add the given directory to the path so we can find the build system. If
|
||||
# dir is empty, has no effect.
|
||||
BOOST_BUILD_PATH = $(dir:R=$(.boost-build-file:D)) $(BOOST_BUILD_PATH) ;
|
||||
|
||||
# We might have just modified the *global* value of BOOST_BUILD_PATH.
|
||||
# The code that loads the rest of Boost.Build, in particular the
|
||||
# site-config.jam and user-config.jam files uses os.environ, so we need to
|
||||
# update the value there.
|
||||
|
||||
# We might have just modified the *global* value of BOOST_BUILD_PATH. The
|
||||
# code that loads the rest of Boost.Build, in particular the site-config.jam
|
||||
# and user-config.jam configuration files uses os.environ, so we need to
|
||||
# update the value there.
|
||||
_poke .ENVIRON : BOOST_BUILD_PATH : $(BOOST_BUILD_PATH) ;
|
||||
|
||||
|
||||
# Try to find the build system bootstrap file 'bootstrap.jam'.
|
||||
#
|
||||
local bootstrap-file =
|
||||
[ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;
|
||||
local bootstrap-file = [ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;
|
||||
.bootstrap-file = $(bootstrap-file[1]) ;
|
||||
|
||||
# There is no boost-build.jam we can find, exit with an error
|
||||
#
|
||||
|
||||
# There is no bootstrap.jam we can find, exit with an error.
|
||||
if ! $(.bootstrap-file)
|
||||
{
|
||||
ECHO "Unable to load Boost.Build: could not find build system." ;
|
||||
@@ -108,44 +106,43 @@ rule boost-build ( dir ? )
|
||||
ECHO ;
|
||||
EXIT "Please consult the documentation at 'http://www.boost.org'." ;
|
||||
}
|
||||
|
||||
|
||||
if [ MATCH .*(--debug-configuration).* : $(ARGV) ]
|
||||
{
|
||||
ECHO "notice: loading Boost.Build from"
|
||||
[ NORMALIZE_PATH $(.bootstrap-file:D) ] ;
|
||||
ECHO "notice: loading Boost.Build from"
|
||||
[ NORMALIZE_PATH $(.bootstrap-file:D) ] ;
|
||||
}
|
||||
|
||||
|
||||
# Load the build system, now that we know where to start from.
|
||||
#
|
||||
include $(.bootstrap-file) ;
|
||||
}
|
||||
|
||||
|
||||
if [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]
|
||||
|| $(BOOST_ROOT) # A temporary measure so Jam works with Boost.Build v1
|
||||
|| $(BOOST_ROOT) # A temporary measure so Jam works with Boost.Build v1.
|
||||
{
|
||||
# We attempt to load "boost-build.jam" by searching from the current invocation directory
|
||||
# up to the root of the file-system.
|
||||
# We attempt to load "boost-build.jam" by searching from the current
|
||||
# invocation directory up to the root of the file-system.
|
||||
#
|
||||
# boost-build.jam is expected to invoke the "boost-build" rule to
|
||||
# load the Boost.Build files.
|
||||
|
||||
# boost-build.jam is expected to invoke the "boost-build" rule to load the
|
||||
# Boost.Build files.
|
||||
|
||||
local search-path = $(BOOST_BUILD_PATH) $(BOOST_ROOT) ;
|
||||
|
||||
|
||||
local boost-build-files =
|
||||
[ find-to-root [ PWD ] : boost-build.jam ]
|
||||
# Another temporary measure so Jam works with Boost.Build v1
|
||||
# Another temporary measure so Jam works with Boost.Build v1.
|
||||
[ GLOB $(search-path) : boost-build.jam ] ;
|
||||
|
||||
|
||||
.boost-build-file = $(boost-build-files[1]) ;
|
||||
|
||||
# There is no boost-build.jam we can find, exit with an error, and information.
|
||||
#
|
||||
|
||||
# There is no boost-build.jam we can find, exit with an error, and
|
||||
# information.
|
||||
if ! $(.boost-build-file)
|
||||
{
|
||||
ECHO "Unable to load Boost.Build: could not find \"boost-build.jam\"" ;
|
||||
ECHO --------------------------------------------------------------- ;
|
||||
|
||||
|
||||
if ! [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]
|
||||
{
|
||||
ECHO "BOOST_ROOT must be set, either in the environment, or " ;
|
||||
@@ -158,23 +155,21 @@ if [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]
|
||||
ECHO "and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: "$(search-path:J=", ")"." ;
|
||||
EXIT "Please consult the documentation at 'http://www.boost.org'." ;
|
||||
}
|
||||
|
||||
if [ MATCH .*(--debug-configuration).* : $(ARGV) ]
|
||||
|
||||
if [ MATCH .*(--debug-configuration).* : $(ARGV) ]
|
||||
{
|
||||
ECHO "notice: found boost-build.jam at"
|
||||
[ NORMALIZE_PATH $(.boost-build-file) ] ;
|
||||
ECHO "notice: found boost-build.jam at"
|
||||
[ NORMALIZE_PATH $(.boost-build-file) ] ;
|
||||
}
|
||||
|
||||
|
||||
# Now load the boost-build.jam to get the build system loaded. This
|
||||
# incidentaly loads the users jamfile and attempts to build targets.
|
||||
#
|
||||
# We also set it up so we can tell wether we are loading the new V2
|
||||
# system or the the old V1 system.
|
||||
#
|
||||
# We also set it up so we can tell whether we are loading the new V2 system
|
||||
# or the the old V1 system.
|
||||
include $(.boost-build-file) ;
|
||||
|
||||
|
||||
# Check that, at minimum, the bootstrap file was found.
|
||||
#
|
||||
if ! $(.bootstrap-file)
|
||||
{
|
||||
ECHO "Unable to load Boost.Build" ;
|
||||
@@ -211,7 +206,7 @@ else
|
||||
# 01/08/95 (seiwald) - Shell now handled with awk, not sed
|
||||
# 01/09/95 (seiwald) - Install* now take dest directory as target
|
||||
# 01/10/95 (seiwald) - All entries sorted.
|
||||
# 01/10/95 (seiwald) - NT support moved in, with LauraW's help.
|
||||
# 01/10/95 (seiwald) - NT support moved in, with LauraW's help.
|
||||
# 01/10/95 (seiwald) - VMS support moved in.
|
||||
# 02/06/95 (seiwald) - ObjectC++Flags and SubDirC++Flags added.
|
||||
# 02/07/95 (seiwald) - Iron out when HDRSEARCH uses "" or SEARCH_SOURCE.
|
||||
@@ -226,15 +221,15 @@ else
|
||||
# Special targets defined in this file:
|
||||
#
|
||||
# all - parent of first, shell, files, lib, exe
|
||||
# first - first dependent of 'all', for potential initialization
|
||||
# shell - parent of all Shell targets
|
||||
# first - first dependency of 'all', for potential initialization
|
||||
# shell - parent of all Shell targets
|
||||
# files - parent of all File targets
|
||||
# lib - parent of all Library targets
|
||||
# exe - parent of all Main targets
|
||||
# dirs - parent of all MkDir targets
|
||||
# clean - removes all Shell, File, Library, and Main targets
|
||||
# uninstall - removes all Install targets
|
||||
#
|
||||
#
|
||||
|
||||
# Rules defined by this file:
|
||||
#
|
||||
@@ -314,7 +309,7 @@ else
|
||||
# EXIT - blurt out targets and exit
|
||||
# INCLUDES - marks sources as headers for target (a codependency)
|
||||
# NOCARE - don't panic if the target can't be built
|
||||
# NOUPDATE - create the target if needed but never update it
|
||||
# NOUPDATE - create the target if needed but never update it
|
||||
# NOTFILE - ignore the timestamp of the target (it's not a file)
|
||||
# TEMPORARY - target need not be present if sources haven't changed
|
||||
#
|
||||
@@ -347,35 +342,35 @@ if $(NT)
|
||||
#
|
||||
local SUPPORTED_TOOLSETS = "BORLANDC" "VC7" "VISUALC" "VISUALC16" "INTELC" "WATCOM"
|
||||
"MINGW" "LCC" ;
|
||||
|
||||
|
||||
# this variable holds the current toolset
|
||||
#
|
||||
TOOLSET = "" ;
|
||||
|
||||
|
||||
# if the JAM_TOOLSET environment variable is defined, check that it is
|
||||
# one of our supported values
|
||||
#
|
||||
if $(JAM_TOOLSET)
|
||||
{
|
||||
local t ;
|
||||
|
||||
|
||||
for t in $(SUPPORTED_TOOLSETS)
|
||||
{
|
||||
$(t) = $($(t):J=" ") ; # reconstitute paths with spaces in them
|
||||
if $(t) = $(JAM_TOOLSET) { TOOLSET = $(t) ; }
|
||||
}
|
||||
|
||||
|
||||
if ! $(TOOLSET)
|
||||
{
|
||||
ECHO "The JAM_TOOLSET environment variable is defined but its value" ;
|
||||
ECHO "is invalid, please use one of the following:" ;
|
||||
ECHO ;
|
||||
|
||||
|
||||
for t in $(SUPPORTED_TOOLSETS) { ECHO " " $(t) ; }
|
||||
EXIT ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# if TOOLSET is empty, we'll try to detect the toolset from other
|
||||
# environment variables to remain backwards compatible with Jam 2.3
|
||||
#
|
||||
@@ -469,7 +464,7 @@ if $(NT)
|
||||
C++FLAGS ?= $(CCFLAGS) ;
|
||||
LINK ?= $(CC) ;
|
||||
LINKFLAGS ?= $(CCFLAGS) ;
|
||||
LINKLIBS ?=
|
||||
LINKLIBS ?=
|
||||
\"$(VISUALC16)\\lib\\mlibce.lib\"
|
||||
\"$(VISUALC16)\\lib\\oldnames.lib\"
|
||||
;
|
||||
@@ -582,7 +577,7 @@ if $(NT)
|
||||
else if $(TOOLSET) = MINGW
|
||||
{
|
||||
ECHO "Compiler is GCC with Mingw" ;
|
||||
|
||||
|
||||
AR ?= ar -ru ;
|
||||
CC ?= gcc ;
|
||||
CCFLAGS ?= "" ;
|
||||
@@ -600,7 +595,7 @@ if $(NT)
|
||||
else if $(TOOLSET) = LCC
|
||||
{
|
||||
ECHO "Compiler is Win32-LCC" ;
|
||||
|
||||
|
||||
AR ?= lcclib ;
|
||||
CC ?= lcc ;
|
||||
CCFLAGS ?= "" ;
|
||||
@@ -616,7 +611,7 @@ if $(NT)
|
||||
{
|
||||
#
|
||||
# XXX: We need better comments here !!
|
||||
#
|
||||
#
|
||||
EXIT On NT, set BCCROOT, MSVCNT, MINGW or MSVC to the root of the
|
||||
Borland or Microsoft directories. ;
|
||||
}
|
||||
@@ -627,18 +622,18 @@ else if $(OS2)
|
||||
# the list of supported toolsets on Windows NT and Windows 95/98
|
||||
#
|
||||
local SUPPORTED_TOOLSETS = "EMX" "WATCOM" ;
|
||||
|
||||
|
||||
# this variable holds the current toolset
|
||||
#
|
||||
TOOLSET = "" ;
|
||||
|
||||
|
||||
# if the JAM_TOOLSET environment variable is defined, check that it is
|
||||
# one of our supported values
|
||||
#
|
||||
if $(JAM_TOOLSET)
|
||||
{
|
||||
local t ;
|
||||
|
||||
|
||||
for t in $(SUPPORTED_TOOLSETS)
|
||||
{
|
||||
$(t) = $($(t):J=" ") ; # reconstitute paths with spaces in them
|
||||
@@ -650,12 +645,12 @@ else if $(OS2)
|
||||
ECHO "The JAM_TOOLSET environment variable is defined but its value" ;
|
||||
ECHO "is invalid, please use one of the following:" ;
|
||||
ECHO ;
|
||||
|
||||
|
||||
for t in $(SUPPORTED_TOOLSETS) { ECHO " " $(t) ; }
|
||||
EXIT ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# if TOOLSET is empty, we'll try to detect the toolset from other
|
||||
# environment variables to remain backwards compatible with Jam 2.3
|
||||
#
|
||||
@@ -698,7 +693,7 @@ else if $(OS2)
|
||||
SUFLIB ?= .lib ;
|
||||
SUFOBJ ?= .obj ;
|
||||
SUFEXE ?= .exe ;
|
||||
|
||||
|
||||
if $(TOOLSET) = WATCOM
|
||||
{
|
||||
AR ?= wlib ;
|
||||
@@ -769,7 +764,7 @@ else if $(VMS)
|
||||
SUFLIB ?= .olb ;
|
||||
SUFOBJ ?= .obj ;
|
||||
|
||||
switch $(OS)
|
||||
switch $(OS)
|
||||
{
|
||||
case OPENVMS : CCFLAGS ?= /stand=vaxc ;
|
||||
case VMS : LINKLIBS ?= sys$library:vaxcrtl.olb/lib ;
|
||||
@@ -778,7 +773,7 @@ else if $(VMS)
|
||||
else if $(MAC)
|
||||
{
|
||||
local OPT ;
|
||||
|
||||
|
||||
CW ?= "{CW}" ;
|
||||
|
||||
MACHDRS ?=
|
||||
@@ -790,19 +785,19 @@ else if $(MAC)
|
||||
"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Interfacelib"
|
||||
"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Mathlib" ;
|
||||
|
||||
MPWLIBS ?=
|
||||
MPWLIBS ?=
|
||||
"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
|
||||
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib" ;
|
||||
|
||||
MPWNLLIBS ?=
|
||||
MPWNLLIBS ?=
|
||||
"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib"
|
||||
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW(NL).Lib" ;
|
||||
|
||||
|
||||
SIOUXHDRS ?= ;
|
||||
|
||||
SIOUXLIBS ?=
|
||||
|
||||
SIOUXLIBS ?=
|
||||
"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.lib"
|
||||
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib"
|
||||
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib"
|
||||
"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC.Lib" ;
|
||||
|
||||
C++ ?= mwcppc ;
|
||||
@@ -814,15 +809,15 @@ else if $(MAC)
|
||||
DOTDOT ?= "::" ;
|
||||
HDRS ?= $(MACHDRS) $(MPWHDRS) ;
|
||||
LINK ?= mwlinkppc ;
|
||||
LINKFLAGS ?= -mpwtool -warn ;
|
||||
LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ;
|
||||
LINKFLAGS ?= -mpwtool -warn ;
|
||||
LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ;
|
||||
MKDIR ?= newfolder ;
|
||||
MV ?= rename -y ;
|
||||
NOARSCAN ?= true ;
|
||||
OPTIM ?= ;
|
||||
RM ?= delete -y ;
|
||||
SLASH ?= ":" ;
|
||||
STDHDRS ?= ;
|
||||
STDHDRS ?= ;
|
||||
SUFLIB ?= .lib ;
|
||||
SUFOBJ ?= .o ;
|
||||
}
|
||||
@@ -842,7 +837,7 @@ else if $(OS) = BEOS && $(METROWERKS)
|
||||
NOARSCAN ?= true ;
|
||||
STDHDRS ?= /boot/develop/headers/posix ;
|
||||
}
|
||||
else if $(OS) = BEOS
|
||||
else if $(OS) = BEOS
|
||||
{
|
||||
BINDIR ?= /boot/apps ;
|
||||
CC ?= gcc ;
|
||||
@@ -865,7 +860,7 @@ else if $(UNIX)
|
||||
CC ?= gcc ;
|
||||
YACC ?= "bison -y" ;
|
||||
|
||||
case CYGWIN :
|
||||
case CYGWIN :
|
||||
CC ?= gcc ;
|
||||
CCFLAGS += -D__cygwin__ ;
|
||||
LEX ?= flex ;
|
||||
@@ -895,12 +890,12 @@ else if $(UNIX)
|
||||
C++ ?= gcc ;
|
||||
CCFLAGS += -D_POSIX_SOURCE ;
|
||||
HDRS += /usr/include ;
|
||||
RANLIB ?= "" ;
|
||||
RANLIB ?= "" ;
|
||||
NOARSCAN ?= true ;
|
||||
NOARUPDATE ?= true ;
|
||||
|
||||
case MVS :
|
||||
RANLIB ?= "" ;
|
||||
RANLIB ?= "" ;
|
||||
|
||||
case NEXT :
|
||||
AR ?= libtool -o ;
|
||||
@@ -1017,7 +1012,7 @@ else if $(UNIX)
|
||||
YACCFILES ?= ;
|
||||
YACCFLAGS ?= ;
|
||||
|
||||
HDRPATTERN =
|
||||
HDRPATTERN =
|
||||
"^[ ]*#[ ]*include[ ]*[<\"]([^\">]*)[\">].*$" ;
|
||||
|
||||
OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;
|
||||
@@ -1137,7 +1132,7 @@ rule Fortran
|
||||
DEPENDS $(<) : $(>) ;
|
||||
}
|
||||
|
||||
rule GenFile
|
||||
rule GenFile
|
||||
{
|
||||
local _t = [ FGristSourceFiles $(<) ] ;
|
||||
local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;
|
||||
@@ -1188,11 +1183,11 @@ rule HdrRule
|
||||
|
||||
local s ;
|
||||
|
||||
if $(HDRGRIST)
|
||||
{
|
||||
if $(HDRGRIST)
|
||||
{
|
||||
s = $(>:G=$(HDRGRIST)) ;
|
||||
} else {
|
||||
s = $(>) ;
|
||||
} else {
|
||||
s = $(>) ;
|
||||
}
|
||||
|
||||
INCLUDES $(<) : $(s) ;
|
||||
@@ -1236,14 +1231,14 @@ rule InstallInto
|
||||
Install $(tt) : $(i) ;
|
||||
Chmod $(tt) ;
|
||||
|
||||
if $(OWNER) && $(CHOWN)
|
||||
{
|
||||
if $(OWNER) && $(CHOWN)
|
||||
{
|
||||
Chown $(tt) ;
|
||||
OWNER on $(tt) = $(OWNER) ;
|
||||
}
|
||||
|
||||
if $(GROUP) && $(CHGRP)
|
||||
{
|
||||
if $(GROUP) && $(CHGRP)
|
||||
{
|
||||
Chgrp $(tt) ;
|
||||
GROUP on $(tt) = $(GROUP) ;
|
||||
}
|
||||
@@ -1344,11 +1339,11 @@ rule LibraryFromObjects
|
||||
MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;
|
||||
}
|
||||
|
||||
if $(NOARSCAN)
|
||||
{
|
||||
if $(NOARSCAN)
|
||||
{
|
||||
# If we can't scan the library to timestamp its contents,
|
||||
# we have to just make the library depend directly on the
|
||||
# on-disk object files.
|
||||
# on-disk object files.
|
||||
|
||||
DEPENDS $(_l) : $(_s) ;
|
||||
}
|
||||
@@ -1446,12 +1441,12 @@ rule MkDir
|
||||
|
||||
NOUPDATE $(<) ;
|
||||
|
||||
if $(<) != $(DOT) && ! $($(<)-mkdir)
|
||||
if $(<) != $(DOT) && ! $($(<)-mkdir)
|
||||
{
|
||||
local s ;
|
||||
|
||||
# Cheesy gate to prevent multiple invocations on same dir
|
||||
# MkDir1 has the actions
|
||||
# MkDir1 has the actions
|
||||
# Arrange for jam dirs
|
||||
|
||||
$(<)-mkdir = true ;
|
||||
@@ -1508,7 +1503,7 @@ rule Object
|
||||
# the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE)
|
||||
# with the scanned file as the target and the found headers
|
||||
# as the sources. HDRSEARCH is the value of SEARCH used for
|
||||
# the found header files. Finally, if jam must deal with
|
||||
# the found header files. Finally, if jam must deal with
|
||||
# header files of the same name in different directories,
|
||||
# they can be distinguished with HDRGRIST.
|
||||
|
||||
@@ -1603,23 +1598,23 @@ rule SubDir
|
||||
#
|
||||
# SubDir TOP d1 [ ... ]
|
||||
#
|
||||
# This introduces a Jamfile that is part of a project tree
|
||||
# This introduces a Jamfile that is part of a project tree
|
||||
# rooted at $(TOP). It (only once) includes the project-specific
|
||||
# rules file $(TOP)/Jamrules and then sets search & locate stuff.
|
||||
#
|
||||
# If the variable $(TOPRULES) is set (where TOP is the first arg
|
||||
# If the variable $(TOPRULES) is set (where TOP is the first arg
|
||||
# to SubDir), that file is included instead of $(TOP)/Jamrules.
|
||||
#
|
||||
# d1 ... are the directory elements that lead to this directory
|
||||
# d1 ... are the directory elements that lead to this directory
|
||||
# from $(TOP). We construct the system dependent path from these
|
||||
# directory elements in order to set search&locate stuff.
|
||||
#
|
||||
# directory elements in order to set search & locate stuff.
|
||||
#
|
||||
|
||||
if ! $($(<[1]))
|
||||
{
|
||||
if ! $(<[1])
|
||||
{
|
||||
EXIT SubDir syntax error ;
|
||||
EXIT SubDir syntax error ;
|
||||
}
|
||||
|
||||
$(<[1]) = [ FSubDir $(<[2-]) ] ;
|
||||
@@ -1703,7 +1698,7 @@ rule SubInclude
|
||||
}
|
||||
|
||||
_s = [ FDirName $(<[2-]) ] ;
|
||||
|
||||
|
||||
include $(JAMFILE:D=$(_s):R=$($(<[1]))) ;
|
||||
}
|
||||
|
||||
@@ -1735,14 +1730,13 @@ rule Yacc
|
||||
Clean clean : $(<) $(_h) ;
|
||||
}
|
||||
|
||||
# make sure someone includes $(_h) else it will be
|
||||
# a deadly independent target
|
||||
|
||||
# Make sure someone includes $(_h) else it will be a deadly independent
|
||||
# target.
|
||||
INCLUDES $(<) : $(_h) ;
|
||||
}
|
||||
|
||||
#
|
||||
# Utility rules; no side effects on these
|
||||
# Utility rules; no side effects on these.
|
||||
#
|
||||
|
||||
rule FGrist
|
||||
@@ -1761,13 +1755,13 @@ rule FGrist
|
||||
return $(_g) ;
|
||||
}
|
||||
|
||||
rule FGristFiles
|
||||
rule FGristFiles
|
||||
{
|
||||
if ! $(SOURCE_GRIST)
|
||||
{
|
||||
return $(<) ;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
return $(<:G=$(SOURCE_GRIST)) ;
|
||||
}
|
||||
@@ -1775,7 +1769,7 @@ rule FGristFiles
|
||||
|
||||
rule FGristSourceFiles
|
||||
{
|
||||
# Produce source file name name with grist in it,
|
||||
# Produce source file name name with grist in it,
|
||||
# if SOURCE_GRIST is set.
|
||||
|
||||
# Leave header files alone, because they have a global
|
||||
@@ -1785,7 +1779,7 @@ rule FGristSourceFiles
|
||||
{
|
||||
return $(<) ;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
local _i _o ;
|
||||
|
||||
@@ -1826,10 +1820,10 @@ rule FSubDir
|
||||
# path (using ../../ etc) back to that root directory.
|
||||
# Sets result in $(<)
|
||||
|
||||
if ! $(<[1])
|
||||
if ! $(<[1])
|
||||
{
|
||||
_d = $(DOT) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_d = $(DOTDOT) ;
|
||||
@@ -1877,7 +1871,7 @@ rule FDirName
|
||||
else if $(MAC)
|
||||
{
|
||||
_s = $(DOT) ;
|
||||
|
||||
|
||||
for _i in $(<)
|
||||
{
|
||||
_s = $(_i:R=$(_s)) ;
|
||||
@@ -1885,7 +1879,7 @@ rule FDirName
|
||||
}
|
||||
else
|
||||
{
|
||||
_s = $(<[1]) ;
|
||||
_s = $(<[1]) ;
|
||||
|
||||
for _i in $(<[2-])
|
||||
{
|
||||
@@ -1940,7 +1934,7 @@ rule FRelPath
|
||||
rule FAppendSuffix
|
||||
{
|
||||
# E.g., "FAppendSuffix yacc lex foo.bat : $(SUFEXE) ;"
|
||||
# returns (yacc,lex,foo.bat) on Unix and
|
||||
# returns (yacc,lex,foo.bat) on Unix and
|
||||
# (yacc.exe,lex.exe,foo.bat) on NT.
|
||||
|
||||
if $(>)
|
||||
@@ -1968,7 +1962,7 @@ rule FAppendSuffix
|
||||
|
||||
rule unmakeDir
|
||||
{
|
||||
if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\
|
||||
if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\
|
||||
{
|
||||
unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;
|
||||
}
|
||||
@@ -1982,10 +1976,10 @@ rule unmakeDir
|
||||
rule FConvertToSlashes
|
||||
{
|
||||
local _d, _s, _i ;
|
||||
|
||||
|
||||
unmakeDir _d : $(<) ;
|
||||
|
||||
_s = $(_d[1]) ;
|
||||
|
||||
_s = $(_d[1]) ;
|
||||
for _i in $(_d[2-])
|
||||
{
|
||||
_s = $(_s)/$(_i) ;
|
||||
@@ -2064,7 +2058,7 @@ actions HardLink
|
||||
|
||||
actions Install
|
||||
{
|
||||
$(CP) $(>) $(<)
|
||||
$(CP) $(>) $(<)
|
||||
}
|
||||
|
||||
actions Lex
|
||||
@@ -2079,7 +2073,7 @@ actions LexMv
|
||||
|
||||
actions Link bind NEEDLIBS
|
||||
{
|
||||
$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
|
||||
$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)
|
||||
}
|
||||
|
||||
actions MkDir1
|
||||
@@ -2252,7 +2246,7 @@ if $(NT)
|
||||
{
|
||||
actions together piecemeal Archive
|
||||
{
|
||||
$(AR) $(<) +-$(>)
|
||||
$(AR) $(<) +-$(>)
|
||||
}
|
||||
|
||||
actions Cc
|
||||
@@ -2279,7 +2273,7 @@ if $(NT)
|
||||
{
|
||||
actions together piecemeal Archive
|
||||
{
|
||||
$(AR) /out:$(<) $(>)
|
||||
$(AR) /out:$(<) $(>)
|
||||
}
|
||||
|
||||
actions Cc
|
||||
@@ -2303,13 +2297,13 @@ if $(NT)
|
||||
# OS2 specific actions
|
||||
#
|
||||
|
||||
else if $(OS2)
|
||||
else if $(OS2)
|
||||
{
|
||||
if $(TOOLSET) = WATCOM
|
||||
{
|
||||
actions together piecemeal Archive
|
||||
{
|
||||
$(AR) $(<) +-$(>)
|
||||
$(AR) $(<) +-$(>)
|
||||
}
|
||||
|
||||
actions Cc
|
||||
@@ -2357,19 +2351,19 @@ else if $(OS2)
|
||||
|
||||
else if $(VMS)
|
||||
{
|
||||
actions updated together piecemeal Archive
|
||||
actions updated together piecemeal Archive
|
||||
{
|
||||
lib/replace $(<) $(>[1]) ,$(>[2-])
|
||||
}
|
||||
|
||||
actions Cc
|
||||
{
|
||||
$(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>)
|
||||
{
|
||||
$(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>)
|
||||
}
|
||||
|
||||
actions C++
|
||||
{
|
||||
$(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>)
|
||||
{
|
||||
$(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>)
|
||||
}
|
||||
|
||||
actions piecemeal together existing Clean
|
||||
@@ -2409,7 +2403,7 @@ else if $(VMS)
|
||||
|
||||
else if $(MAC)
|
||||
{
|
||||
actions together Archive
|
||||
actions together Archive
|
||||
{
|
||||
$(LINK) -library -o $(<) $(>)
|
||||
}
|
||||
@@ -2417,13 +2411,13 @@ else if $(MAC)
|
||||
actions Cc
|
||||
{
|
||||
set -e MWCincludes $(MACINC)
|
||||
$(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>)
|
||||
$(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>)
|
||||
}
|
||||
|
||||
actions C++
|
||||
{
|
||||
{
|
||||
set -e MWCincludes $(MACINC)
|
||||
$(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>)
|
||||
$(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>)
|
||||
}
|
||||
|
||||
actions Link bind NEEDLIBS
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: boost-jam
|
||||
Version: 3.1.16
|
||||
Version: 3.1.17
|
||||
Summary: Build tool
|
||||
Release: 1
|
||||
Source: %{name}-%{version}.tgz
|
||||
@@ -11,9 +11,9 @@ Packager: Rene Rivera <grafik@redshift-software.com>
|
||||
BuildRoot: /var/tmp/%{name}-%{version}.root
|
||||
|
||||
%description
|
||||
Boost Jam is a build tool based on FTJam, which in turn is based on
|
||||
Boost Jam is a build tool based on FTJam, which in turn is based on
|
||||
Perforce Jam. It contains significant improvements made to facilitate
|
||||
its use in the Boost Build System, but should be backward compatible
|
||||
its use in the Boost Build System, but should be backward compatible
|
||||
with Perforce Jam.
|
||||
|
||||
Authors:
|
||||
@@ -26,7 +26,7 @@ Copyright:
|
||||
+\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
|
||||
\+/
|
||||
License is hereby granted to use this software and distribute it
|
||||
freely, as long as this copyright notice is retained and modifications
|
||||
freely, as long as this copyright notice is retained and modifications
|
||||
are clearly marked.
|
||||
ALL WARRANTIES ARE HEREBY DISCLAIMED.
|
||||
|
||||
@@ -34,7 +34,7 @@ Also:
|
||||
Copyright 2001-2006 David Abrahams.
|
||||
Copyright 2002-2006 Rene Rivera.
|
||||
Copyright 2003-2006 Vladimir Prus.
|
||||
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
|
||||
@@ -7,8 +7,15 @@ REM ~ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0
|
||||
setlocal
|
||||
goto Start
|
||||
|
||||
REM NOTE: The "setlocal & endlocal" construct is used to reset the errorlevel to 0.
|
||||
REM NOTE: The "set _error_=" construct is used to set the errorlevel to 1
|
||||
|
||||
:Set_Error
|
||||
color 00
|
||||
goto :eof
|
||||
|
||||
|
||||
:Clear_Error
|
||||
ver >nul
|
||||
goto :eof
|
||||
|
||||
|
||||
:Error_Print
|
||||
@@ -20,9 +27,10 @@ ECHO ###
|
||||
ECHO ### You can specify the toolset as the argument, i.e.:
|
||||
ECHO ### .\build.bat msvc
|
||||
ECHO ###
|
||||
ECHO ### Toolsets supported by this script are: borland, como, gcc, gcc-nocygwin, intel-win32, metrowerks, mingw, msvc, vc7, vc8
|
||||
ECHO ### Toolsets supported by this script are: borland, como, gcc, gcc-nocygwin,
|
||||
ECHO ### intel-win32, metrowerks, mingw, msvc, vc7, vc8, vc9
|
||||
ECHO ###
|
||||
set _error_=
|
||||
call :Set_Error
|
||||
endlocal
|
||||
goto :eof
|
||||
|
||||
@@ -31,7 +39,7 @@ goto :eof
|
||||
REM Tests for the given file(executable) presence in the directories in the PATH
|
||||
REM environment variable. Additionaly sets FOUND_PATH to the path of the
|
||||
REM found file.
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
setlocal
|
||||
set test=%~$PATH:1
|
||||
endlocal
|
||||
@@ -40,15 +48,39 @@ goto :eof
|
||||
|
||||
|
||||
:Test_Option
|
||||
REM Tests wether the given string is in the form of an option: "--*"
|
||||
setlocal & endlocal
|
||||
REM Tests whether the given string is in the form of an option: "--*"
|
||||
call :Clear_Error
|
||||
setlocal
|
||||
set test=%1
|
||||
if not defined test (
|
||||
call :Set_Error
|
||||
goto Test_Option_End
|
||||
)
|
||||
set test=###%test%###
|
||||
set test=%test:"###=%
|
||||
set test=%test:###"=%
|
||||
set test=%test:###=%
|
||||
if not [-] == [%test:~1,1%] set _error_=
|
||||
if not "-" == "%test:~1,1%" call :Set_Error
|
||||
:Test_Option_End
|
||||
endlocal
|
||||
goto :eof
|
||||
|
||||
|
||||
:Test_Empty
|
||||
REM Tests whether the given string is not empty
|
||||
call :Clear_Error
|
||||
setlocal
|
||||
set test=%1
|
||||
if not defined test (
|
||||
call :Clear_Error
|
||||
goto Test_Empty_End
|
||||
)
|
||||
set test=###%test%###
|
||||
set test=%test:"###=%
|
||||
set test=%test:###"=%
|
||||
set test=%test:###=%
|
||||
if not "" == "%test%" call :Set_Error
|
||||
:Test_Empty_End
|
||||
endlocal
|
||||
goto :eof
|
||||
|
||||
@@ -64,132 +96,134 @@ REM Sets BOOST_JAM_TOOLSET to the first found toolset.
|
||||
REM May also set BOOST_JAM_TOOLSET_ROOT to the
|
||||
REM location of the found toolset.
|
||||
|
||||
if "_%ProgramFiles%_" == "__" set ProgramFiles=C:\Program Files
|
||||
call :Clear_Error
|
||||
call :Test_Empty %ProgramFiles%
|
||||
if not errorlevel 1 set ProgramFiles=C:\Program Files
|
||||
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if NOT "_%VS90COMNTOOLS%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET=vc9"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%VS90COMNTOOLS%..\..\VC\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "%ProgramFiles%\Microsoft Visual Studio 9.0\VC\VCVARSALL.BAT" (
|
||||
set "BOOST_JAM_TOOLSET=vc9"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 9.0\VC\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if NOT "_%VS80COMNTOOLS%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET=vc8"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%VS80COMNTOOLS%..\..\VC\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "%ProgramFiles%\Microsoft Visual Studio 8\VC\VCVARSALL.BAT" (
|
||||
set "BOOST_JAM_TOOLSET=vc8"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio 8\VC\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if NOT "_%VS71COMNTOOLS%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET=vc7"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%VS71COMNTOOLS%\..\..\VC7\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if NOT "_%VCINSTALLDIR%_" == "__" (
|
||||
REM %VCINSTALLDIR% is also set for VC9 (and probably VC8)
|
||||
set "BOOST_JAM_TOOLSET=vc7"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%VCINSTALLDIR%\VC7\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "%ProgramFiles%\Microsoft Visual Studio .NET 2003\VC7\bin\VCVARS32.BAT" (
|
||||
set "BOOST_JAM_TOOLSET=vc7"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio .NET 2003\VC7\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "%ProgramFiles%\Microsoft Visual Studio .NET\VC7\bin\VCVARS32.BAT" (
|
||||
set "BOOST_JAM_TOOLSET=vc7"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio .NET\VC7\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if NOT "_%MSVCDir%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET=msvc"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "%ProgramFiles%\Microsoft Visual Studio\VC98\bin\VCVARS32.BAT" (
|
||||
set "BOOST_JAM_TOOLSET=msvc"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual Studio\VC98\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "%ProgramFiles%\Microsoft Visual C++\VC98\bin\VCVARS32.BAT" (
|
||||
set "BOOST_JAM_TOOLSET=msvc"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%ProgramFiles%\Microsoft Visual C++\VC98\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Test_Path cl.exe
|
||||
if not errorlevel 1 (
|
||||
set "BOOST_JAM_TOOLSET=msvc"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Test_Path vcvars32.bat
|
||||
if not errorlevel 1 (
|
||||
set "BOOST_JAM_TOOLSET=msvc"
|
||||
call "%FOUND_PATH%VCVARS32.BAT"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "C:\Borland\BCC55\Bin\bcc32.exe" (
|
||||
set "BOOST_JAM_TOOLSET=borland"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=C:\Borland\BCC55\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Test_Path bcc32.exe
|
||||
if not errorlevel 1 (
|
||||
set "BOOST_JAM_TOOLSET=borland"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Test_Path icl.exe
|
||||
if not errorlevel 1 (
|
||||
set "BOOST_JAM_TOOLSET=intel-win32"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "C:\MinGW\bin\gcc.exe" (
|
||||
set "BOOST_JAM_TOOLSET=mingw"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=C:\MinGW\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if NOT "_%CWFolder%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET=metrowerks"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%CWFolder%\"
|
||||
goto :eof )
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Test_Path mwcc.exe
|
||||
if not errorlevel 1 (
|
||||
set "BOOST_JAM_TOOLSET=metrowerks"
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%FOUND_PATH%..\..\"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Error_Print "Could not find a suitable toolset."
|
||||
goto :eof
|
||||
|
||||
|
||||
:Guess_Yacc
|
||||
REM Tries to find bison or yacc in common places so we can build the grammar.
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Test_Path yacc.exe
|
||||
if not errorlevel 1 (
|
||||
set "YACC=yacc -d"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Test_Path bison.exe
|
||||
if not errorlevel 1 (
|
||||
set "YACC=bison -d --yacc"
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if EXIST "C:\Program Files\GnuWin32\bin\bison.exe" (
|
||||
set "YACC=C:\Program Files\GnuWin32\bin\bison.exe" -d --yacc
|
||||
goto :eof)
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
call :Error_Print "Could not find Yacc to build the Jam grammar."
|
||||
goto :eof
|
||||
|
||||
@@ -201,22 +235,24 @@ set BOOST_JAM_ARGS=
|
||||
REM If no arguments guess the toolset;
|
||||
REM or if first argument is an option guess the toolset;
|
||||
REM otherwise the argument is the toolset to use.
|
||||
if "_%1_" == "__" (
|
||||
call :Clear_Error
|
||||
call :Test_Empty %1
|
||||
if not errorlevel 1 (
|
||||
call :Guess_Toolset
|
||||
if not errorlevel 1 goto Setup_Toolset
|
||||
) else (
|
||||
call :Test_Option "%1"
|
||||
if not errorlevel 1 (
|
||||
call :Guess_Toolset
|
||||
if not errorlevel 1 goto Setup_Toolset
|
||||
) else (
|
||||
setlocal & endlocal
|
||||
set "BOOST_JAM_TOOLSET=%1"
|
||||
shift
|
||||
goto Setup_Toolset
|
||||
)
|
||||
if not errorlevel 1 ( goto Setup_Toolset ) else ( goto Finish )
|
||||
)
|
||||
if errorlevel 1 goto Finish
|
||||
|
||||
call :Clear_Error
|
||||
call :Test_Option %1
|
||||
if not errorlevel 1 (
|
||||
call :Guess_Toolset
|
||||
if not errorlevel 1 ( goto Setup_Toolset ) else ( goto Finish )
|
||||
)
|
||||
|
||||
call :Clear_Error
|
||||
set BOOST_JAM_TOOLSET=%1
|
||||
shift
|
||||
goto Setup_Toolset
|
||||
|
||||
|
||||
:Setup_Toolset
|
||||
@@ -229,15 +265,18 @@ REM because in BAT variables are subsituted only once during a single
|
||||
REM command. A complete "if ... ( commands ) else ( commands )"
|
||||
REM is a single command, even though it's in multiple lines here.
|
||||
:Setup_Args
|
||||
if "_%1_" == "__" goto Config_Toolset
|
||||
call :Test_Option "%1"
|
||||
call :Clear_Error
|
||||
call :Test_Empty %1
|
||||
if not errorlevel 1 goto Config_Toolset
|
||||
call :Clear_Error
|
||||
call :Test_Option %1
|
||||
if errorlevel 1 (
|
||||
set BOOST_JAM_ARGS=%BOOST_JAM_ARGS% %1
|
||||
shift
|
||||
goto Setup_Args
|
||||
)
|
||||
:Config_Toolset
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_metrowerks_" goto :Skip_METROWERKS
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_metrowerks_" goto Skip_METROWERKS
|
||||
if NOT "_%CWFolder%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%CWFolder%\"
|
||||
)
|
||||
@@ -248,7 +287,7 @@ set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
|
||||
set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
|
||||
set "_known_=1"
|
||||
:Skip_METROWERKS
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_msvc_" goto :Skip_MSVC
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_msvc_" goto Skip_MSVC
|
||||
if NOT "_%MSVCDir%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%MSVCDir%\"
|
||||
)
|
||||
@@ -262,7 +301,7 @@ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
|
||||
set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
|
||||
set "_known_=1"
|
||||
:Skip_MSVC
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc7_" goto :Skip_VC7
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc7_" goto Skip_VC7
|
||||
if NOT "_%VS71COMNTOOLS%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%VS71COMNTOOLS%..\..\VC7\"
|
||||
)
|
||||
@@ -277,7 +316,7 @@ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
|
||||
set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
|
||||
set "_known_=1"
|
||||
:Skip_VC7
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc8_" goto :Skip_VC8
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc8_" goto Skip_VC8
|
||||
if NOT "_%VS80COMNTOOLS%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%VS80COMNTOOLS%..\..\VC\"
|
||||
)
|
||||
@@ -292,7 +331,7 @@ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
|
||||
set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
|
||||
set "_known_=1"
|
||||
:Skip_VC8
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc9_" goto :Skip_VC9
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_vc9_" goto Skip_VC9
|
||||
if NOT "_%VS90COMNTOOLS%_" == "__" (
|
||||
set "BOOST_JAM_TOOLSET_ROOT=%VS90COMNTOOLS%..\..\VC\"
|
||||
)
|
||||
@@ -307,7 +346,7 @@ set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
|
||||
set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
|
||||
set "_known_=1"
|
||||
:Skip_VC9
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_borland_" goto :Skip_BORLAND
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_borland_" goto Skip_BORLAND
|
||||
if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
|
||||
call :Test_Path bcc32.exe )
|
||||
if "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
|
||||
@@ -323,35 +362,35 @@ set "BOOST_JAM_OPT_MKJAMBASE=-emkjambasejam0"
|
||||
set "BOOST_JAM_OPT_YYACC=-eyyacc0"
|
||||
set "_known_=1"
|
||||
:Skip_BORLAND
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_como_" goto :Skip_COMO
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_como_" goto Skip_COMO
|
||||
set "BOOST_JAM_CC=como -DNT"
|
||||
set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
|
||||
set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
|
||||
set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
|
||||
set "_known_=1"
|
||||
:Skip_COMO
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc_" goto :Skip_GCC
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc_" goto Skip_GCC
|
||||
set "BOOST_JAM_CC=gcc -DNT"
|
||||
set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
|
||||
set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
|
||||
set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
|
||||
set "_known_=1"
|
||||
:Skip_GCC
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc-nocygwin_" goto :Skip_GCC_NOCYGWIN
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_gcc-nocygwin_" goto Skip_GCC_NOCYGWIN
|
||||
set "BOOST_JAM_CC=gcc -DNT -mno-cygwin"
|
||||
set "BOOST_JAM_OPT_JAM=-o bootstrap\jam0.exe"
|
||||
set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
|
||||
set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
|
||||
set "_known_=1"
|
||||
:Skip_GCC_NOCYGWIN
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_intel-win32_" goto :Skip_INTEL_WIN32
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_intel-win32_" goto Skip_INTEL_WIN32
|
||||
set "BOOST_JAM_CC=icl -DNT /nologo kernel32.lib advapi32.lib user32.lib"
|
||||
set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0"
|
||||
set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0"
|
||||
set "BOOST_JAM_OPT_YYACC=/Febootstrap\yyacc0"
|
||||
set "_known_=1"
|
||||
:Skip_INTEL_WIN32
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_mingw_" goto :Skip_MINGW
|
||||
if NOT "_%BOOST_JAM_TOOLSET%_" == "_mingw_" goto Skip_MINGW
|
||||
if not "_%BOOST_JAM_TOOLSET_ROOT%_" == "__" (
|
||||
set "PATH=%BOOST_JAM_TOOLSET_ROOT%bin;%PATH%"
|
||||
)
|
||||
@@ -361,7 +400,7 @@ set "BOOST_JAM_OPT_MKJAMBASE=-o bootstrap\mkjambase0.exe"
|
||||
set "BOOST_JAM_OPT_YYACC=-o bootstrap\yyacc0.exe"
|
||||
set "_known_=1"
|
||||
:Skip_MINGW
|
||||
setlocal & endlocal
|
||||
call :Clear_Error
|
||||
if "_%_known_%_" == "__" (
|
||||
call :Error_Print "Unknown toolset: %BOOST_JAM_TOOLSET%"
|
||||
)
|
||||
@@ -379,29 +418,31 @@ set BJAM_SOURCES=%BJAM_SOURCES% hdrmacro.c headers.c jam.c jambase.c jamgram.c l
|
||||
set BJAM_SOURCES=%BJAM_SOURCES% newstr.c option.c output.c parse.c pathunix.c regexp.c
|
||||
set BJAM_SOURCES=%BJAM_SOURCES% rules.c scan.c search.c subst.c timestamp.c variable.c modules.c
|
||||
set BJAM_SOURCES=%BJAM_SOURCES% strings.c filesys.c builtins.c pwd.c class.c w32_getreg.c native.c
|
||||
set BJAM_SOURCES=%BJAM_SOURCES% modules/set.c modules/path.c modules/regex.c
|
||||
set BJAM_SOURCES=%BJAM_SOURCES% modules/set.c modules/path.c modules/regex.c
|
||||
set BJAM_SOURCES=%BJAM_SOURCES% modules/property-set.c modules/sequence.c modules/order.c
|
||||
|
||||
set BJAM_UPDATE=
|
||||
if "_%1" == "_--update" (
|
||||
set BJAM_UPDATE=update
|
||||
)
|
||||
if "_%2" == "_--update" (
|
||||
set BJAM_UPDATE=update
|
||||
)
|
||||
if "_%3" == "_--update" (
|
||||
set BJAM_UPDATE=update
|
||||
)
|
||||
if "_%4" == "_--update" (
|
||||
set BJAM_UPDATE=update
|
||||
)
|
||||
:Check_Update
|
||||
call :Test_Empty %1
|
||||
if not errorlevel 1 goto Check_Update_End
|
||||
call :Clear_Error
|
||||
setlocal
|
||||
set test=%1
|
||||
set test=###%test%###
|
||||
set test=%test:"###=%
|
||||
set test=%test:###"=%
|
||||
set test=%test:###=%
|
||||
if "%test%" == "--update" set BJAM_UPDATE=update
|
||||
endlocal
|
||||
shift
|
||||
if not "_%BJAM_UPDATE%_" == "_update_" goto Check_Update
|
||||
:Check_Update_End
|
||||
if "_%BJAM_UPDATE%_" == "_update_" (
|
||||
if not exist ".\bootstrap\jam0.exe" (
|
||||
set BJAM_UPDATE=
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@echo ON
|
||||
@if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Bootstrap
|
||||
rd /S /Q bootstrap
|
||||
@@ -443,13 +484,23 @@ rename y.tab.h jamgram.h
|
||||
@if "_%BJAM_UPDATE%_" == "_update_" goto Skip_Clean
|
||||
.\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " clean
|
||||
:Skip_Clean
|
||||
@set args=
|
||||
@set args=%*
|
||||
@echo OFF
|
||||
:Set_Args
|
||||
@if not "_%1_" == "__" (
|
||||
set args=%args% %1
|
||||
shift
|
||||
goto Set_Args
|
||||
)
|
||||
setlocal
|
||||
call :Test_Empty %args%
|
||||
if not errorlevel 1 goto Set_Args_End
|
||||
set test=###%args:~0,2%###
|
||||
set test=%test:"###=%
|
||||
set test=%test:###"=%
|
||||
set test=%test:###=%
|
||||
set test=%test:~0,1%
|
||||
if "-" == "%test%" goto Set_Args_End
|
||||
endlocal
|
||||
set args=%args:~1%
|
||||
goto Set_Args
|
||||
:Set_Args_End
|
||||
@echo ON
|
||||
.\bootstrap\jam0 -f build.jam --toolset=%BOOST_JAM_TOOLSET% "--toolset-root=%BOOST_JAM_TOOLSET_ROOT% " %args%
|
||||
:Skip_Jam
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ else if $(MAC) { rule .path { return ":$(<:J=\:)" ; } }
|
||||
else { rule .path { return "$(<:J=/)" ; } }
|
||||
if $(VMS) { . = "_" ; }
|
||||
else { . = "." ; }
|
||||
./ ?= "" ;
|
||||
./ ?= "" ;
|
||||
|
||||
# Info about what we are building.
|
||||
_VERSION_ = 3 1 16 ;
|
||||
_VERSION_ = 3 1 17 ;
|
||||
NAME = boost-jam ;
|
||||
VERSION = $(_VERSION_:J=$(.)) ;
|
||||
RELEASE = 1 ;
|
||||
@@ -25,6 +25,11 @@ if --debug in $(ARGV)
|
||||
debug = true ;
|
||||
}
|
||||
|
||||
if --profile in $(ARGV)
|
||||
{
|
||||
profile = true ;
|
||||
}
|
||||
|
||||
# Attempt to generate and/or build the grammar?
|
||||
if --grammar in $(ARGV)
|
||||
{
|
||||
@@ -33,7 +38,8 @@ if --grammar in $(ARGV)
|
||||
|
||||
# Do we need to add a default build type argument?
|
||||
if ! ( --release in $(ARGV) ) &&
|
||||
! ( --debug in $(ARGV) )
|
||||
! ( --debug in $(ARGV) ) &&
|
||||
! ( --profile in $(ARGV) )
|
||||
{
|
||||
ARGV += --release ;
|
||||
}
|
||||
@@ -126,6 +132,7 @@ toolset-root = [ MATCH --toolset-root=(.*) : $(ARGV) ] ;
|
||||
# commands and options to compile the full Jam. When
|
||||
# adding new toolsets make sure to add them to the
|
||||
# "known" list also.
|
||||
|
||||
rule toolset ( name command .type ? : opt.out + : opt.define * : flags * : linklibs * )
|
||||
{
|
||||
.type ?= "" ;
|
||||
@@ -136,7 +143,13 @@ rule toolset ( name command .type ? : opt.out + : opt.define * : flags * : linkl
|
||||
tool.$(name)$(.type).linklibs ?= $(linklibs) ;
|
||||
if ! $(name) in $(toolsets) { toolsets += $(name) ; }
|
||||
}
|
||||
rule opt ( type : yes-opt * : no-opt * ) { if $(type) in $(ARGV) { return $(yes-opt) ; } else { return $(no-opt) ; } }
|
||||
|
||||
rule if-os ( os + : yes-opt * : no-opt * )
|
||||
{ if $(os) in $(OS) { return $(yes-opt) ; } else { return $(no-opt) ; } }
|
||||
|
||||
rule opt ( type : yes-opt * : no-opt * )
|
||||
{ if $(type) in $(ARGV) { return $(yes-opt) ; } else { return $(no-opt) ; } }
|
||||
|
||||
## HP-UX aCC compiler
|
||||
toolset acc cc : "-o " : -D
|
||||
: -Ae
|
||||
@@ -171,6 +184,7 @@ toolset darwin cc : "-o " : -D
|
||||
:
|
||||
[ opt --release : -Wl,-x -O3 -finline-functions ]
|
||||
[ opt --debug : -g -O0 -fno-inline -pg ]
|
||||
[ opt --profile : -Wl,-x -O3 -finline-functions -g -pg ]
|
||||
-I$(--python-include) -I$(--extra-include)
|
||||
: -L$(--python-lib[1]) -l$(--python-lib[2]) ;
|
||||
## GCC 2.x, 3.x, 4.x
|
||||
@@ -254,7 +268,7 @@ toolset msvc cl : /Fe /Fe /Fd /Fo : -D
|
||||
: kernel32.lib advapi32.lib user32.lib $(--python-lib[1]) ;
|
||||
## QNX 6.x GCC 3.x/2.95.3
|
||||
toolset qcc qcc : "-o " : -D
|
||||
: -Wc,-pedantic
|
||||
: -Wc,-pedantic -Wc,-fno-strict-aliasing
|
||||
[ opt --release : [ opt --symbols : -g ] -O3 -Wc,-finline-functions ]
|
||||
[ opt --debug : -g -O0 -Wc,-fno-inline ]
|
||||
-I$(--python-include) -I$(--extra-include)
|
||||
@@ -278,7 +292,6 @@ toolset sun cc : "-o " : -D
|
||||
:
|
||||
[ opt --release : -s -fast -xO4 ]
|
||||
[ opt --debug : -g ]
|
||||
-xarch=generic
|
||||
-I$(--python-include) -I$(--extra-include)
|
||||
: -L$(--python-lib[1]) -l$(--python-lib[2]) ;
|
||||
## Sun Workshop 6 C++ (old alias)
|
||||
@@ -286,7 +299,6 @@ toolset sunpro cc : "-o " : -D
|
||||
:
|
||||
[ opt --release : -s -fast -xO4 ]
|
||||
[ opt --debug : -g ]
|
||||
-xarch=generic
|
||||
-I$(--python-include) -I$(--extra-include)
|
||||
: -L$(--python-lib[1]) -l$(--python-lib[2]) ;
|
||||
## Compaq Alpha CXX
|
||||
@@ -302,7 +314,7 @@ toolset vacpp xlc : "-o " : -D
|
||||
[ opt --release : -s -O3 -qstrict -qinline ]
|
||||
[ opt --debug : -g -qNOOPTimize -qnoinline -pg ]
|
||||
-I$(--python-include) -I$(--extra-include)
|
||||
: -L$(--python-lib[1]) -l$(--python-lib[2]) -bmaxdata:0x40000000 ;
|
||||
: -L$(--python-lib[1]) -l$(--python-lib[2]) [ if-os AIX : -bmaxdata:0x40000000 ] ;
|
||||
## Microsoft Visual C++ .NET 7.x
|
||||
toolset vc7 cl : /Fe /Fe /Fd /Fo : -D
|
||||
: /nologo
|
||||
@@ -341,13 +353,12 @@ toolset vmsdecc link .link : /EXECUTABLE= :
|
||||
toolset = [ MATCH --toolset=(.*) : $(ARGV) ] ;
|
||||
if ! $(toolset)
|
||||
{
|
||||
# For some reason, the following test does not catch
|
||||
# empty toolset.
|
||||
# For some reason, the following test does not catch empty toolset.
|
||||
ECHO "###" ;
|
||||
ECHO "###" No toolset specified. Please use --toolset option. ;
|
||||
ECHO "###" ;
|
||||
ECHO "###" Known toolsets are: $(toolsets:J=", ") ;
|
||||
EXIT "###" ;
|
||||
EXIT "###" ;
|
||||
}
|
||||
if ! $(toolset) in $(toolsets)
|
||||
{
|
||||
@@ -431,6 +442,10 @@ if $(debug)
|
||||
{
|
||||
locate-target = [ .path $(locate-target)$(.)debug ] ;
|
||||
}
|
||||
if $(profile)
|
||||
{
|
||||
locate-target = [ .path $(locate-target)$(.)profile ] ;
|
||||
}
|
||||
else
|
||||
{
|
||||
locate-target = [ .path $(locate-target) ] ;
|
||||
@@ -449,8 +464,8 @@ jam.source =
|
||||
lists.c make.c make1.c mem.c newstr.c
|
||||
option.c output.c parse.c regexp.c rules.c
|
||||
scan.c search.c subst.c w32_getreg.c
|
||||
timestamp.c variable.c modules.c strings.c filesys.c
|
||||
builtins.c pwd.c class.c native.c modules/set.c
|
||||
timestamp.c variable.c modules.c strings.c filesys.c
|
||||
builtins.c pwd.c class.c native.c modules/set.c
|
||||
modules/path.c modules/regex.c modules/property-set.c
|
||||
modules/sequence.c modules/order.c
|
||||
;
|
||||
@@ -461,7 +476,7 @@ if $(NT)
|
||||
else if $(OS2)
|
||||
{
|
||||
jam.source += execunix.c fileos2.c pathunix.c ;
|
||||
}
|
||||
}
|
||||
else if $(VMS)
|
||||
{
|
||||
jam.source += execvms.c filevms.c pathvms.c ;
|
||||
@@ -541,10 +556,10 @@ rule .clean
|
||||
[DELETE] clean : $(<) ;
|
||||
}
|
||||
if $(NT) { actions piecemeal together existing [DELETE] {
|
||||
del /F /Q $(>)
|
||||
del /F /Q "$(>)"
|
||||
} }
|
||||
if $(UNIX) { actions piecemeal together existing [DELETE] {
|
||||
rm -f $(>)
|
||||
rm -f "$(>)"
|
||||
} }
|
||||
if $(VMS) { actions piecemeal together existing [DELETE] {
|
||||
DELETE $(>[--2]:J=";*, ") $(>[-1]);*
|
||||
@@ -566,10 +581,10 @@ rule .mkdir
|
||||
if ! $(md<$(<)>) { [MKDIR] $(<) ; md<$(<)> = - ; }
|
||||
}
|
||||
if $(NT) { actions [MKDIR] {
|
||||
md $(<)
|
||||
md "$(<)"
|
||||
} }
|
||||
if $(UNIX) { actions [MKDIR] {
|
||||
mkdir $(<)
|
||||
mkdir "$(<)"
|
||||
} }
|
||||
if $(VMS) { actions [MKDIR] {
|
||||
CREATE/DIR $(<J=", ")
|
||||
@@ -614,16 +629,16 @@ rule .exe
|
||||
return $(exe) ;
|
||||
}
|
||||
if ! $(--def[2]) { actions [COMPILE] {
|
||||
"$(--cc)" $(--bin)$(<:D=) $(--dir)$(<:D)$(./) $(--out)$(<) $(--def)$(--defs) $(--flags) "$(--libs)" $(>)
|
||||
"$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def)$(--defs)" "$(--flags)" "$(--libs)" "$(>)"
|
||||
} }
|
||||
else { actions [COMPILE] {
|
||||
"$(--cc)" $(--bin)$(<:D=) $(--dir)$(<:D)$(./) $(--out)$(<) $(--def[1])$(--defs:J=$(--def[2]))$(--def[3]) $(--flags) "$(--libs)" $(>)
|
||||
"$(--cc)" "$(--bin)$(<:D=)" "$(--dir)$(<:D)$(./)" $(--out)$(<) "$(--def[1])$(--defs:J=$(--def[2]))$(--def[3])" "$(--flags)" "$(--libs)" "$(>)"
|
||||
} }
|
||||
if $(VMS) { actions [COMPILE.LINK] {
|
||||
"$(--link)" $(--link-bin)$(<:D=) $(--link-dir)$(<:D)$(./) $(--link-out)$(<) $(--link-def)$(--link-defs) $(--link-flags) "$(--link-libs)" $(>J=", ")
|
||||
} }
|
||||
else { actions [COMPILE.LINK] {
|
||||
"$(--link)" $(--link-bin)$(<:D=) $(--link-dir)$(<:D)$(./) $(--link-out)$(<) $(--link-def)$(--link-defs) $(--link-flags) "$(--link-libs)" $(>)
|
||||
"$(--link)" "$(--link-bin)$(<:D=)" "$(--link-dir)$(<:D)$(./)" "$(--link-out)$(<)" "$(--link-def)$(--link-defs)" "$(--link-flags)" "$(--link-libs)" "$(>)"
|
||||
} }
|
||||
|
||||
rule .link
|
||||
@@ -634,10 +649,10 @@ rule .link
|
||||
.clean $(<) ;
|
||||
}
|
||||
if $(NT) { actions [LINK] {
|
||||
copy $(>) $(<)
|
||||
copy "$(>)" "$(<)"
|
||||
} }
|
||||
if $(UNIX) { actions [LINK] {
|
||||
ln -fs $(>) $(<)
|
||||
ln -fs "$(>)" "$(<)"
|
||||
} }
|
||||
if $(VMS) { actions [LINK] {
|
||||
COPY/REPLACE $(>) $(<)
|
||||
@@ -649,14 +664,14 @@ rule .move
|
||||
[MOVE] $(<) : $(>) ;
|
||||
}
|
||||
if $(NT) { actions [MOVE] {
|
||||
del /f $(<)
|
||||
rename $(>) $(<)
|
||||
del /f "$(<)"
|
||||
rename "$(>)" "$(<)"
|
||||
} }
|
||||
if $(UNIX) { actions [MOVE] {
|
||||
mv -f $(>) $(<)
|
||||
mv -f "$(>)" "$(<)"
|
||||
} }
|
||||
if $(VMS) { actions [MOVE] {
|
||||
RENAME $(>) $(<)
|
||||
RENAME "$(>)" "$(<)"
|
||||
} }
|
||||
|
||||
# Generate the grammar tokens table, and the real yacc grammar.
|
||||
@@ -672,7 +687,7 @@ rule .yyacc
|
||||
actions [YYACC] {
|
||||
$(--chmod+w)$(<[1])
|
||||
$(--chmod+w)$(<[2])
|
||||
"$(yyacc.exe)" $(<) $(>)
|
||||
"$(yyacc.exe)" "$(<)" "$(>)"
|
||||
}
|
||||
if $(grammar)
|
||||
{
|
||||
@@ -715,18 +730,18 @@ rule .yacc
|
||||
[YACC] $(<) : $(>) ;
|
||||
}
|
||||
if $(NT) { actions [YACC] {
|
||||
"$(yacc)" $(>)
|
||||
"$(yacc)" "$(>)"
|
||||
if not errorlevel 1 (
|
||||
del /f $(<[1])
|
||||
rename y.tab$(<[1]:S) $(<[1])
|
||||
del /f "$(<[1])"
|
||||
rename y.tab$(<[1]:S) "$(<[1])"
|
||||
del /f $(<[2])
|
||||
rename y.tab$(<[2]:S) $(<[2])
|
||||
rename y.tab$(<[2]:S) "$(<[2])"
|
||||
) else set _error_ =
|
||||
} }
|
||||
if $(UNIX) { actions [YACC] {
|
||||
if ` "$(yacc)" $(>) ` ; then
|
||||
mv -f y.tab$(<[1]:S) $(<[1])
|
||||
mv -f y.tab$(<[2]:S) $(<[2])
|
||||
if ` "$(yacc)" "$(>)" ` ; then
|
||||
mv -f y.tab$(<[1]:S) "$(<[1])"
|
||||
mv -f y.tab$(<[2]:S) "$(<[2])"
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
@@ -758,7 +773,7 @@ rule .mkjambase
|
||||
}
|
||||
actions [MKJAMBASE] {
|
||||
$(--chmod+w)$(<)
|
||||
$(mkjambase.exe) $(<) $(>)
|
||||
$(mkjambase.exe) "$(<)" "$(>)"
|
||||
}
|
||||
if $(debug)
|
||||
{
|
||||
@@ -770,7 +785,7 @@ rule .jam
|
||||
{
|
||||
$(>).exe = [ .exe $(>) : $(jam.source) ] ;
|
||||
DEPENDS all : $($(>).exe) ;
|
||||
|
||||
|
||||
if $(debug)
|
||||
{
|
||||
$(<).exe = $(<:S=$($(>).exe:S)) ;
|
||||
@@ -929,14 +944,14 @@ rule .package ( dst-dir : src-files + )
|
||||
src-files-actual += $(src-path) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
local pack = ;
|
||||
if $(NT) { pack = $(dst-dir).zip ; }
|
||||
if $(UNIX) { pack = $(dst-dir).tgz ; }
|
||||
|
||||
|
||||
DEPENDS dist : $(pack) ;
|
||||
DEPENDS $(pack) : $(dst-files) ;
|
||||
|
||||
|
||||
local dst-files-queue = $(dst-files) ;
|
||||
for local src-path in $(src-files-actual)
|
||||
{
|
||||
@@ -944,11 +959,11 @@ rule .package ( dst-dir : src-files + )
|
||||
dst-files-queue = $(dst-files-queue[2-]) ;
|
||||
DEPENDS $(dst-file) : $(src-path) $(dst-file:D) ;
|
||||
.mkdir $(dst-file:D) ;
|
||||
|
||||
|
||||
[COPY] $(dst-file) : $(src-path) ;
|
||||
.clean $(dst-file) ;
|
||||
}
|
||||
|
||||
|
||||
[PACK] $(pack) : $(dst-files) ;
|
||||
.clean $(pack) ;
|
||||
}
|
||||
|
||||
@@ -127,15 +127,15 @@ case $BOOST_JAM_TOOLSET in
|
||||
fi
|
||||
BOOST_JAM_CC="gcc -DNT"
|
||||
;;
|
||||
|
||||
|
||||
gcc)
|
||||
BOOST_JAM_CC=gcc
|
||||
;;
|
||||
|
||||
|
||||
darwin)
|
||||
BOOST_JAM_CC=cc
|
||||
;;
|
||||
|
||||
|
||||
intel-linux)
|
||||
if test -r /opt/intel/cc/9.0/bin/iccvars.sh ; then
|
||||
BOOST_JAM_TOOLSET_ROOT=/opt/intel/cc/9.0/
|
||||
@@ -164,35 +164,35 @@ case $BOOST_JAM_TOOLSET in
|
||||
fi
|
||||
BOOST_JAM_CC=icc
|
||||
;;
|
||||
|
||||
|
||||
vacpp)
|
||||
BOOST_JAM_CC=xlc
|
||||
;;
|
||||
|
||||
|
||||
como)
|
||||
BOOST_JAM_CC="como --c"
|
||||
;;
|
||||
|
||||
|
||||
kcc)
|
||||
BOOST_JAM_CC=KCC
|
||||
;;
|
||||
|
||||
|
||||
kylix)
|
||||
BOOST_JAM_CC=bc++
|
||||
;;
|
||||
|
||||
|
||||
mipspro)
|
||||
BOOST_JAM_CC=cc
|
||||
;;
|
||||
|
||||
|
||||
pathscale)
|
||||
BOOST_JAM_CC=pathcc
|
||||
;;
|
||||
|
||||
|
||||
pgi)
|
||||
BOOST_JAM_CC=pgcc
|
||||
;;
|
||||
|
||||
|
||||
sun*)
|
||||
if test -z "${BOOST_JAM_TOOLSET_ROOT}" -a -r /opt/SUNWspro/bin/cc ; then
|
||||
BOOST_JAM_TOOLSET_ROOT=/opt/SUNWspro/
|
||||
@@ -203,15 +203,15 @@ case $BOOST_JAM_TOOLSET in
|
||||
fi
|
||||
BOOST_JAM_CC=cc
|
||||
;;
|
||||
|
||||
|
||||
tru64cxx)
|
||||
BOOST_JAM_CC=cc
|
||||
;;
|
||||
|
||||
|
||||
acc)
|
||||
BOOST_JAM_CC="cc -Ae"
|
||||
;;
|
||||
|
||||
|
||||
cc)
|
||||
if test -z "$CC" ; then CC=cc ; fi
|
||||
BOOST_JAM_CC=$CC
|
||||
@@ -219,11 +219,11 @@ case $BOOST_JAM_TOOLSET in
|
||||
BOOST_JAM_OPT_MKJAMBASE="$BOOST_JAM_OPT_MKJAMBASE $CFLAGS $LIBS"
|
||||
BOOST_JAM_OPT_YYACC="$BOOST_JAM_OPT_YYACC $CFLAGS $LIBS"
|
||||
;;
|
||||
|
||||
|
||||
qcc)
|
||||
BOOST_JAM_CC=qcc
|
||||
;;
|
||||
|
||||
|
||||
*)
|
||||
error_exit "Unknown toolset: $BOOST_JAM_TOOLSET"
|
||||
;;
|
||||
@@ -247,7 +247,7 @@ case $BOOST_JAM_TOOLSET in
|
||||
mingw)
|
||||
BJAM_SOURCES="${BJAM_SOURCES} execnt.c filent.c"
|
||||
;;
|
||||
|
||||
|
||||
*)
|
||||
BJAM_SOURCES="${BJAM_SOURCES} execunix.c fileunix.c"
|
||||
;;
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
$ ! Copyright 2002-2003 Rene Rivera, Johan Nilsson.
|
||||
$ ! Distributed under the Boost Software License, Version 1.0.
|
||||
$ ! (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
$ !
|
||||
$ !
|
||||
$ ! bootstrap build script for Jam
|
||||
$ !
|
||||
$ !
|
||||
$ SAY :== WRITE SYS$OUTPUT
|
||||
$ !
|
||||
$ !
|
||||
$ ON WARNING THEN CONTINUE
|
||||
$ !
|
||||
$ !
|
||||
$ IF "" .NES. F$SEARCH("[.bootstrap_vms]*.*")
|
||||
$ THEN
|
||||
$ SAY "Cleaning previous boostrap files..."
|
||||
$ !
|
||||
$ !
|
||||
$ SET FILE/PROTECTION=(S:RWED) [.bootstrap_vms]*.*;*
|
||||
$ DELETE [.bootstrap_vms]*.*;*
|
||||
$ ENDIF
|
||||
$ !
|
||||
$ !
|
||||
$ IF "" .NES. F$SEARCH("bootstrap_vms.dir")
|
||||
$ THEN
|
||||
$ SAY "Removing previous boostrap directory..."
|
||||
$ !
|
||||
$ !
|
||||
$ SET FILE/PROT=(S:RWED) bootstrap_vms.dir
|
||||
$ DELETE bootstrap_vms.dir;
|
||||
$ ENDIF
|
||||
$ !
|
||||
$ !
|
||||
$ SAY "Creating boostrap directory..."
|
||||
$ !
|
||||
$ !
|
||||
$ CREATE/DIR [.bootstrap_vms]
|
||||
$ !
|
||||
$ !
|
||||
$ SAY "Building bootstrap jam..."
|
||||
$ !
|
||||
$ !
|
||||
$ CC_FLAGS = "/DEFINE=VMS /STANDARD=VAXC /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES "
|
||||
$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]builtins.obj builtins.c
|
||||
$ cc 'CC_FLAGS /OBJECT=[.bootstrap_vms]command.obj command.c
|
||||
@@ -95,11 +95,11 @@ $ link -
|
||||
[.bootstrap_vms]subst.obj, -
|
||||
[.bootstrap_vms]timestamp.obj, -
|
||||
[.bootstrap_vms]variable.obj
|
||||
$ !
|
||||
$ !
|
||||
$ SAY "Cleaning any previous build..."
|
||||
$ !
|
||||
$ !
|
||||
$ MCR [.bootstrap_vms]jam0.exe -f build.jam --toolset=vmsdecc clean
|
||||
$ !
|
||||
$ !
|
||||
$ SAY "Building Boost.Jam..."
|
||||
$ !
|
||||
$ !
|
||||
$ MCR [.bootstrap_vms]jam0.exe -f build.jam --toolset=vmsdecc
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* Copyright Vladiir Prus 2003. Distributed under the Boost */
|
||||
/* Copyright Vladimir Prus 2003. Distributed under the Boost */
|
||||
/* Software License, Version 1.0. (See accompanying */
|
||||
/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
|
||||
|
||||
@@ -11,121 +11,131 @@
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
static struct hash* classes = 0;
|
||||
|
||||
static void check_defined(LIST* class_names)
|
||||
static struct hash * classes = 0;
|
||||
|
||||
|
||||
static void check_defined( LIST * class_names )
|
||||
{
|
||||
for (; class_names; class_names = class_names->next) {
|
||||
char** p = &class_names->string;
|
||||
if (!hashcheck(classes, (HASHDATA**)&p)) {
|
||||
printf("Class %s is not defined\n", class_names->string);
|
||||
for ( ; class_names; class_names = class_names->next )
|
||||
{
|
||||
char * * p = &class_names->string;
|
||||
if ( !hashcheck( classes, (HASHDATA * *)&p ) )
|
||||
{
|
||||
printf( "Class %s is not defined\n", class_names->string );
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char* class_module_name(char* declared_name)
|
||||
{
|
||||
string name[1];
|
||||
char* result;
|
||||
|
||||
string_new(name);
|
||||
string_append(name, "class@");
|
||||
string_append(name, declared_name);
|
||||
|
||||
result = newstr(name->value);
|
||||
string_free(name);
|
||||
|
||||
static char * class_module_name( char * declared_name )
|
||||
{
|
||||
string name[ 1 ];
|
||||
char * result;
|
||||
|
||||
string_new( name );
|
||||
string_append( name, "class@" );
|
||||
string_append( name, declared_name );
|
||||
|
||||
result = newstr( name->value );
|
||||
string_free( name );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct import_base_data {
|
||||
char* base_name;
|
||||
module_t* base_module;
|
||||
module_t* class_module;
|
||||
|
||||
struct import_base_data
|
||||
{
|
||||
char * base_name;
|
||||
module_t * base_module;
|
||||
module_t * class_module;
|
||||
};
|
||||
|
||||
static void import_base_rule(void* r_, void* d_)
|
||||
|
||||
static void import_base_rule( void * r_, void * d_ )
|
||||
{
|
||||
RULE* r = (RULE*)r_;
|
||||
RULE* ir1;
|
||||
RULE* ir2;
|
||||
struct import_base_data* d = (struct import_base_data*)d_;
|
||||
string qualified_name[1];
|
||||
int basename_lenght = strlen(d->base_name)+1;
|
||||
RULE * r = (RULE *)r_;
|
||||
RULE * ir1;
|
||||
RULE * ir2;
|
||||
struct import_base_data * d = (struct import_base_data *)d_;
|
||||
string qualified_name[ 1 ];
|
||||
|
||||
string_new(qualified_name);
|
||||
string_append(qualified_name, d->base_name);
|
||||
string_push_back(qualified_name, '.');
|
||||
string_append(qualified_name, r->name);
|
||||
string_new ( qualified_name );
|
||||
string_append ( qualified_name, d->base_name );
|
||||
string_push_back( qualified_name, '.' );
|
||||
string_append ( qualified_name, r->name );
|
||||
|
||||
ir1 = import_rule(r, d->class_module, r->name);
|
||||
ir2 = import_rule(r, d->class_module, qualified_name->value);
|
||||
ir1 = import_rule( r, d->class_module, r->name );
|
||||
ir2 = import_rule( r, d->class_module, qualified_name->value );
|
||||
|
||||
/* Copy 'exported' flag. */
|
||||
ir1->exported = ir2->exported = r->exported;
|
||||
|
||||
/* If we're importing class method, localize it. */
|
||||
if (r->module == d->base_module
|
||||
|| r->module->class_module && r->module->class_module == d->base_module) {
|
||||
ir1->module = ir2->module = d->class_module;
|
||||
}
|
||||
|
||||
string_free(qualified_name);
|
||||
/* If we are importing a class method, localize it. */
|
||||
if ( ( r->module == d->base_module ) || ( r->module->class_module &&
|
||||
( r->module->class_module == d->base_module ) ) )
|
||||
ir1->module = ir2->module = d->class_module;
|
||||
|
||||
string_free( qualified_name );
|
||||
}
|
||||
|
||||
/** For each exported rule 'n', declared in class module for base,
|
||||
imports that rule in 'class' as 'n' and as 'base.n'. Imported
|
||||
rules are localized and marked as exported.
|
||||
*/
|
||||
static void import_base_rules(module_t* class, char* base)
|
||||
|
||||
/*
|
||||
* For each exported rule 'n', declared in class module for base, imports that
|
||||
* rule in 'class' as 'n' and as 'base.n'. Imported rules are localized and
|
||||
* marked as exported.
|
||||
*/
|
||||
|
||||
static void import_base_rules( module_t * class, char * base )
|
||||
{
|
||||
module_t* base_module = bindmodule(class_module_name(base));
|
||||
module_t * base_module = bindmodule( class_module_name( base ) );
|
||||
struct import_base_data d;
|
||||
d.base_name = base;
|
||||
d.base_module = base_module;
|
||||
d.class_module = class;
|
||||
|
||||
if (base_module->rules)
|
||||
hashenumerate(base_module->rules, import_base_rule, &d);
|
||||
if ( base_module->rules )
|
||||
hashenumerate( base_module->rules, import_base_rule, &d );
|
||||
|
||||
import_module( imported_modules(base_module), class );
|
||||
import_module( imported_modules( base_module ), class );
|
||||
}
|
||||
|
||||
char* make_class_module(LIST* xname, LIST* bases, FRAME* frame)
|
||||
|
||||
char * make_class_module( LIST * xname, LIST * bases, FRAME * frame )
|
||||
{
|
||||
char* name = class_module_name(xname->string);
|
||||
char** pp = &xname->string;
|
||||
module_t* class_module = 0;
|
||||
module_t* outer_module = frame->module;
|
||||
char * name = class_module_name( xname->string );
|
||||
char * * pp = &xname->string;
|
||||
module_t * class_module = 0;
|
||||
module_t * outer_module = frame->module;
|
||||
|
||||
if (!classes)
|
||||
classes = hashinit(sizeof(char*), "classes");
|
||||
if ( !classes )
|
||||
classes = hashinit( sizeof( char * ), "classes" );
|
||||
|
||||
|
||||
if (hashcheck(classes, (HASHDATA**)&pp)) {
|
||||
printf("Class %s already defined\n", xname->string);
|
||||
if ( hashcheck( classes, (HASHDATA * *)&pp ) )
|
||||
{
|
||||
printf( "Class %s already defined\n", xname->string );
|
||||
abort();
|
||||
} else {
|
||||
hashenter(classes, (HASHDATA**)&pp);
|
||||
}
|
||||
check_defined(bases);
|
||||
|
||||
class_module = bindmodule(name);
|
||||
else
|
||||
{
|
||||
hashenter( classes, (HASHDATA * *)&pp );
|
||||
}
|
||||
check_defined( bases );
|
||||
|
||||
class_module = bindmodule( name );
|
||||
|
||||
exit_module( outer_module );
|
||||
enter_module( class_module );
|
||||
|
||||
var_set("__name__", xname, VAR_SET);
|
||||
var_set("__bases__", bases, VAR_SET);
|
||||
|
||||
var_set( "__name__", xname, VAR_SET );
|
||||
var_set( "__bases__", bases, VAR_SET );
|
||||
|
||||
exit_module( class_module );
|
||||
enter_module( outer_module );
|
||||
|
||||
for(; bases; bases = bases->next)
|
||||
import_base_rules(class_module, bases->string);
|
||||
|
||||
|
||||
for ( ; bases; bases = bases->next )
|
||||
import_base_rules( class_module, bases->string );
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -14,30 +14,26 @@
|
||||
* command.c - maintain lists of commands
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
#include "jam.h"
|
||||
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "variable.h"
|
||||
# include "rules.h"
|
||||
#include "lists.h"
|
||||
#include "parse.h"
|
||||
#include "variable.h"
|
||||
#include "rules.h"
|
||||
|
||||
#include "command.h"
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
# include "command.h"
|
||||
# include <limits.h>
|
||||
# include <string.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_new( RULE * rule, LIST * targets, LIST * sources, LIST * shell )
|
||||
{
|
||||
CMD *cmd = (CMD *)BJAM_MALLOC( sizeof( CMD ) );
|
||||
/* lift line-length limitation entirely when JAMSHELL is just "%" */
|
||||
CMD * cmd = (CMD *)BJAM_MALLOC( sizeof( CMD ) );
|
||||
/* Lift line-length limitation entirely when JAMSHELL is just "%". */
|
||||
int no_limit = ( shell && !strcmp(shell->string,"%") && !list_next(shell) );
|
||||
int max_line = MAXLINE;
|
||||
int allocated = -1;
|
||||
@@ -53,34 +49,34 @@ cmd_new(
|
||||
|
||||
do
|
||||
{
|
||||
BJAM_FREE(cmd->buf); /* free any buffer from previous iteration */
|
||||
|
||||
cmd->buf = (char*)BJAM_MALLOC_ATOMIC(max_line + 1);
|
||||
|
||||
if (cmd->buf == 0)
|
||||
BJAM_FREE( cmd->buf ); /* free any buffer from previous iteration */
|
||||
|
||||
cmd->buf = (char*)BJAM_MALLOC_ATOMIC( 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( allocated < 0 && max_line < INT_MAX / 2 );
|
||||
while ( ( allocated < 0 ) && ( max_line < INT_MAX / 2 ) );
|
||||
|
||||
if ( !no_limit )
|
||||
{
|
||||
/* Bail if the result won't fit in MAXLINE */
|
||||
char *s = cmd->buf;
|
||||
/* Bail if the result will not fit in MAXLINE. */
|
||||
char * s = cmd->buf;
|
||||
while ( *s )
|
||||
{
|
||||
size_t l = strcspn( s, "\n" );
|
||||
|
||||
|
||||
if ( l > MAXLINE )
|
||||
{
|
||||
/* We don't free targets/sources/shell if bailing. */
|
||||
/* We do not free targets/sources/shell if bailing. */
|
||||
cmd_free( cmd );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
s += l;
|
||||
if ( *s )
|
||||
++s;
|
||||
@@ -90,15 +86,15 @@ cmd_new(
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* cmd_free() - free a CMD
|
||||
*/
|
||||
|
||||
void
|
||||
cmd_free( CMD *cmd )
|
||||
void cmd_free( CMD * cmd )
|
||||
{
|
||||
lol_free( &cmd->args );
|
||||
list_free( cmd->shell );
|
||||
lol_free( &cmd->args );
|
||||
list_free( cmd->shell );
|
||||
BJAM_FREE( cmd->buf );
|
||||
BJAM_FREE( (char *)cmd );
|
||||
BJAM_FREE( (char *)cmd );
|
||||
}
|
||||
|
||||
@@ -12,47 +12,50 @@
|
||||
* 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'.
|
||||
* 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
|
||||
* 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
|
||||
* 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_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
|
||||
* 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 * 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) */
|
||||
CMD * cmd_new
|
||||
(
|
||||
RULE * rule, /* rule (referenced) */
|
||||
LIST * targets, /* $(<) (freed) */
|
||||
LIST * sources, /* $(>) (freed) */
|
||||
LIST * shell /* $(SHELL) (freed) */
|
||||
);
|
||||
|
||||
void cmd_free( CMD *cmd );
|
||||
void cmd_free( CMD * );
|
||||
|
||||
# define cmd_next( c ) ((c)->next)
|
||||
#define cmd_next( c ) ( ( c )->next )
|
||||
|
||||
1152
src/engine/compile.c
1152
src/engine/compile.c
File diff suppressed because it is too large
Load Diff
@@ -50,33 +50,33 @@ regexp* regex_compile( const char* pattern );
|
||||
|
||||
/* 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 */
|
||||
# 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 */
|
||||
# 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 EXPR_NOT 0 /* ! cond */
|
||||
# define EXPR_AND 1 /* cond && cond */
|
||||
# define EXPR_OR 2 /* cond || cond */
|
||||
# define EXPR_NOT 0 /* ! cond */
|
||||
# define EXPR_AND 1 /* cond && cond */
|
||||
# define EXPR_OR 2 /* cond || cond */
|
||||
|
||||
# define EXPR_EXISTS 3 /* arg */
|
||||
# define EXPR_EQUALS 4 /* arg = arg */
|
||||
# define EXPR_NOTEQ 5 /* arg != arg */
|
||||
# define EXPR_LESS 6 /* arg < arg */
|
||||
# define EXPR_LESSEQ 7 /* arg <= arg */
|
||||
# define EXPR_MORE 8 /* arg > arg */
|
||||
# define EXPR_MOREEQ 9 /* arg >= arg */
|
||||
# define EXPR_IN 10 /* arg in arg */
|
||||
# define EXPR_EXISTS 3 /* arg */
|
||||
# define EXPR_EQUALS 4 /* arg = arg */
|
||||
# define EXPR_NOTEQ 5 /* arg != arg */
|
||||
# define EXPR_LESS 6 /* arg < arg */
|
||||
# define EXPR_LESSEQ 7 /* arg <= arg */
|
||||
# define EXPR_MORE 8 /* arg > arg */
|
||||
# define EXPR_MOREEQ 9 /* arg >= arg */
|
||||
# define EXPR_IN 10 /* arg in arg */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,45 +4,47 @@
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
#include "jam.h"
|
||||
|
||||
# include "hash.h"
|
||||
#include "hash.h"
|
||||
|
||||
# include <time.h>
|
||||
# include <assert.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
static profile_frame* profile_stack = 0;
|
||||
static struct hash* profile_hash = 0;
|
||||
static profile_info profile_other = { "[OTHER]", 0, 0, 0, 0, 0 };
|
||||
static profile_info profile_total = { "[TOTAL]", 0, 0, 0, 0, 0 };
|
||||
|
||||
profile_frame* profile_init( char* rulename, profile_frame* frame )
|
||||
static profile_frame * profile_stack = 0;
|
||||
static struct hash * profile_hash = 0;
|
||||
static profile_info profile_other = { "[OTHER]", 0, 0, 0, 0, 0 };
|
||||
static profile_info profile_total = { "[TOTAL]", 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
profile_frame * profile_init( char * rulename, profile_frame * frame )
|
||||
{
|
||||
if ( DEBUG_PROFILE ) profile_enter(rulename,frame);
|
||||
if ( DEBUG_PROFILE ) profile_enter( rulename, frame );
|
||||
return frame;
|
||||
}
|
||||
|
||||
void profile_enter( char* rulename, profile_frame* frame )
|
||||
|
||||
void profile_enter( char * rulename, profile_frame * frame )
|
||||
{
|
||||
if ( DEBUG_PROFILE )
|
||||
{
|
||||
clock_t start = clock();
|
||||
profile_info info, *p = &info;
|
||||
profile_info info;
|
||||
profile_info * p = &info;
|
||||
|
||||
if ( !rulename ) p = &profile_other;
|
||||
|
||||
if ( !profile_hash )
|
||||
{
|
||||
if ( rulename ) profile_hash = hashinit(sizeof(profile_info), "profile");
|
||||
}
|
||||
if ( !profile_hash && rulename )
|
||||
profile_hash = hashinit( sizeof( profile_info ), "profile" );
|
||||
|
||||
info.name = rulename;
|
||||
|
||||
if ( rulename && hashenter( profile_hash, (HASHDATA **)&p ) )
|
||||
if ( rulename && hashenter( profile_hash, (HASHDATA * *)&p ) )
|
||||
p->cumulative = p->net = p->num_entries = p->stack_count = p->memory = 0;
|
||||
|
||||
++(p->num_entries);
|
||||
++(p->stack_count);
|
||||
++p->num_entries;
|
||||
++p->stack_count;
|
||||
|
||||
frame->info = p;
|
||||
|
||||
@@ -59,75 +61,72 @@ void profile_enter( char* rulename, profile_frame* frame )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void profile_memory( long mem )
|
||||
{
|
||||
if ( DEBUG_PROFILE )
|
||||
{
|
||||
if ( profile_stack && profile_stack->info )
|
||||
{
|
||||
profile_stack->info->memory += mem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void profile_exit(profile_frame* frame)
|
||||
|
||||
|
||||
void profile_exit( profile_frame * frame )
|
||||
{
|
||||
if ( DEBUG_PROFILE )
|
||||
{
|
||||
/* cumulative time for this call */
|
||||
/* Cumulative time for this call. */
|
||||
clock_t t = clock() - frame->entry_time - frame->overhead;
|
||||
/* If this rule is already present on the stack, don't add the time for
|
||||
this instance. */
|
||||
if (frame->info->stack_count == 1)
|
||||
* this instance.
|
||||
*/
|
||||
if ( frame->info->stack_count == 1 )
|
||||
frame->info->cumulative += t;
|
||||
/* Net time does not depend on presense of the same rule in call stack. */
|
||||
/* Net time does not depend on presense of the same rule in call stack.
|
||||
*/
|
||||
frame->info->net += t - frame->subrules;
|
||||
|
||||
if (frame->caller)
|
||||
if ( frame->caller )
|
||||
{
|
||||
/* caller's cumulative time must account for this overhead */
|
||||
/* Caller's cumulative time must account for this overhead. */
|
||||
frame->caller->overhead += frame->overhead;
|
||||
frame->caller->subrules += t;
|
||||
}
|
||||
/* pop this stack frame */
|
||||
/* Pop this stack frame. */
|
||||
--frame->info->stack_count;
|
||||
profile_stack = frame->caller;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_profile_entry(void* p_, void* ignored)
|
||||
|
||||
static void dump_profile_entry( void * p_, void * ignored )
|
||||
{
|
||||
profile_info* p = (profile_info*)p_;
|
||||
unsigned long mem_each = (p->memory/(p->num_entries ? p->num_entries : 1));
|
||||
profile_info * p = (profile_info *)p_;
|
||||
unsigned long mem_each = ( p->memory / ( p->num_entries ? p->num_entries : 1 ) );
|
||||
double cumulative = p->cumulative;
|
||||
double net = p->net;
|
||||
double q = p->net;
|
||||
q /= (p->num_entries ? p->num_entries : 1);
|
||||
q /= ( p->num_entries ? p->num_entries : 1 );
|
||||
cumulative /= CLOCKS_PER_SEC;
|
||||
net /= CLOCKS_PER_SEC;
|
||||
q /= CLOCKS_PER_SEC;
|
||||
if (!ignored)
|
||||
if ( !ignored )
|
||||
{
|
||||
profile_total.cumulative += p->net;
|
||||
profile_total.memory += p->memory;
|
||||
}
|
||||
printf("%10d %12.6f %12.6f %12.8f %10d %10d %s\n",
|
||||
p->num_entries,
|
||||
cumulative,net,q,
|
||||
p->memory, mem_each,
|
||||
p->name);
|
||||
printf( "%10ld %12.6f %12.6f %12.8f %10ld %10ld %s\n", p->num_entries,
|
||||
cumulative, net, q, p->memory, mem_each, p->name );
|
||||
}
|
||||
|
||||
|
||||
void profile_dump()
|
||||
{
|
||||
if ( profile_hash )
|
||||
{
|
||||
printf("%10s %12s %12s %12s %10s %10s %s\n",
|
||||
"--count--", "--gross--", "--net--", "--each--",
|
||||
"--mem--", "--each--",
|
||||
"--name--");
|
||||
printf( "%10s %12s %12s %12s %10s %10s %s\n", "--count--", "--gross--",
|
||||
"--net--", "--each--", "--mem--", "--each--", "--name--" );
|
||||
hashenumerate( profile_hash, dump_profile_entry, 0 );
|
||||
dump_profile_entry(&profile_other,0);
|
||||
dump_profile_entry(&profile_total,(void*)1);
|
||||
dump_profile_entry( &profile_other, 0 );
|
||||
dump_profile_entry( &profile_total, (void *)1 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
#ifndef BJAM_DEBUG_H
|
||||
#define BJAM_DEBUG_H
|
||||
|
||||
# include "jam.h"
|
||||
# include <time.h>
|
||||
#include "jam.h"
|
||||
#include <time.h>
|
||||
|
||||
|
||||
struct profile_info
|
||||
{
|
||||
@@ -41,13 +42,13 @@ struct profile_frame
|
||||
};
|
||||
typedef struct profile_frame profile_frame;
|
||||
|
||||
profile_frame * profile_init( char* rulename, profile_frame* frame );
|
||||
void profile_enter( char* rulename, profile_frame* frame );
|
||||
profile_frame * profile_init( char * rulename, profile_frame * frame );
|
||||
void profile_enter( char* rulename, profile_frame * frame );
|
||||
void profile_memory( long mem );
|
||||
void profile_exit(profile_frame* frame);
|
||||
void profile_exit( profile_frame * frame );
|
||||
void profile_dump();
|
||||
|
||||
#define PROFILE_ENTER(scope) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init(#scope,&PROF_ ## scope)
|
||||
#define PROFILE_EXIT(scope) profile_exit(PROF_ ## scope ## _p)
|
||||
#define PROFILE_ENTER( scope ) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init( #scope, &PROF_ ## scope )
|
||||
#define PROFILE_EXIT( scope ) profile_exit( PROF_ ## scope ## _p )
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* execcmd.h - execute a shell script
|
||||
* execcmd.h - execute a shell script.
|
||||
*
|
||||
* Defines the interface to be implemented in platform specific implementation
|
||||
* modules.
|
||||
*
|
||||
* 05/04/94 (seiwald) - async multiprocess interface
|
||||
*/
|
||||
@@ -23,18 +26,20 @@ typedef struct timing_info
|
||||
time_t end;
|
||||
} timing_info;
|
||||
|
||||
void execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status, timing_info*, char *, char * ),
|
||||
void *closure,
|
||||
LIST *shell,
|
||||
char *action,
|
||||
char *target);
|
||||
void exec_cmd
|
||||
(
|
||||
char * string,
|
||||
void (* func)( void * closure, int status, timing_info *, char *, char * ),
|
||||
void * closure,
|
||||
LIST * shell,
|
||||
char * action,
|
||||
char * target
|
||||
);
|
||||
|
||||
int execwait();
|
||||
int exec_wait();
|
||||
|
||||
# define EXEC_CMD_OK 0
|
||||
# define EXEC_CMD_FAIL 1
|
||||
# define EXEC_CMD_INTR 2
|
||||
#define EXEC_CMD_OK 0
|
||||
#define EXEC_CMD_FAIL 1
|
||||
#define EXEC_CMD_INTR 2
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "execcmd.h"
|
||||
# include <errno.h>
|
||||
#include "jam.h"
|
||||
#include "lists.h"
|
||||
#include "execcmd.h"
|
||||
#include <errno.h>
|
||||
|
||||
# ifdef OS_MAC
|
||||
#ifdef OS_MAC
|
||||
|
||||
/*
|
||||
* execunix.c - execute a shell script on UNIX
|
||||
@@ -17,11 +17,11 @@
|
||||
* If $(JAMSHELL) is defined, uses that to formulate execvp().
|
||||
* The default is:
|
||||
*
|
||||
* /bin/sh -c %
|
||||
* /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
|
||||
* 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.
|
||||
@@ -29,41 +29,41 @@
|
||||
* 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
|
||||
* exec_cmd() - launch an async command execution.
|
||||
* exec_wait() - wait and drive at most one execution completion.
|
||||
*
|
||||
* Internal routines:
|
||||
* onintr() - bump intr to note command interruption
|
||||
* 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
|
||||
* exec_cmd() - launch an async command execution.
|
||||
*/
|
||||
|
||||
void
|
||||
execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status, timing_info*, char *, char * ),
|
||||
void *closure,
|
||||
LIST *shell )
|
||||
void exec_cmd
|
||||
(
|
||||
char * string,
|
||||
void (* func)( void * closure, int status, timing_info *, char *, char * ),
|
||||
void * closure,
|
||||
LIST * shell
|
||||
)
|
||||
{
|
||||
|
||||
printf( "%s", string );
|
||||
(*func)( closure, EXEC_CMD_OK );
|
||||
printf( "%s", string );
|
||||
(*func)( closure, EXEC_CMD_OK );
|
||||
}
|
||||
|
||||
/*
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
* exec_wait() - wait and drive at most one execution completion.
|
||||
*/
|
||||
|
||||
int
|
||||
execwait()
|
||||
int exec_wait()
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# endif /* OS_MAC */
|
||||
#endif /* OS_MAC */
|
||||
|
||||
1302
src/engine/execnt.c
1302
src/engine/execnt.c
File diff suppressed because it is too large
Load Diff
@@ -5,29 +5,35 @@
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "execcmd.h"
|
||||
# include "output.h"
|
||||
# include <errno.h>
|
||||
# include <signal.h>
|
||||
# include <stdio.h>
|
||||
# include <time.h>
|
||||
# include <unistd.h> /* needed for vfork(), _exit() prototypes */
|
||||
# include <sys/resource.h>
|
||||
# include <sys/times.h>
|
||||
# include <sys/wait.h>
|
||||
#include "jam.h"
|
||||
#include "lists.h"
|
||||
#include "execcmd.h"
|
||||
#include "output.h"
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h> /* needed for vfork(), _exit() prototypes */
|
||||
#include <sys/resource.h>
|
||||
#include <sys/times.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if defined(sun) || defined(__sun) || defined(linux)
|
||||
#include <wait.h>
|
||||
#include <wait.h>
|
||||
#endif
|
||||
|
||||
# ifdef USE_EXECUNIX
|
||||
# include <sys/times.h>
|
||||
#ifdef USE_EXECUNIX
|
||||
|
||||
#include <sys/times.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define NO_VFORK
|
||||
#endif
|
||||
|
||||
#ifdef NO_VFORK
|
||||
#define vfork() fork()
|
||||
#endif
|
||||
|
||||
# ifdef NO_VFORK
|
||||
# define vfork() fork()
|
||||
# endif
|
||||
|
||||
/*
|
||||
* execunix.c - execute a shell script on UNIX/WinNT/OS2/AmigaOS
|
||||
@@ -35,24 +41,23 @@
|
||||
* 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 ]
|
||||
* /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.
|
||||
* In $(JAMSHELL), % expands to the command string and ! expands to the slot
|
||||
* number (starting at 1) for multiprocess (-j) invocations. If $(JAMSHELL) does
|
||||
* not 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!
|
||||
* Do not just set JAMSHELL to /bin/sh or cmd.exe - it will not work!
|
||||
*
|
||||
* External routines:
|
||||
* execcmd() - launch an async command execution
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
* exec_cmd() - launch an async command execution.
|
||||
* exec_wait() - wait and drive at most one execution completion.
|
||||
*
|
||||
* Internal routines:
|
||||
* onintr() - bump intr to note command interruption
|
||||
* onintr() - bump intr to note command interruption.
|
||||
*
|
||||
* 04/08/94 (seiwald) - Coherent/386 support added.
|
||||
* 05/04/94 (seiwald) - async multiprocess interface
|
||||
@@ -72,7 +77,7 @@ static struct tms old_time;
|
||||
|
||||
static struct
|
||||
{
|
||||
int pid; /* on win32, a real process handle */
|
||||
int pid; /* on win32, a real process handle */
|
||||
int fd[2]; /* file descriptors for stdout and stderr */
|
||||
FILE *stream[2]; /* child's stdout (0) and stderr (1) file stream */
|
||||
clock_t start_time; /* start time of child process */
|
||||
@@ -92,446 +97,466 @@ static struct
|
||||
* onintr() - bump intr to note command interruption
|
||||
*/
|
||||
|
||||
void
|
||||
onintr( int disp )
|
||||
void onintr( int disp )
|
||||
{
|
||||
intr++;
|
||||
printf( "...interrupted\n" );
|
||||
++intr;
|
||||
printf( "...interrupted\n" );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* execcmd() - launch an async command execution
|
||||
* exec_cmd() - launch an async command execution.
|
||||
*/
|
||||
|
||||
void
|
||||
execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status, timing_info*, char *, char * ),
|
||||
void *closure,
|
||||
LIST *shell,
|
||||
char *action,
|
||||
char *target )
|
||||
void exec_cmd
|
||||
(
|
||||
char * string,
|
||||
void (*func)( void *closure, int status, timing_info*, char *, char * ),
|
||||
void * closure,
|
||||
LIST * shell,
|
||||
char * action,
|
||||
char * target
|
||||
)
|
||||
{
|
||||
static int initialized = 0;
|
||||
int out[2], err[2];
|
||||
int slot, len;
|
||||
char *argv[ MAXARGC + 1 ]; /* +1 for NULL */
|
||||
static int initialized = 0;
|
||||
int out[2];
|
||||
int err[2];
|
||||
int slot;
|
||||
int len;
|
||||
char * argv[ MAXARGC + 1 ]; /* +1 for NULL */
|
||||
|
||||
/* Find a slot in the running commands table for this one. */
|
||||
/* Find a slot in the running commands table for this one. */
|
||||
for ( slot = 0; slot < MAXJOBS; ++slot )
|
||||
if ( !cmdtab[ slot ].pid )
|
||||
break;
|
||||
|
||||
for( slot = 0; slot < MAXJOBS; slot++ )
|
||||
if( !cmdtab[ slot ].pid )
|
||||
break;
|
||||
if ( slot == MAXJOBS )
|
||||
{
|
||||
printf( "no slots for child!\n" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
if( slot == MAXJOBS )
|
||||
{
|
||||
printf( "no slots for child!\n" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
/* 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;
|
||||
|
||||
/* Forumulate argv */
|
||||
/* If shell was defined, be prepared for % and ! subs. */
|
||||
/* Otherwise, use stock /bin/sh (on unix) or cmd.exe (on NT). */
|
||||
sprintf( jobno, "%d", slot + 1 );
|
||||
|
||||
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
|
||||
{
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = "-c";
|
||||
argv[2] = string;
|
||||
argv[3] = 0;
|
||||
}
|
||||
|
||||
/* increment jobs running */
|
||||
++cmdsrunning;
|
||||
|
||||
/* save off actual command string */
|
||||
cmdtab[ slot ].command = BJAM_MALLOC_ATOMIC(strlen(string)+1);
|
||||
strcpy(cmdtab[slot].command, string);
|
||||
|
||||
/* initialize only once */
|
||||
if ( ! initialized ) {
|
||||
times(&old_time);
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
/* create pipe from child to parent */
|
||||
|
||||
if (pipe(out) < 0)
|
||||
exit(EXITBAD);
|
||||
|
||||
fcntl(out[0], F_SETFL, O_NONBLOCK);
|
||||
fcntl(out[1], F_SETFL, O_NONBLOCK);
|
||||
|
||||
if (pipe(err) < 0)
|
||||
exit(EXITBAD);
|
||||
|
||||
fcntl(err[0], F_SETFL, O_NONBLOCK);
|
||||
fcntl(err[1], F_SETFL, O_NONBLOCK);
|
||||
|
||||
/* Start the command */
|
||||
|
||||
cmdtab[ slot ].start_dt = time(0);
|
||||
|
||||
if (0 < globs.timeout) {
|
||||
/*
|
||||
* handle hung processes by manually tracking elapsed
|
||||
* time and signal process when time limit expires
|
||||
*/
|
||||
struct tms buf;
|
||||
cmdtab[ slot ].start_time = times(&buf);
|
||||
|
||||
/* make a global, only do this once */
|
||||
if (tps == 0) tps = sysconf(_SC_CLK_TCK);
|
||||
}
|
||||
|
||||
if ((cmdtab[slot].pid = vfork()) == 0)
|
||||
{
|
||||
close(out[0]);
|
||||
close(err[0]);
|
||||
|
||||
dup2(out[1], STDOUT_FILENO);
|
||||
|
||||
if (globs.pipe_action == 0)
|
||||
for ( i = 0; shell && i < MAXARGC; ++i, shell = list_next( shell ) )
|
||||
{
|
||||
switch ( shell->string[0] )
|
||||
{
|
||||
dup2(out[1], STDERR_FILENO);
|
||||
close(err[1]);
|
||||
case '%': argv[ i ] = string; ++gotpercent; break;
|
||||
case '!': argv[ i ] = jobno; break;
|
||||
default : argv[ i ] = shell->string;
|
||||
}
|
||||
else
|
||||
dup2(err[1], STDERR_FILENO);
|
||||
if ( DEBUG_EXECCMD )
|
||||
printf( "argv[%d] = '%s'\n", i, argv[ i ] );
|
||||
}
|
||||
|
||||
/* Make this process a process group leader
|
||||
* so that when we kill it, all child
|
||||
* processes of this process are terminated
|
||||
* as well.
|
||||
*
|
||||
* we use killpg(pid, SIGKILL) to kill the
|
||||
* process group leader and all its children.
|
||||
*/
|
||||
if (0 < globs.timeout)
|
||||
{
|
||||
struct rlimit r_limit;
|
||||
r_limit.rlim_cur = globs.timeout;
|
||||
r_limit.rlim_max = globs.timeout;
|
||||
setrlimit(RLIMIT_CPU, &r_limit);
|
||||
}
|
||||
setpgid(cmdtab[slot].pid, cmdtab[slot].pid);
|
||||
if ( !gotpercent )
|
||||
argv[ i++ ] = string;
|
||||
|
||||
execvp( argv[0], argv );
|
||||
_exit(127);
|
||||
}
|
||||
else if( cmdtab[slot].pid == -1 )
|
||||
{
|
||||
perror( "vfork" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
argv[ i ] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
argv[ 0 ] = "/bin/sh";
|
||||
argv[ 1 ] = "-c";
|
||||
argv[ 2 ] = string;
|
||||
argv[ 3 ] = 0;
|
||||
}
|
||||
|
||||
/* close write end of pipes */
|
||||
close(out[1]);
|
||||
close(err[1]);
|
||||
/* Increment jobs running. */
|
||||
++cmdsrunning;
|
||||
|
||||
/* child writes stdout to out[1], parent reads from out[0] */
|
||||
cmdtab[slot].fd[OUT] = out[0];
|
||||
cmdtab[slot].stream[OUT] = fdopen(cmdtab[slot].fd[OUT], "rb");
|
||||
if (cmdtab[slot].stream[OUT] == NULL) {
|
||||
/* Save off actual command string. */
|
||||
cmdtab[ slot ].command = BJAM_MALLOC_ATOMIC( strlen( string ) + 1 );
|
||||
strcpy( cmdtab[ slot ].command, string );
|
||||
|
||||
/* Initialize only once. */
|
||||
if ( !initialized )
|
||||
{
|
||||
times( &old_time );
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
/* Create pipes from child to parent. */
|
||||
{
|
||||
if ( pipe( out ) < 0 )
|
||||
exit( EXITBAD );
|
||||
fcntl( out[0], F_SETFL, O_NONBLOCK );
|
||||
fcntl( out[1], F_SETFL, O_NONBLOCK );
|
||||
|
||||
if ( pipe( err ) < 0 )
|
||||
exit( EXITBAD );
|
||||
fcntl( err[0], F_SETFL, O_NONBLOCK );
|
||||
fcntl( err[1], F_SETFL, O_NONBLOCK );
|
||||
}
|
||||
|
||||
/* Start the command */
|
||||
|
||||
cmdtab[ slot ].start_dt = time(0);
|
||||
|
||||
if ( 0 < globs.timeout )
|
||||
{
|
||||
/*
|
||||
* Handle hung processes by manually tracking elapsed time and signal
|
||||
* process when time limit expires.
|
||||
*/
|
||||
struct tms buf;
|
||||
cmdtab[ slot ].start_time = times( &buf );
|
||||
|
||||
/* Make a global, only do this once. */
|
||||
if ( tps == 0 ) tps = sysconf( _SC_CLK_TCK );
|
||||
}
|
||||
|
||||
if ( ( cmdtab[ slot ].pid = vfork() ) == 0 )
|
||||
{
|
||||
int pid = getpid();
|
||||
|
||||
close( out[0] );
|
||||
close( err[0] );
|
||||
|
||||
dup2( out[1], STDOUT_FILENO );
|
||||
|
||||
if ( globs.pipe_action == 0 )
|
||||
{
|
||||
dup2( out[1], STDERR_FILENO );
|
||||
close( err[1] );
|
||||
}
|
||||
else
|
||||
dup2( err[1], STDERR_FILENO );
|
||||
|
||||
/* Make this process a process group leader so that when we kill it, all
|
||||
* child processes of this process are terminated as well. We use
|
||||
* killpg(pid, SIGKILL) to kill the process group leader and all its
|
||||
* children.
|
||||
*/
|
||||
if ( 0 < globs.timeout )
|
||||
{
|
||||
struct rlimit r_limit;
|
||||
r_limit.rlim_cur = globs.timeout;
|
||||
r_limit.rlim_max = globs.timeout;
|
||||
setrlimit( RLIMIT_CPU, &r_limit );
|
||||
}
|
||||
setpgid( pid,pid );
|
||||
execvp( argv[0], argv );
|
||||
perror( "execvp" );
|
||||
_exit( 127 );
|
||||
}
|
||||
else if ( cmdtab[ slot ].pid == -1 )
|
||||
{
|
||||
perror( "vfork" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
setpgid( cmdtab[ slot ].pid, cmdtab[ slot ].pid );
|
||||
|
||||
/* close write end of pipes */
|
||||
close( out[1] );
|
||||
close( err[1] );
|
||||
|
||||
/* child writes stdout to out[1], parent reads from out[0] */
|
||||
cmdtab[ slot ].fd[ OUT ] = out[0];
|
||||
cmdtab[ slot ].stream[ OUT ] = fdopen( cmdtab[ slot ].fd[ OUT ], "rb" );
|
||||
if ( cmdtab[ slot ].stream[ OUT ] == NULL )
|
||||
{
|
||||
perror( "fdopen" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
|
||||
/* child writes stderr to err[1], parent reads from err[0] */
|
||||
if (globs.pipe_action == 0)
|
||||
{
|
||||
close(err[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdtab[ slot ].fd[ ERR ] = err[0];
|
||||
cmdtab[ slot ].stream[ ERR ] = fdopen( cmdtab[ slot ].fd[ ERR ], "rb" );
|
||||
if ( cmdtab[ slot ].stream[ ERR ] == NULL )
|
||||
{
|
||||
perror( "fdopen" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
}
|
||||
|
||||
/* child writes stderr to err[1], parent reads from err[0] */
|
||||
if (globs.pipe_action == 0)
|
||||
/* Ensure enough room for rule and target name. */
|
||||
if ( action && target )
|
||||
{
|
||||
len = strlen( action ) + 1;
|
||||
if ( cmdtab[ slot ].action_length < len )
|
||||
{
|
||||
close(err[0]);
|
||||
BJAM_FREE( cmdtab[ slot ].action );
|
||||
cmdtab[ slot ].action = BJAM_MALLOC_ATOMIC( len );
|
||||
cmdtab[ slot ].action_length = len;
|
||||
}
|
||||
else
|
||||
strcpy( cmdtab[ slot ].action, action );
|
||||
len = strlen( target ) + 1;
|
||||
if ( cmdtab[ slot ].target_length < len )
|
||||
{
|
||||
cmdtab[slot].fd[ERR] = err[0];
|
||||
cmdtab[slot].stream[ERR] = fdopen(cmdtab[slot].fd[ERR], "rb");
|
||||
if (cmdtab[slot].stream[ERR] == NULL) {
|
||||
perror( "fdopen" );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
BJAM_FREE( cmdtab[ slot ].target );
|
||||
cmdtab[ slot ].target = BJAM_MALLOC_ATOMIC( len );
|
||||
cmdtab[ slot ].target_length = len;
|
||||
}
|
||||
strcpy( cmdtab[ slot ].target, target );
|
||||
}
|
||||
else
|
||||
{
|
||||
BJAM_FREE( cmdtab[ slot ].action );
|
||||
BJAM_FREE( cmdtab[ slot ].target );
|
||||
cmdtab[ slot ].action = 0;
|
||||
cmdtab[ slot ].target = 0;
|
||||
cmdtab[ slot ].action_length = 0;
|
||||
cmdtab[ slot ].target_length = 0;
|
||||
}
|
||||
|
||||
/* ensure enough room for rule and target name */
|
||||
/* Save the operation for exec_wait() to find. */
|
||||
cmdtab[ slot ].func = func;
|
||||
cmdtab[ slot ].closure = closure;
|
||||
|
||||
if (action && target)
|
||||
{
|
||||
len = strlen(action) + 1;
|
||||
if (cmdtab[slot].action_length < len)
|
||||
{
|
||||
BJAM_FREE(cmdtab[ slot ].action);
|
||||
cmdtab[ slot ].action = BJAM_MALLOC_ATOMIC(len);
|
||||
cmdtab[ slot ].action_length = len;
|
||||
}
|
||||
strcpy(cmdtab[ slot ].action, action);
|
||||
len = strlen(target) + 1;
|
||||
if (cmdtab[slot].target_length < len)
|
||||
{
|
||||
BJAM_FREE(cmdtab[ slot ].target);
|
||||
cmdtab[ slot ].target = BJAM_MALLOC_ATOMIC(len);
|
||||
cmdtab[ slot ].target_length = len;
|
||||
}
|
||||
strcpy(cmdtab[ slot ].target, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
BJAM_FREE(cmdtab[ slot ].action);
|
||||
BJAM_FREE(cmdtab[ slot ].target);
|
||||
cmdtab[ slot ].action = 0;
|
||||
cmdtab[ slot ].target = 0;
|
||||
cmdtab[ slot ].action_length = 0;
|
||||
cmdtab[ slot ].target_length = 0;
|
||||
}
|
||||
|
||||
/* Save the operation for execwait() to find. */
|
||||
|
||||
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;
|
||||
/* Wait until we are under the limit of concurrent commands. Do not trust
|
||||
* globs.jobs alone.
|
||||
*/
|
||||
while ( ( cmdsrunning >= MAXJOBS ) || ( cmdsrunning >= globs.jobs ) )
|
||||
if ( !exec_wait() )
|
||||
break;
|
||||
}
|
||||
|
||||
/* returns 1 if file is closed, 0 if descriptor is still live
|
||||
|
||||
/* Returns 1 if file is closed, 0 if descriptor is still live.
|
||||
*
|
||||
* i is index into cmdtab
|
||||
*
|
||||
* s (stream) indexes
|
||||
*
|
||||
* cmdtab[i].stream[s]
|
||||
* cmdtab[i].buffer[s] and
|
||||
* cmdtab[i].fd[s]
|
||||
* s (stream) indexes:
|
||||
* - cmdtab[ i ].stream[ s ]
|
||||
* - cmdtab[ i ].buffer[ s ]
|
||||
* - cmdtab[ i ].fd [ s ]
|
||||
*/
|
||||
|
||||
int read_descriptor(int i, int s)
|
||||
int read_descriptor( int i, int s )
|
||||
{
|
||||
int ret, len;
|
||||
int ret;
|
||||
int len;
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
while (0 < (ret = fread(buffer, sizeof(char), BUFSIZ-1, cmdtab[i].stream[s])))
|
||||
while ( 0 < ( ret = fread( buffer, sizeof(char), BUFSIZ-1, cmdtab[ i ].stream[ s ] ) ) )
|
||||
{
|
||||
buffer[ret] = 0;
|
||||
if (!cmdtab[i].buffer[s])
|
||||
if ( !cmdtab[ i ].buffer[ s ] )
|
||||
{
|
||||
/* never been allocated */
|
||||
cmdtab[i].buffer[s] = (char*)BJAM_MALLOC_ATOMIC(ret+1);
|
||||
memcpy(cmdtab[i].buffer[s], buffer, ret+1);
|
||||
/* Never been allocated. */
|
||||
cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( ret + 1 );
|
||||
memcpy( cmdtab[ i ].buffer[ s ], buffer, ret + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* previously allocated */
|
||||
char *tmp = cmdtab[i].buffer[s];
|
||||
len = strlen(tmp);
|
||||
cmdtab[i].buffer[s] = (char*)BJAM_MALLOC_ATOMIC(len+ret+1);
|
||||
memcpy(cmdtab[i].buffer[s], tmp, len);
|
||||
memcpy(cmdtab[i].buffer[s]+len, buffer, ret+1);
|
||||
BJAM_FREE(tmp);
|
||||
/* Previously allocated. */
|
||||
char * tmp = cmdtab[ i ].buffer[ s ];
|
||||
len = strlen( tmp );
|
||||
cmdtab[ i ].buffer[ s ] = (char*)BJAM_MALLOC_ATOMIC( len + ret + 1 );
|
||||
memcpy( cmdtab[ i ].buffer[ s ], tmp, len );
|
||||
memcpy( cmdtab[ i ].buffer[ s ] + len, buffer, ret + 1 );
|
||||
BJAM_FREE( tmp );
|
||||
}
|
||||
}
|
||||
|
||||
return feof(cmdtab[i].stream[s]);
|
||||
return feof(cmdtab[ i ].stream[ s ]);
|
||||
}
|
||||
|
||||
void close_streams(int i, int s)
|
||||
|
||||
void close_streams( int i, int s )
|
||||
{
|
||||
/* close the stream and pipe descriptor */
|
||||
fclose(cmdtab[i].stream[s]);
|
||||
cmdtab[i].stream[s] = 0;
|
||||
|
||||
close(cmdtab[i].fd[s]);
|
||||
cmdtab[i].fd[s] = 0;
|
||||
/* Close the stream and pipe descriptor. */
|
||||
fclose(cmdtab[ i ].stream[ s ]);
|
||||
cmdtab[ i ].stream[ s ] = 0;
|
||||
|
||||
close(cmdtab[ i ].fd[ s ]);
|
||||
cmdtab[ i ].fd[ s ] = 0;
|
||||
}
|
||||
|
||||
void populate_file_descriptors(int *fmax, fd_set *fds)
|
||||
|
||||
void populate_file_descriptors( int * fmax, fd_set * fds)
|
||||
{
|
||||
int i, fd_max = 0;
|
||||
struct tms buf;
|
||||
clock_t current = times(&buf);
|
||||
clock_t current = times( &buf );
|
||||
select_timeout = globs.timeout;
|
||||
|
||||
/* compute max read file descriptor for use in select */
|
||||
/* Compute max read file descriptor for use in select. */
|
||||
FD_ZERO(fds);
|
||||
for (i=0; i<globs.jobs; ++i)
|
||||
for ( i = 0; i < globs.jobs; ++i )
|
||||
{
|
||||
if (0 < cmdtab[i].fd[OUT])
|
||||
if ( 0 < cmdtab[ i ].fd[ OUT ] )
|
||||
{
|
||||
fd_max = fd_max < cmdtab[i].fd[OUT] ? cmdtab[i].fd[OUT] : fd_max;
|
||||
FD_SET(cmdtab[i].fd[OUT], fds);
|
||||
fd_max = fd_max < cmdtab[ i ].fd[ OUT ] ? cmdtab[ i ].fd[ OUT ] : fd_max;
|
||||
FD_SET(cmdtab[ i ].fd[ OUT ], fds);
|
||||
}
|
||||
if (globs.pipe_action != 0)
|
||||
if ( globs.pipe_action != 0 )
|
||||
{
|
||||
if (0 < cmdtab[i].fd[ERR])
|
||||
if (0 < cmdtab[ i ].fd[ ERR ])
|
||||
{
|
||||
fd_max = fd_max < cmdtab[i].fd[ERR] ? cmdtab[i].fd[ERR] : fd_max;
|
||||
FD_SET(cmdtab[i].fd[ERR], fds);
|
||||
fd_max = fd_max < cmdtab[ i ].fd[ ERR ] ? cmdtab[ i ].fd[ ERR ] : fd_max;
|
||||
FD_SET(cmdtab[ i ].fd[ ERR ], fds);
|
||||
}
|
||||
}
|
||||
|
||||
if (globs.timeout && cmdtab[i].pid) {
|
||||
clock_t consumed = (current - cmdtab[i].start_time) / tps;
|
||||
if (globs.timeout && cmdtab[ i ].pid) {
|
||||
clock_t consumed = (current - cmdtab[ i ].start_time) / tps;
|
||||
clock_t process_timesout = globs.timeout - consumed;
|
||||
if (0 < process_timesout && process_timesout < select_timeout) {
|
||||
select_timeout = process_timesout;
|
||||
}
|
||||
if (globs.timeout <= consumed) {
|
||||
killpg(cmdtab[i].pid, SIGKILL);
|
||||
cmdtab[i].exit_reason = EXIT_TIMEOUT;
|
||||
if ( globs.timeout <= consumed )
|
||||
{
|
||||
killpg( cmdtab[ i ].pid, SIGKILL );
|
||||
cmdtab[ i ].exit_reason = EXIT_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
*fmax = fd_max;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* execwait() - wait and drive at most one execution completion
|
||||
* exec_wait() - wait and drive at most one execution completion.
|
||||
*/
|
||||
|
||||
int
|
||||
execwait()
|
||||
int exec_wait()
|
||||
{
|
||||
int i, ret, fd_max;
|
||||
int pid, status, finished;
|
||||
int rstat;
|
||||
int i;
|
||||
int ret;
|
||||
int fd_max;
|
||||
int pid;
|
||||
int status;
|
||||
int finished;
|
||||
int rstat;
|
||||
timing_info time_info;
|
||||
fd_set fds;
|
||||
struct tms new_time;
|
||||
fd_set fds;
|
||||
struct tms new_time;
|
||||
|
||||
/* Handle naive make1() which doesn't know if cmds are running. */
|
||||
|
||||
if( !cmdsrunning )
|
||||
/* Handle naive make1() which does not know if commands are running. */
|
||||
if ( !cmdsrunning )
|
||||
return 0;
|
||||
|
||||
/* process children that signaled */
|
||||
/* Process children that signaled. */
|
||||
finished = 0;
|
||||
while (!finished && cmdsrunning)
|
||||
while ( !finished && cmdsrunning )
|
||||
{
|
||||
/* compute max read file descriptor for use in select */
|
||||
populate_file_descriptors(&fd_max, &fds);
|
||||
/* Compute max read file descriptor for use in select(). */
|
||||
populate_file_descriptors( &fd_max, &fds );
|
||||
|
||||
if (0 < globs.timeout) {
|
||||
/* force select to timeout so we can terminate expired processes */
|
||||
if ( 0 < globs.timeout )
|
||||
{
|
||||
/* Force select() to timeout so we can terminate expired processes.
|
||||
*/
|
||||
tv.tv_sec = select_timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
/* select will wait until: io on a descriptor, a signal, or we time out */
|
||||
ret = select(fd_max+1, &fds, 0, 0, &tv);
|
||||
/* select() will wait until: i/o on a descriptor, a signal, or we
|
||||
* time out.
|
||||
*/
|
||||
ret = select( fd_max + 1, &fds, 0, 0, &tv );
|
||||
}
|
||||
else {
|
||||
/* select will wait until io on a descriptor or a signal */
|
||||
ret = select(fd_max+1, &fds, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (0 < ret)
|
||||
else
|
||||
{
|
||||
for (i=0; i<globs.jobs; ++i)
|
||||
/* select() will wait until i/o on a descriptor or a signal. */
|
||||
ret = select( fd_max + 1, &fds, 0, 0, 0 );
|
||||
}
|
||||
|
||||
if ( 0 < ret )
|
||||
{
|
||||
for ( i = 0; i < globs.jobs; ++i )
|
||||
{
|
||||
int out = 0, err = 0;
|
||||
if (FD_ISSET(cmdtab[i].fd[OUT], &fds))
|
||||
out = read_descriptor(i, OUT);
|
||||
int out = 0;
|
||||
int err = 0;
|
||||
if ( FD_ISSET( cmdtab[ i ].fd[ OUT ], &fds ) )
|
||||
out = read_descriptor( i, OUT );
|
||||
|
||||
if (FD_ISSET(cmdtab[i].fd[ERR], &fds))
|
||||
err = read_descriptor(i, ERR);
|
||||
if ( ( globs.pipe_action != 0 ) &&
|
||||
( FD_ISSET( cmdtab[ i ].fd[ ERR ], &fds ) ) )
|
||||
err = read_descriptor( i, ERR );
|
||||
|
||||
/* if feof on either descriptor, then we're done */
|
||||
if (out || err)
|
||||
/* If feof on either descriptor, then we are done. */
|
||||
if ( out || err )
|
||||
{
|
||||
/* close the stream and pipe descriptors */
|
||||
close_streams(i, OUT);
|
||||
if (globs.pipe_action != 0)
|
||||
close_streams(i, ERR);
|
||||
/* Close the stream and pipe descriptors. */
|
||||
close_streams( i, OUT );
|
||||
if ( globs.pipe_action != 0 )
|
||||
close_streams( i, ERR );
|
||||
|
||||
/* reap the child and release resources */
|
||||
pid = waitpid(cmdtab[i].pid, &status, 0);
|
||||
/* Reap the child and release resources. */
|
||||
pid = waitpid( cmdtab[ i ].pid, &status, 0 );
|
||||
|
||||
if (pid == cmdtab[i].pid)
|
||||
if ( pid == cmdtab[ i ].pid )
|
||||
{
|
||||
finished = 1;
|
||||
pid = 0;
|
||||
cmdtab[i].pid = 0;
|
||||
cmdtab[ i ].pid = 0;
|
||||
|
||||
/* set reason for exit if not timed out */
|
||||
if (WIFEXITED(status))
|
||||
/* Set reason for exit if not timed out. */
|
||||
if ( WIFEXITED( status ) )
|
||||
{
|
||||
if (0 == WEXITSTATUS(status))
|
||||
cmdtab[i].exit_reason = EXIT_OK;
|
||||
else
|
||||
cmdtab[i].exit_reason = EXIT_FAIL;
|
||||
cmdtab[ i ].exit_reason = 0 == WEXITSTATUS( status )
|
||||
? EXIT_OK
|
||||
: EXIT_FAIL;
|
||||
}
|
||||
|
||||
/* print out the rule and target name */
|
||||
out_action(cmdtab[i].action, cmdtab[i].target,
|
||||
cmdtab[i].command, cmdtab[i].buffer[OUT], cmdtab[i].buffer[ERR],
|
||||
cmdtab[i].exit_reason);
|
||||
/* Print out the rule and target name. */
|
||||
out_action( cmdtab[ i ].action, cmdtab[ i ].target,
|
||||
cmdtab[ i ].command, cmdtab[ i ].buffer[ OUT ],
|
||||
cmdtab[ i ].buffer[ ERR ], cmdtab[ i ].exit_reason
|
||||
);
|
||||
|
||||
times(&new_time);
|
||||
times( &new_time );
|
||||
|
||||
time_info.system = (double)( new_time.tms_cstime - old_time.tms_cstime ) / CLOCKS_PER_SEC;
|
||||
time_info.user = (double)( new_time.tms_cutime - old_time.tms_cutime ) / CLOCKS_PER_SEC;
|
||||
time_info.start = cmdtab[ i ].start_dt;
|
||||
time_info.end = time( 0 );
|
||||
|
||||
time_info.system = (double)(new_time.tms_cstime - old_time.tms_cstime) / CLOCKS_PER_SEC;
|
||||
time_info.user = (double)(new_time.tms_cutime - old_time.tms_cutime) / CLOCKS_PER_SEC;
|
||||
time_info.start = cmdtab[i].start_dt;
|
||||
time_info.end = time(0);
|
||||
|
||||
old_time = new_time;
|
||||
|
||||
/* Drive the completion */
|
||||
|
||||
/* Drive the completion. */
|
||||
--cmdsrunning;
|
||||
|
||||
if( intr )
|
||||
if ( intr )
|
||||
rstat = EXEC_CMD_INTR;
|
||||
else if( status != 0 )
|
||||
else if ( status != 0 )
|
||||
rstat = EXEC_CMD_FAIL;
|
||||
else
|
||||
rstat = EXEC_CMD_OK;
|
||||
|
||||
/* assume -p0 in effect so only pass buffer[0] containing merged output */
|
||||
(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time_info, cmdtab[i].command, cmdtab[i].buffer[0] );
|
||||
/* Assume -p0 in effect so only pass buffer[ 0 ]
|
||||
* containing merged output.
|
||||
*/
|
||||
(*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat,
|
||||
&time_info, cmdtab[ i ].command,
|
||||
cmdtab[ i ].buffer[ 0 ] );
|
||||
|
||||
BJAM_FREE(cmdtab[i].buffer[OUT]);
|
||||
cmdtab[i].buffer[OUT] = 0;
|
||||
BJAM_FREE( cmdtab[ i ].buffer[ OUT ] );
|
||||
cmdtab[ i ].buffer[ OUT ] = 0;
|
||||
|
||||
BJAM_FREE(cmdtab[i].buffer[ERR]);
|
||||
cmdtab[i].buffer[ERR] = 0;
|
||||
BJAM_FREE( cmdtab[ i ].buffer[ ERR ] );
|
||||
cmdtab[ i ].buffer[ ERR ] = 0;
|
||||
|
||||
BJAM_FREE(cmdtab[i].command);
|
||||
cmdtab[i].command = 0;
|
||||
BJAM_FREE( cmdtab[ i ].command );
|
||||
cmdtab[ i ].command = 0;
|
||||
|
||||
cmdtab[i].func = 0;
|
||||
cmdtab[i].closure = 0;
|
||||
cmdtab[i].start_time = 0;
|
||||
cmdtab[ i ].func = 0;
|
||||
cmdtab[ i ].closure = 0;
|
||||
cmdtab[ i ].start_time = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unknown pid %d with errno = %d\n", pid, errno);
|
||||
exit(EXITBAD);
|
||||
printf( "unknown pid %d with errno = %d\n", pid, errno );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
/*
|
||||
* 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 "jam.h"
|
||||
#include "lists.h"
|
||||
#include "execcmd.h"
|
||||
|
||||
# ifdef OS_VMS
|
||||
#ifdef OS_VMS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -20,150 +20,142 @@
|
||||
#include <clidef.h>
|
||||
|
||||
/*
|
||||
* execvms.c - execute a shell script, ala VMS
|
||||
* 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 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.
|
||||
* 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 do not 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
|
||||
* 01/14/96 (seiwald) - do not put -'s between "'s
|
||||
*/
|
||||
|
||||
#define WRTLEN 240
|
||||
|
||||
#define MIN( a, b ) ((a) < (b) ? (a) : (b))
|
||||
#define MIN( a, b ) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/* 1 for the @ and 4 for the .com */
|
||||
|
||||
char tempnambuf[ L_tmpnam + 1 + 4 ] = {0};
|
||||
char tempnambuf[ L_tmpnam + 1 + 4 ] = { 0 };
|
||||
|
||||
void
|
||||
execcmd(
|
||||
char *string,
|
||||
void (*func)( void *closure, int status, timing_info*, char *, char * ),
|
||||
void *closure,
|
||||
LIST *shell,
|
||||
char *rule_name,
|
||||
char *target )
|
||||
|
||||
void exec_cmd
|
||||
(
|
||||
char * string,
|
||||
void (* func)( void * closure, int status, timing_info *, char *, char * ),
|
||||
void * closure,
|
||||
LIST * shell,
|
||||
char * rule_name,
|
||||
char * target
|
||||
)
|
||||
{
|
||||
char *s, *e, *p;
|
||||
int rstat = EXEC_CMD_OK;
|
||||
int status;
|
||||
char * s;
|
||||
char * e;
|
||||
cahr * p;
|
||||
int rstat = EXEC_CMD_OK;
|
||||
int status;
|
||||
|
||||
/* See if string is more than one line */
|
||||
/* discounting leading/trailing white space */
|
||||
/* See if string is more than one line discounting leading/trailing white
|
||||
* space.
|
||||
*/
|
||||
for ( s = string; *s && isspace( *s ); ++s );
|
||||
|
||||
for( s = string; *s && isspace( *s ); s++ )
|
||||
;
|
||||
e = p = strchr( s, '\n' );
|
||||
|
||||
e = p = strchr( s, '\n' );
|
||||
while ( p && isspace( *p ) )
|
||||
++p;
|
||||
|
||||
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;
|
||||
|
||||
/* If multi line or long, write to com file. */
|
||||
/* Otherwise, exec directly. */
|
||||
/* Create temp file invocation "@sys$scratch:tempfile.com". */
|
||||
if ( !*tempnambuf )
|
||||
{
|
||||
tempnambuf[0] = '@';
|
||||
(void)tmpnam( tempnambuf + 1 );
|
||||
strcat( tempnambuf, ".com" );
|
||||
}
|
||||
|
||||
if( p && *p || e - s > WRTLEN )
|
||||
{
|
||||
FILE *f;
|
||||
/* Open tempfile. */
|
||||
if ( !( f = fopen( tempnambuf + 1, "w" ) ) )
|
||||
{
|
||||
printf( "can't open command file\n" );
|
||||
(*func)( closure, EXEC_CMD_FAIL );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create temp file invocation "@sys$scratch:tempfile.com" */
|
||||
/* For each line of the string. */
|
||||
while ( *string )
|
||||
{
|
||||
char * s = strchr( string, '\n' );
|
||||
int len = s ? s + 1 - string : strlen( string );
|
||||
|
||||
if( !*tempnambuf )
|
||||
{
|
||||
tempnambuf[0] = '@';
|
||||
(void)tmpnam( tempnambuf + 1 );
|
||||
strcat( tempnambuf, ".com" );
|
||||
}
|
||||
|
||||
/* Open tempfile */
|
||||
fputc( '$', f );
|
||||
|
||||
if( !( f = fopen( tempnambuf + 1, "w" ) ) )
|
||||
{
|
||||
printf( "can't open command file\n" );
|
||||
(*func)( closure, EXEC_CMD_FAIL );
|
||||
return;
|
||||
}
|
||||
/* 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;
|
||||
|
||||
/* For each line of the string */
|
||||
/* Look for matching "s. */
|
||||
for ( ; q < qe; ++q )
|
||||
if ( ( *q == '"' ) && ( quote = !quote ) )
|
||||
qq = q;
|
||||
|
||||
while( *string )
|
||||
{
|
||||
char *s = strchr( string, '\n' );
|
||||
int len = s ? s + 1 - string : strlen( string );
|
||||
/* Back up to opening quote, if in one. */
|
||||
if ( quote )
|
||||
q = qq;
|
||||
|
||||
fputc( '$', f );
|
||||
fwrite( string, ( q - string ), 1, f );
|
||||
|
||||
/* For each chunk of a line that needs to be split */
|
||||
len -= ( q - string );
|
||||
string = q;
|
||||
|
||||
while( len > 0 )
|
||||
{
|
||||
char *q = string;
|
||||
char *qe = string + MIN( len, WRTLEN );
|
||||
char *qq = q;
|
||||
int quote = 0;
|
||||
if ( len )
|
||||
{
|
||||
fputc( '-', f );
|
||||
fputc( '\n', f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for matching "'s */
|
||||
fclose( f );
|
||||
|
||||
for( ; q < qe; q++ )
|
||||
if( *q == '"' && ( quote = !quote ) )
|
||||
qq = q;
|
||||
status = system( tempnambuf ) & 0x07;
|
||||
|
||||
/* Back up to opening quote, if in one */
|
||||
unlink( tempnambuf + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Execute single line command. Strip trailing newline before execing.
|
||||
*/
|
||||
if ( e ) *e = 0;
|
||||
status = system( s ) & 0x07;
|
||||
}
|
||||
|
||||
if( quote )
|
||||
q = qq;
|
||||
/* Fail for error or fatal error. OK on OK, warning or info exit. */
|
||||
if ( ( status == 2 ) || ( status == 4 ) )
|
||||
rstat = EXEC_CMD_FAIL;
|
||||
|
||||
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 );
|
||||
(*func)( closure, rstat );
|
||||
}
|
||||
|
||||
int
|
||||
execwait()
|
||||
|
||||
int exec_wait()
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# endif /* VMS */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,5 +10,5 @@
|
||||
|
||||
#include "lists.h"
|
||||
|
||||
LIST *var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin );
|
||||
LIST *var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin );
|
||||
void var_expand_unit_test();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
|
||||
/* This file is ALSO:
|
||||
* Copyright 2001-2004 David Abrahams.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
@@ -26,9 +26,9 @@
|
||||
*
|
||||
* 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() - 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()
|
||||
@@ -43,90 +43,84 @@
|
||||
* 11/21/96 (peterk) - BEOS does not have Unix-style archives
|
||||
*/
|
||||
|
||||
void CopyC2PStr(const char * cstr, StringPtr pstr)
|
||||
|
||||
void CopyC2PStr( char const * cstr, StringPtr pstr )
|
||||
{
|
||||
int len;
|
||||
|
||||
for (len = 0; *cstr && len<255; pstr[++len] = *cstr++)
|
||||
;
|
||||
|
||||
pstr[0] = len;
|
||||
int len;
|
||||
for ( len = 0; *cstr && ( len < 255 ); pstr[ ++len ] = *cstr++ );
|
||||
pstr[ 0 ] = len;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* file_dirscan() - scan a directory for files
|
||||
* file_dirscan() - scan a directory for files.
|
||||
*/
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
scanback func,
|
||||
void *closure )
|
||||
void file_dirscan( char * dir, scanback func, void * closure )
|
||||
{
|
||||
PATHNAME f;
|
||||
string filename[1];
|
||||
string filename[ 1 ];
|
||||
unsigned char fullPath[ 512 ];
|
||||
|
||||
FSSpec spec;
|
||||
WDPBRec vol;
|
||||
Str63 volName;
|
||||
Str63 volName;
|
||||
CInfoPBRec lastInfo;
|
||||
int index = 1;
|
||||
|
||||
/* First enter directory itself */
|
||||
|
||||
/* First enter directory itself. */
|
||||
|
||||
memset( (char *)&f, '\0', sizeof( f ) );
|
||||
|
||||
f.f_dir.ptr = dir;
|
||||
f.f_dir.len = strlen(dir);
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
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)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
if ( ( f.f_dir.len == 1 ) && ( f.f_dir.ptr[0] == ':' ) )
|
||||
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
|
||||
/* Now enter contents of directory */
|
||||
|
||||
vol.ioNamePtr = volName;
|
||||
|
||||
if( PBHGetVolSync( &vol ) )
|
||||
|
||||
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) )
|
||||
|
||||
if ( FSMakeFSSpec( vol.ioWDVRefNum, vol.ioWDDirID, fullPath, &spec ) )
|
||||
return;
|
||||
|
||||
if (!(lastInfo.dirInfo.ioFlAttrib & 0x10))
|
||||
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;
|
||||
|
||||
// ioDrDirID must be reset each time.
|
||||
|
||||
if ( !( lastInfo.dirInfo.ioFlAttrib & 0x10 ) )
|
||||
return;
|
||||
|
||||
/* ioDrDirID must be reset each time. */
|
||||
spec.parID = lastInfo.dirInfo.ioDrDirID;
|
||||
|
||||
string_new( filename );
|
||||
for( ;; )
|
||||
for ( ; ; )
|
||||
{
|
||||
lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
|
||||
lastInfo.dirInfo.ioDrDirID = spec.parID;
|
||||
lastInfo.dirInfo.ioNamePtr = fullPath;
|
||||
lastInfo.dirInfo.ioVRefNum = spec.vRefNum;
|
||||
lastInfo.dirInfo.ioDrDirID = spec.parID;
|
||||
lastInfo.dirInfo.ioNamePtr = fullPath;
|
||||
lastInfo.dirInfo.ioFDirIndex = index++;
|
||||
|
||||
if( PBGetCatInfoSync(&lastInfo) )
|
||||
|
||||
if ( PBGetCatInfoSync( &lastInfo ) )
|
||||
return;
|
||||
|
||||
|
||||
f.f_base.ptr = (char *)fullPath + 1;
|
||||
f.f_base.len = *fullPath;
|
||||
|
||||
@@ -137,51 +131,40 @@ file_dirscan(
|
||||
string_free( filename );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan()
|
||||
* file_time() - get timestamp of file, if not done by file_dirscan().
|
||||
*/
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
int file_time( char * filename, time_t * time )
|
||||
{
|
||||
struct stat statbuf;
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
if ( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
|
||||
*time = statbuf.st_mtime;
|
||||
|
||||
return 0;
|
||||
*time = statbuf.st_mtime;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int file_is_file(char* filename)
|
||||
|
||||
int file_is_file( char * filename )
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
|
||||
if (S_ISREG(statbuf.st_mode))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
struct stat statbuf;
|
||||
if ( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
return S_ISREG( statbuf.st_mode ) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* file_archscan() - scan an archive for files
|
||||
* file_archscan() - scan an archive for files.
|
||||
*/
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
scanback func,
|
||||
void *closure )
|
||||
void file_archscan( char * archive, scanback func, void * closure )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
# endif /* macintosh */
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
# include <dir.h>
|
||||
# include <dos.h>
|
||||
# endif
|
||||
# undef FILENAME /* cpp namespace collision */
|
||||
# undef FILENAME /* cpp namespace collision */
|
||||
# define _finddata_t ffblk
|
||||
# endif
|
||||
|
||||
@@ -38,9 +38,9 @@
|
||||
*
|
||||
* 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() - 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()
|
||||
@@ -56,14 +56,10 @@
|
||||
* file_dirscan() - scan a directory for files
|
||||
*/
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
scanback func,
|
||||
void *closure )
|
||||
void file_dirscan( char * dir, scanback func, void * closure )
|
||||
{
|
||||
PROFILE_ENTER(FILE_DIRSCAN);
|
||||
|
||||
PROFILE_ENTER( FILE_DIRSCAN );
|
||||
|
||||
file_info_t * d = 0;
|
||||
|
||||
dir = short_path_to_long_path( dir );
|
||||
@@ -71,49 +67,64 @@ file_dirscan(
|
||||
/* First enter directory itself */
|
||||
|
||||
d = file_query( dir );
|
||||
|
||||
if ( ! d || ! d->is_dir )
|
||||
|
||||
if ( !d || !d->is_dir )
|
||||
{
|
||||
PROFILE_EXIT(FILE_DIRSCAN);
|
||||
PROFILE_EXIT( FILE_DIRSCAN );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! d->files )
|
||||
if ( !d->files )
|
||||
{
|
||||
PATHNAME f;
|
||||
string filespec[1];
|
||||
string filename[1];
|
||||
string filespec[ 1 ];
|
||||
string filename[ 1 ];
|
||||
long handle;
|
||||
int ret;
|
||||
struct _finddata_t finfo[1];
|
||||
LIST* files = L0;
|
||||
struct _finddata_t finfo[ 1 ];
|
||||
LIST * files = L0;
|
||||
int d_length = strlen( d->name );
|
||||
|
||||
memset( (char *)&f, '\0', sizeof( f ) );
|
||||
|
||||
|
||||
f.f_dir.ptr = d->name;
|
||||
f.f_dir.len = strlen(d->name);
|
||||
|
||||
f.f_dir.len = d_length;
|
||||
|
||||
/* Now enter contents of directory */
|
||||
|
||||
string_copy( filespec, *d->name ? d->name : "." );
|
||||
string_append( filespec, "/*" );
|
||||
/* Prepare file search specification for the findfirst() API. */
|
||||
if ( d_length == 0 )
|
||||
string_copy( filespec, ".\\*" );
|
||||
else
|
||||
{
|
||||
/*
|
||||
* We can not simply assume the given folder name will never include
|
||||
* its trailing path separator or otherwise we would not support the
|
||||
* Windows root folder specified without its drive letter, i.e. '\'.
|
||||
*/
|
||||
char trailingChar = d->name[ d_length - 1 ] ;
|
||||
string_copy( filespec, d->name );
|
||||
if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) )
|
||||
string_append( filespec, "\\" );
|
||||
string_append( filespec, "*" );
|
||||
}
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
if ( DEBUG_BINDSCAN )
|
||||
printf( "scan directory %s\n", dir );
|
||||
|
||||
# if defined(__BORLANDC__) && __BORLANDC__ < 0x550
|
||||
#if defined(__BORLANDC__) && __BORLANDC__ < 0x550
|
||||
if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
|
||||
{
|
||||
string_free( filespec );
|
||||
PROFILE_EXIT(FILE_DIRSCAN);
|
||||
PROFILE_EXIT( FILE_DIRSCAN );
|
||||
return;
|
||||
}
|
||||
|
||||
string_new( filename );
|
||||
while( !ret )
|
||||
string_new ( filename );
|
||||
while ( !ret )
|
||||
{
|
||||
file_info_t * ff = 0;
|
||||
|
||||
|
||||
f.f_base.ptr = finfo->ff_name;
|
||||
f.f_base.len = strlen( finfo->ff_name );
|
||||
|
||||
@@ -132,15 +143,15 @@ file_dirscan(
|
||||
# else
|
||||
handle = _findfirst( filespec->value, finfo );
|
||||
|
||||
if( ret = ( handle < 0L ) )
|
||||
if ( ret = ( handle < 0L ) )
|
||||
{
|
||||
string_free( filespec );
|
||||
PROFILE_EXIT(FILE_DIRSCAN);
|
||||
PROFILE_EXIT( FILE_DIRSCAN );
|
||||
return;
|
||||
}
|
||||
|
||||
string_new( filename );
|
||||
while( !ret )
|
||||
while ( !ret )
|
||||
{
|
||||
file_info_t * ff = 0;
|
||||
|
||||
@@ -150,7 +161,7 @@ file_dirscan(
|
||||
string_truncate( filename, 0 );
|
||||
path_build( &f, filename, 0 );
|
||||
|
||||
files = list_new( files, newstr(filename->value) );
|
||||
files = list_new( files, newstr( filename->value ) );
|
||||
ff = file_info( filename->value );
|
||||
ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
|
||||
ff->is_dir = finfo->attrib & _A_SUBDIR ? 1 : 0;
|
||||
@@ -164,16 +175,16 @@ file_dirscan(
|
||||
# endif
|
||||
string_free( filename );
|
||||
string_free( filespec );
|
||||
|
||||
|
||||
d->files = files;
|
||||
}
|
||||
|
||||
/* Special case \ or d:\ : enter it */
|
||||
{
|
||||
unsigned long len = strlen(d->name);
|
||||
if( len == 1 && d->name[0] == '\\' )
|
||||
if ( len == 1 && d->name[0] == '\\' )
|
||||
(*func)( closure, d->name, 1 /* stat()'ed */, d->time );
|
||||
else if( len == 3 && d->name[1] == ':' )
|
||||
else if ( len == 3 && d->name[1] == ':' )
|
||||
(*func)( closure, d->name, 1 /* stat()'ed */, d->time );
|
||||
}
|
||||
|
||||
@@ -188,8 +199,8 @@ file_dirscan(
|
||||
files = list_next( files );
|
||||
}
|
||||
}
|
||||
|
||||
PROFILE_EXIT(FILE_DIRSCAN);
|
||||
|
||||
PROFILE_EXIT( FILE_DIRSCAN );
|
||||
}
|
||||
|
||||
file_info_t * file_query( char * filename )
|
||||
@@ -199,7 +210,7 @@ file_info_t * file_query( char * filename )
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( *filename ? filename : ".", &statbuf ) < 0 )
|
||||
if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
|
||||
return 0;
|
||||
|
||||
ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
|
||||
@@ -216,8 +227,8 @@ file_info_t * file_query( char * filename )
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
file_info_t * ff = file_query( filename );
|
||||
if ( !ff ) return -1;
|
||||
@@ -239,19 +250,19 @@ int file_is_file(char* filename)
|
||||
|
||||
/* Straight from SunOS */
|
||||
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
|
||||
#define ARFMAG "`\n"
|
||||
#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];
|
||||
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
|
||||
@@ -259,98 +270,98 @@ struct ar_hdr {
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
scanback func,
|
||||
void *closure )
|
||||
char *archive,
|
||||
scanback func,
|
||||
void *closure )
|
||||
{
|
||||
struct ar_hdr ar_hdr;
|
||||
char *string_table = 0;
|
||||
char buf[ MAXJPATH ];
|
||||
long offset;
|
||||
int fd;
|
||||
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 ( ( fd = open( archive, O_RDONLY | O_BINARY, 0 ) ) < 0 )
|
||||
return;
|
||||
|
||||
if( read( fd, buf, SARMAG ) != SARMAG ||
|
||||
strncmp( ARMAG, buf, SARMAG ) )
|
||||
{
|
||||
close( fd );
|
||||
return;
|
||||
}
|
||||
if ( read( fd, buf, SARMAG ) != SARMAG ||
|
||||
strncmp( ARMAG, buf, SARMAG ) )
|
||||
{
|
||||
close( fd );
|
||||
return;
|
||||
}
|
||||
|
||||
offset = SARMAG;
|
||||
offset = SARMAG;
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan archive %s\n", archive );
|
||||
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;
|
||||
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 );
|
||||
sscanf( ar_hdr.ar_date, "%ld", &lar_date );
|
||||
sscanf( ar_hdr.ar_size, "%ld", &lar_size );
|
||||
|
||||
lar_size = ( lar_size + 1 ) & ~1;
|
||||
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
|
||||
*/
|
||||
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 = BJAM_MALLOC_ATOMIC(lar_size+1);
|
||||
if (read(fd, string_table, lar_size) != lar_size)
|
||||
printf("error reading string table\n");
|
||||
string_table[lar_size] = '\0';
|
||||
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.
|
||||
*/
|
||||
string_table = BJAM_MALLOC_ATOMIC(lar_size+1);
|
||||
if (read(fd, string_table, lar_size) != lar_size)
|
||||
printf("error reading string table\n");
|
||||
string_table[lar_size] = '\0';
|
||||
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 );
|
||||
for ( endname = name; *endname && *endname != '\n'; ++endname) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* normal name */
|
||||
name = ar_hdr.ar_name;
|
||||
endname = name + sizeof( ar_hdr.ar_name );
|
||||
}
|
||||
name = string_table + atoi( ar_hdr.ar_name + 1 );
|
||||
for ( endname = name; *endname && *endname != '\n'; ++endname) {}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* normal name */
|
||||
name = ar_hdr.ar_name;
|
||||
endname = name + sizeof( ar_hdr.ar_name );
|
||||
}
|
||||
|
||||
/* strip trailing white-space, slashes, and backslashes */
|
||||
/* strip trailing white-space, slashes, and backslashes */
|
||||
|
||||
while( endname-- > name )
|
||||
if( !isspace(*endname) && *endname != '\\' && *endname != '/' )
|
||||
break;
|
||||
*++endname = 0;
|
||||
while ( endname-- > name )
|
||||
if ( !isspace(*endname) && ( *endname != '\\' ) && ( *endname != '/' ) )
|
||||
break;
|
||||
*++endname = 0;
|
||||
|
||||
/* strip leading directory names, an NT specialty */
|
||||
/* strip leading directory names, an NT specialty */
|
||||
|
||||
if( c = strrchr( name, '/' ) )
|
||||
name = c + 1;
|
||||
if( c = strrchr( name, '\\' ) )
|
||||
name = c + 1;
|
||||
if ( c = strrchr( name, '/' ) )
|
||||
name = c + 1;
|
||||
if ( c = strrchr( name, '\\' ) )
|
||||
name = c + 1;
|
||||
|
||||
sprintf( buf, "%s(%.*s)", archive, endname - name, name );
|
||||
(*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
|
||||
sprintf( buf, "%s(%.*s)", archive, endname - name, name );
|
||||
(*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
|
||||
|
||||
offset += SARHDR + lar_size;
|
||||
lseek( fd, offset, 0 );
|
||||
}
|
||||
offset += SARHDR + lar_size;
|
||||
lseek( fd, offset, 0 );
|
||||
}
|
||||
|
||||
close( fd );
|
||||
close( fd );
|
||||
}
|
||||
|
||||
# endif /* NT */
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
*
|
||||
* 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() - 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()
|
||||
@@ -45,10 +45,10 @@
|
||||
*/
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
scanback func,
|
||||
void *closure )
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
scanback func,
|
||||
void *closure )
|
||||
{
|
||||
PATHNAME f;
|
||||
string filespec[1];
|
||||
@@ -68,10 +68,10 @@ file_dirscan(
|
||||
/* Special case \ or d:\ : enter it */
|
||||
string_copy( filespec, dir );
|
||||
|
||||
if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
|
||||
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
|
||||
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
if ( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
|
||||
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
else if ( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
|
||||
(*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
|
||||
else
|
||||
string_push_back( filespec, '/' );
|
||||
|
||||
@@ -79,20 +79,19 @@ file_dirscan(
|
||||
|
||||
/* Now enter contents of directory */
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
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 ) )
|
||||
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 );
|
||||
|
||||
@@ -100,7 +99,7 @@ file_dirscan(
|
||||
path_build( &f, filename, 0 );
|
||||
(*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
|
||||
}
|
||||
while( !_dos_findnext( finfo ) );
|
||||
while ( !_dos_findnext( finfo ) );
|
||||
string_free( filename );
|
||||
}
|
||||
}
|
||||
@@ -111,27 +110,27 @@ file_dirscan(
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
/* This is called on OS2, not NT. */
|
||||
/* NT fills in the time in the dirscan. */
|
||||
/* This is called on OS2, not NT. */
|
||||
/* NT fills in the time in the dirscan. */
|
||||
|
||||
struct stat statbuf;
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
if ( stat( filename, &statbuf ) < 0 )
|
||||
return -1;
|
||||
|
||||
*time = statbuf.st_mtime;
|
||||
*time = statbuf.st_mtime;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
scanback func,
|
||||
void *closure )
|
||||
char *archive,
|
||||
scanback func,
|
||||
void *closure )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -5,57 +5,56 @@
|
||||
# include "filesys.h"
|
||||
# include "lists.h"
|
||||
|
||||
void
|
||||
file_build1(
|
||||
PATHNAME *f,
|
||||
string* file)
|
||||
void file_build1( PATHNAME * f, string * file )
|
||||
{
|
||||
if( DEBUG_SEARCH )
|
||||
if ( DEBUG_SEARCH )
|
||||
{
|
||||
printf("build file: ");
|
||||
if( f->f_root.len )
|
||||
printf("build file: ");
|
||||
if ( f->f_root.len )
|
||||
printf( "root = '%.*s' ", f->f_root.len, f->f_root.ptr );
|
||||
if( f->f_dir.len )
|
||||
if ( f->f_dir.len )
|
||||
printf( "dir = '%.*s' ", f->f_dir.len, f->f_dir.ptr );
|
||||
if( f->f_base.len )
|
||||
if ( f->f_base.len )
|
||||
printf( "base = '%.*s' ", f->f_base.len, f->f_base.ptr );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
|
||||
/* Start with the grist. If the current grist isn't */
|
||||
/* surrounded by <>'s, add them. */
|
||||
|
||||
if( f->f_grist.len )
|
||||
if ( f->f_grist.len )
|
||||
{
|
||||
if( f->f_grist.ptr[0] != '<' )
|
||||
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] != '>' )
|
||||
if ( file->value[file->size - 1] != '>' )
|
||||
string_push_back( file, '>' );
|
||||
}
|
||||
}
|
||||
|
||||
static struct hash * filecache_hash = 0;
|
||||
static file_info_t filecache_finfo;
|
||||
|
||||
file_info_t * file_info(char * filename)
|
||||
{
|
||||
file_info_t finfo_, *finfo = &finfo_;
|
||||
|
||||
file_info_t *finfo = &filecache_finfo;
|
||||
|
||||
if ( !filecache_hash )
|
||||
filecache_hash = hashinit( sizeof( file_info_t ), "file_info" );
|
||||
|
||||
|
||||
finfo->name = filename;
|
||||
finfo->is_file = 0;
|
||||
finfo->is_dir = 0;
|
||||
finfo->size = 0;
|
||||
finfo->time = 0;
|
||||
finfo->files = 0;
|
||||
if ( hashenter( filecache_hash, (HASHDATA**)&finfo ) )
|
||||
{
|
||||
/* printf( "file_info: %s\n", filename ); */
|
||||
finfo->name = newstr( finfo->name );
|
||||
finfo->is_file = 0;
|
||||
finfo->is_dir = 0;
|
||||
finfo->size = 0;
|
||||
finfo->time = 0;
|
||||
finfo->files = 0;
|
||||
}
|
||||
|
||||
|
||||
return finfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* filesys.h - OS specific file routines
|
||||
* filesys.h - OS specific file routines
|
||||
*/
|
||||
|
||||
#ifndef FILESYS_DWA20011025_H
|
||||
@@ -31,24 +31,29 @@ int file_time( char *filename, time_t *time );
|
||||
void file_build1(PATHNAME *f, string* file) ;
|
||||
int file_is_file(char* filename);
|
||||
|
||||
struct file_info_t {
|
||||
char * name;
|
||||
short is_file;
|
||||
short is_dir;
|
||||
unsigned long size;
|
||||
time_t time;
|
||||
LIST * files;
|
||||
} ;
|
||||
typedef struct file_info_t file_info_t ;
|
||||
struct file_info_t
|
||||
{
|
||||
char * name;
|
||||
short is_file;
|
||||
short is_dir;
|
||||
unsigned long size;
|
||||
time_t time;
|
||||
LIST * files;
|
||||
};
|
||||
|
||||
file_info_t * file_info(char * filename);
|
||||
|
||||
file_info_t * file_query(char * filename);
|
||||
/* Creates a pointer to information about file 'filename', creating it as
|
||||
* necessary. If created, the structure will be default initialized.
|
||||
*/
|
||||
file_info_t * file_info( char * filename );
|
||||
|
||||
/* Returns information about a file, queries the OS if needed. */
|
||||
file_info_t * file_query( char * filename );
|
||||
|
||||
void file_done();
|
||||
|
||||
/** Marks a path/file to be removed when jam exits.
|
||||
*/
|
||||
/* Marks a path/file to be removed when jam exits. */
|
||||
void file_remove_atexit( const char * path );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
# if defined( OS_SEQUENT ) || \
|
||||
defined( OS_DGUX ) || \
|
||||
defined( OS_SCO ) || \
|
||||
defined( OS_ISC )
|
||||
defined( OS_ISC )
|
||||
# define PORTAR 1
|
||||
# endif
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
/* need unistd for rhapsody's proper lseek */
|
||||
# include <sys/dir.h>
|
||||
# include <unistd.h>
|
||||
# define STRUCT_DIRENT struct direct
|
||||
# define STRUCT_DIRENT struct direct
|
||||
# else
|
||||
# include <dirent.h>
|
||||
# define STRUCT_DIRENT struct dirent
|
||||
# define STRUCT_DIRENT struct dirent
|
||||
# endif
|
||||
|
||||
# ifdef OS_COHERENT
|
||||
@@ -58,21 +58,21 @@
|
||||
# endif
|
||||
|
||||
# if defined( OS_MVS ) || \
|
||||
defined( OS_INTERIX )
|
||||
defined( OS_INTERIX )
|
||||
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\n"
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\n"
|
||||
|
||||
struct ar_hdr /* archive file member header - printable ascii */
|
||||
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 */
|
||||
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
|
||||
@@ -90,21 +90,21 @@ struct ar_hdr /* archive file member header - printable ascii */
|
||||
# ifdef OS_AIX
|
||||
/* Define those for AIX to get the definitions for both the small and the
|
||||
* big variant of the archive file format. */
|
||||
# define __AR_SMALL__
|
||||
# define __AR_BIG__
|
||||
# define __AR_SMALL__
|
||||
# define __AR_BIG__
|
||||
# endif
|
||||
|
||||
# include <ar.h>
|
||||
# endif
|
||||
# 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() - 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()
|
||||
@@ -119,25 +119,22 @@ struct ar_hdr /* archive file member header - printable ascii */
|
||||
* 11/21/96 (peterk) - BEOS does not have Unix-style archives
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* file_dirscan() - scan a directory for files
|
||||
* file_dirscan() - scan a directory for files.
|
||||
*/
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
scanback func,
|
||||
void *closure )
|
||||
void file_dirscan( char * dir, scanback func, void * closure )
|
||||
{
|
||||
PROFILE_ENTER(FILE_DIRSCAN);
|
||||
|
||||
PROFILE_ENTER( FILE_DIRSCAN );
|
||||
|
||||
file_info_t * d = 0;
|
||||
|
||||
d = file_query( dir );
|
||||
|
||||
if ( ! d || ! d->is_dir )
|
||||
|
||||
if ( !d || !d->is_dir )
|
||||
{
|
||||
PROFILE_EXIT(FILE_DIRSCAN);
|
||||
PROFILE_EXIT( FILE_DIRSCAN );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -158,22 +155,20 @@ file_dirscan(
|
||||
|
||||
dir = *dir ? dir : ".";
|
||||
|
||||
/* Now enter contents of directory */
|
||||
/* Now enter contents of directory. */
|
||||
|
||||
if( !( dd = opendir( dir ) ) )
|
||||
if ( !( dd = opendir( dir ) ) )
|
||||
{
|
||||
PROFILE_EXIT(FILE_DIRSCAN);
|
||||
PROFILE_EXIT( FILE_DIRSCAN );
|
||||
return;
|
||||
}
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
if ( DEBUG_BINDSCAN )
|
||||
printf( "scan directory %s\n", dir );
|
||||
|
||||
string_new( filename );
|
||||
while( dirent = readdir( dd ) )
|
||||
while ( ( dirent = readdir( dd ) ) )
|
||||
{
|
||||
file_info_t * ff = 0;
|
||||
|
||||
# ifdef old_sinix
|
||||
/* Broken structure definition on sinix. */
|
||||
f.f_base.ptr = dirent->d_name - 2;
|
||||
@@ -191,14 +186,14 @@ file_dirscan(
|
||||
string_free( filename );
|
||||
|
||||
closedir( dd );
|
||||
|
||||
|
||||
d->files = files;
|
||||
}
|
||||
|
||||
/* Special case / : enter it */
|
||||
{
|
||||
unsigned long len = strlen(d->name);
|
||||
if( len == 1 && d->name[0] == '/' )
|
||||
if ( ( len == 1 ) && ( d->name[0] == '/' ) )
|
||||
(*func)( closure, d->name, 1 /* stat()'ed */, d->time );
|
||||
}
|
||||
|
||||
@@ -213,10 +208,11 @@ file_dirscan(
|
||||
files = list_next( files );
|
||||
}
|
||||
}
|
||||
|
||||
PROFILE_EXIT(FILE_DIRSCAN);
|
||||
|
||||
PROFILE_EXIT( FILE_DIRSCAN );
|
||||
}
|
||||
|
||||
|
||||
file_info_t * file_query( char * filename )
|
||||
{
|
||||
file_info_t * ff = file_info( filename );
|
||||
@@ -224,7 +220,7 @@ file_info_t * file_query( char * filename )
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if( stat( *filename ? filename : ".", &statbuf ) < 0 )
|
||||
if ( stat( *filename ? filename : ".", &statbuf ) < 0 )
|
||||
return 0;
|
||||
|
||||
ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
|
||||
@@ -241,8 +237,8 @@ file_info_t * file_query( char * filename )
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
file_info_t * ff = file_query( filename );
|
||||
if ( !ff ) return -1;
|
||||
@@ -262,109 +258,109 @@ int file_is_file(char* filename)
|
||||
* file_archscan() - scan an archive for files
|
||||
*/
|
||||
|
||||
# ifndef AIAMAG /* God-fearing UNIX */
|
||||
# ifndef AIAMAG /* God-fearing UNIX */
|
||||
|
||||
# define SARFMAG 2
|
||||
# define SARHDR sizeof( struct ar_hdr )
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
scanback func,
|
||||
void *closure )
|
||||
char *archive,
|
||||
scanback func,
|
||||
void *closure )
|
||||
{
|
||||
# ifndef NO_AR
|
||||
struct ar_hdr ar_hdr;
|
||||
char buf[ MAXJPATH ];
|
||||
long offset;
|
||||
char *string_table = 0;
|
||||
int fd;
|
||||
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 ( ( fd = open( archive, O_RDONLY, 0 ) ) < 0 )
|
||||
return;
|
||||
|
||||
if( read( fd, buf, SARMAG ) != SARMAG ||
|
||||
strncmp( ARMAG, buf, SARMAG ) )
|
||||
{
|
||||
close( fd );
|
||||
return;
|
||||
}
|
||||
if ( read( fd, buf, SARMAG ) != SARMAG ||
|
||||
strncmp( ARMAG, buf, SARMAG ) )
|
||||
{
|
||||
close( fd );
|
||||
return;
|
||||
}
|
||||
|
||||
offset = SARMAG;
|
||||
offset = SARMAG;
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "scan archive %s\n", archive );
|
||||
if ( DEBUG_BINDSCAN )
|
||||
printf( "scan archive %s\n", archive );
|
||||
|
||||
while( read( fd, &ar_hdr, SARHDR ) == SARHDR
|
||||
&& ! ( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
|
||||
while ( ( read( fd, &ar_hdr, SARHDR ) == SARHDR )
|
||||
&& !( memcmp( ar_hdr.ar_fmag, ARFMAG, SARFMAG )
|
||||
#ifdef ARFZMAG
|
||||
/* OSF also has a compressed format */
|
||||
&& memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
|
||||
/* OSF also has a compressed format */
|
||||
&& memcmp( ar_hdr.ar_fmag, ARFZMAG, SARFMAG )
|
||||
#endif
|
||||
) )
|
||||
{
|
||||
char lar_name_[257];
|
||||
char* lar_name = lar_name_ + 1;
|
||||
long lar_date;
|
||||
long lar_size;
|
||||
long lar_offset;
|
||||
char *c;
|
||||
char *src, *dest;
|
||||
) )
|
||||
{
|
||||
char lar_name_[257];
|
||||
char * lar_name = lar_name_ + 1;
|
||||
long lar_date;
|
||||
long lar_size;
|
||||
long lar_offset;
|
||||
char * c;
|
||||
char * src;
|
||||
char * dest;
|
||||
|
||||
strncpy( lar_name, ar_hdr.ar_name, sizeof(ar_hdr.ar_name) );
|
||||
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 );
|
||||
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
|
||||
*/
|
||||
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 *)BJAM_MALLOC_ATOMIC(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 = '/';
|
||||
}
|
||||
}
|
||||
string_table = (char *)BJAM_MALLOC_ATOMIC(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';
|
||||
c = lar_name - 1;
|
||||
while ( ( *++c != ' ' ) && ( *c != '/' ) ) ;
|
||||
*c = '\0';
|
||||
|
||||
if ( DEBUG_BINDSCAN )
|
||||
printf( "archive name %s found\n", lar_name );
|
||||
if ( DEBUG_BINDSCAN )
|
||||
printf( "archive name %s found\n", lar_name );
|
||||
|
||||
sprintf( buf, "%s(%s)", archive, lar_name );
|
||||
sprintf( buf, "%s(%s)", archive, lar_name );
|
||||
|
||||
(*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
|
||||
(*func)( closure, buf, 1 /* time valid */, (time_t)lar_date );
|
||||
|
||||
offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
|
||||
lseek( fd, offset, 0 );
|
||||
}
|
||||
offset += SARHDR + ( ( lar_size + 1 ) & ~1 );
|
||||
lseek( fd, offset, 0 );
|
||||
}
|
||||
|
||||
if (string_table)
|
||||
BJAM_FREE(string_table);
|
||||
if (string_table)
|
||||
BJAM_FREE(string_table);
|
||||
|
||||
close( fd );
|
||||
close( fd );
|
||||
|
||||
# endif /* NO_AR */
|
||||
|
||||
@@ -385,28 +381,28 @@ static void file_archscan_small(
|
||||
char buf[ MAXJPATH ];
|
||||
long offset;
|
||||
|
||||
if( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
|
||||
if ( read( fd, (char *)&fl_hdr, FL_HSZ ) != FL_HSZ)
|
||||
return;
|
||||
|
||||
sscanf( fl_hdr.fl_fstmoff, "%ld", &offset );
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
|
||||
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 ) )
|
||||
|
||||
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 )
|
||||
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 );
|
||||
@@ -431,26 +427,26 @@ static void file_archscan_big(
|
||||
char buf[ MAXJPATH ];
|
||||
long long offset;
|
||||
|
||||
if( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
|
||||
if ( read( fd, (char *)&fl_hdr, FL_HSZ_BIG) != FL_HSZ_BIG)
|
||||
return;
|
||||
|
||||
sscanf( fl_hdr.fl_fstmoff, "%lld", &offset );
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
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 ) )
|
||||
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;
|
||||
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, "%lld", &offset );
|
||||
sscanf( ar_hdr.hdr.ar_namlen, "%d" , &lar_namlen );
|
||||
sscanf( ar_hdr.hdr.ar_date , "%ld" , &lar_date );
|
||||
sscanf( ar_hdr.hdr.ar_nxtmem, "%lld", &offset );
|
||||
|
||||
if( !lar_namlen )
|
||||
if ( !lar_namlen )
|
||||
continue;
|
||||
|
||||
ar_hdr.hdr._ar_name.ar_name[ lar_namlen ] = '\0';
|
||||
@@ -469,10 +465,10 @@ void file_archscan(char *archive, scanback func, void *closure)
|
||||
int fd;
|
||||
char fl_magic[SAIAMAG];
|
||||
|
||||
if(( fd = open(archive, O_RDONLY, 0)) < 0)
|
||||
if (( fd = open(archive, O_RDONLY, 0)) < 0)
|
||||
return;
|
||||
|
||||
if(read( fd, fl_magic, SAIAMAG) != SAIAMAG
|
||||
|
||||
if (read( fd, fl_magic, SAIAMAG) != SAIAMAG
|
||||
|| lseek(fd, 0, SEEK_SET) == -1)
|
||||
{
|
||||
close(fd);
|
||||
@@ -491,7 +487,7 @@ void file_archscan(char *archive, scanback func, void *closure)
|
||||
file_archscan_big(fd, archive, func, closure);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
close( fd );
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
*
|
||||
* 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() - 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()
|
||||
@@ -53,45 +53,45 @@
|
||||
/* Supply missing prototypes for lbr$-routines*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int lbr$set_module(
|
||||
void **,
|
||||
unsigned long *,
|
||||
struct dsc$descriptor_s *,
|
||||
unsigned short *,
|
||||
void * );
|
||||
int lbr$set_module(
|
||||
void **,
|
||||
unsigned long *,
|
||||
struct dsc$descriptor_s *,
|
||||
unsigned short *,
|
||||
void * );
|
||||
|
||||
int lbr$open( void **,
|
||||
struct dsc$descriptor_s *,
|
||||
void *,
|
||||
void *,
|
||||
void *,
|
||||
void *,
|
||||
void * );
|
||||
struct dsc$descriptor_s *,
|
||||
void *,
|
||||
void *,
|
||||
void *,
|
||||
void *,
|
||||
void * );
|
||||
|
||||
int lbr$ini_control(
|
||||
void **,
|
||||
unsigned long *,
|
||||
unsigned long *,
|
||||
void * );
|
||||
void **,
|
||||
unsigned long *,
|
||||
unsigned long *,
|
||||
void * );
|
||||
|
||||
int lbr$get_index(
|
||||
void **,
|
||||
unsigned long *,
|
||||
int (*func)( struct dsc$descriptor_s *, unsigned long *),
|
||||
void * );
|
||||
void **,
|
||||
unsigned long *,
|
||||
int (*func)( struct dsc$descriptor_s *, unsigned long *),
|
||||
void * );
|
||||
|
||||
int lbr$close(
|
||||
void ** );
|
||||
void ** );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
static void
|
||||
file_cvttime(
|
||||
file_cvttime(
|
||||
unsigned int *curtime,
|
||||
time_t *unixtime )
|
||||
{
|
||||
@@ -108,10 +108,10 @@ file_cvttime(
|
||||
# define min( a,b ) ((a)<(b)?(a):(b))
|
||||
|
||||
void
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
scanback func,
|
||||
void *closure )
|
||||
file_dirscan(
|
||||
char *dir,
|
||||
scanback func,
|
||||
void *closure )
|
||||
{
|
||||
|
||||
struct FAB xfab;
|
||||
@@ -129,8 +129,8 @@ file_dirscan(
|
||||
f.f_root.ptr = dir;
|
||||
f.f_root.len = strlen( dir );
|
||||
|
||||
/* get the input file specification
|
||||
*/
|
||||
/* get the input file specification
|
||||
*/
|
||||
xnam = cc$rms_nam;
|
||||
xnam.nam$l_esa = esa;
|
||||
xnam.nam$b_ess = sizeof( esa ) - 1;
|
||||
@@ -138,111 +138,111 @@ file_dirscan(
|
||||
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$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_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 ( DEBUG_BINDSCAN )
|
||||
printf( "scan directory %s\n", dir );
|
||||
|
||||
if ( !( status & 1 ) )
|
||||
return;
|
||||
return;
|
||||
|
||||
|
||||
|
||||
/* Add bogus directory for [000000] */
|
||||
|
||||
if( !strcmp( dir, "[000000]" ) )
|
||||
if ( !strcmp( dir, "[000000]" ) )
|
||||
{
|
||||
(*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
|
||||
(*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
|
||||
}
|
||||
|
||||
/* Add bogus directory for [] */
|
||||
|
||||
if( !strcmp( dir, "[]" ) )
|
||||
if ( !strcmp( dir, "[]" ) )
|
||||
{
|
||||
(*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
|
||||
(*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
|
||||
(*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
|
||||
(*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
|
||||
}
|
||||
|
||||
string_new( filename2 );
|
||||
while ( (status = sys$search( &xfab )) & 1 )
|
||||
{
|
||||
char *s;
|
||||
time_t time;
|
||||
char *s;
|
||||
time_t time;
|
||||
|
||||
/* "I think that might work" - eml */
|
||||
/* "I think that might work" - eml */
|
||||
|
||||
sys$open( &xfab );
|
||||
sys$close( &xfab );
|
||||
sys$open( &xfab );
|
||||
sys$close( &xfab );
|
||||
|
||||
file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
|
||||
file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
|
||||
|
||||
filename[xnam.nam$b_rsl] = '\0';
|
||||
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 */
|
||||
/* 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;
|
||||
}
|
||||
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 );
|
||||
path_build( &f, filename2, 0 );
|
||||
path_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);
|
||||
*/
|
||||
/*
|
||||
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)( closure, filename2->value, 1 /* time valid */, time );
|
||||
(*func)( closure, filename2->value, 1 /* time valid */, time );
|
||||
}
|
||||
string_free( filename2 );
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
file_time(
|
||||
char *filename,
|
||||
time_t *time )
|
||||
char *filename,
|
||||
time_t *time )
|
||||
{
|
||||
/* This should never be called, as all files are */
|
||||
/* timestampped in file_dirscan() and file_archscan() */
|
||||
return -1;
|
||||
/* This should never be called, as all files are */
|
||||
/* timestampped in file_dirscan() and file_archscan() */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *VMS_archive = 0;
|
||||
@@ -251,12 +251,12 @@ static void *VMS_closure;
|
||||
static void *context;
|
||||
|
||||
static int
|
||||
file_archmember(
|
||||
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};
|
||||
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
|
||||
|
||||
struct mhddef *mhd;
|
||||
char filename[128];
|
||||
@@ -271,19 +271,19 @@ file_archmember(
|
||||
bufdsc.dsc$a_pointer = filename;
|
||||
bufdsc.dsc$w_length = sizeof( filename );
|
||||
status = lbr$set_module( &context, rfa, &bufdsc,
|
||||
&bufdsc.dsc$w_length, NULL );
|
||||
&bufdsc.dsc$w_length, NULL );
|
||||
|
||||
if ( !(status & 1) )
|
||||
return ( 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;
|
||||
for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; ++i, ++p )
|
||||
filename[ i ] = *p;
|
||||
|
||||
filename[i] = '\0';
|
||||
filename[ i ] = '\0';
|
||||
|
||||
sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
|
||||
|
||||
@@ -292,14 +292,11 @@ file_archmember(
|
||||
return ( 1 );
|
||||
}
|
||||
|
||||
void
|
||||
file_archscan(
|
||||
char *archive,
|
||||
scanback func,
|
||||
void *closure )
|
||||
|
||||
void file_archscan( char * archive, scanback func, void * closure )
|
||||
{
|
||||
static struct dsc$descriptor_s library =
|
||||
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
|
||||
{0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
|
||||
|
||||
unsigned long lfunc = LBR$C_READ;
|
||||
unsigned long typ = LBR$C_TYP_UNK;
|
||||
@@ -313,14 +310,14 @@ file_archscan(
|
||||
|
||||
status = lbr$ini_control( &context, &lfunc, &typ, NULL );
|
||||
if ( !( status & 1 ) )
|
||||
return;
|
||||
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;
|
||||
return;
|
||||
|
||||
(void) lbr$get_index( &context, &index, file_archmember, NULL );
|
||||
|
||||
@@ -328,4 +325,3 @@ file_archscan(
|
||||
}
|
||||
|
||||
# endif /* VMS */
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2001-2004 David Abrahams.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -1,39 +1,37 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright 2001-2004 David Abrahams.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
#ifndef FRAMES_DWA20011021_H
|
||||
# define FRAMES_DWA20011021_H
|
||||
#define FRAMES_DWA20011021_H
|
||||
|
||||
# include "lists.h"
|
||||
# include "modules.h"
|
||||
#include "lists.h"
|
||||
#include "modules.h"
|
||||
|
||||
typedef struct _PARSE PARSE;
|
||||
typedef struct frame FRAME;
|
||||
|
||||
struct frame
|
||||
{
|
||||
FRAME* prev;
|
||||
/** The nearest enclosing frame for which module->user_module is
|
||||
true. */
|
||||
FRAME* prev_user;
|
||||
LOL args[1];
|
||||
module_t* module;
|
||||
PARSE* procedure;
|
||||
char* rulename;
|
||||
FRAME * prev;
|
||||
/* The nearest enclosing frame for which module->user_module is true. */
|
||||
FRAME * prev_user;
|
||||
LOL args[ 1 ];
|
||||
module_t * module;
|
||||
PARSE * procedure;
|
||||
char * rulename;
|
||||
};
|
||||
|
||||
/* When call into Python is in progress, this
|
||||
variable points to the bjam frame that
|
||||
was current at the moment of call. When the call
|
||||
completes, the variable is not defined. Further,
|
||||
if Jam calls Python which calls Jam and so on,
|
||||
this variable only keeps the most recent Jam frame. */
|
||||
extern struct frame *frame_before_python_call;
|
||||
|
||||
void frame_init( FRAME* ); /* implemented in compile.c */
|
||||
void frame_free( FRAME* ); /* implemented in compile.c */
|
||||
/* When call into Python is in progress, this variable points to the bjam frame
|
||||
* that was current at the moment of call. When the call completes, the variable
|
||||
* is not defined. Further, if Jam calls Python which calls Jam and so on, this
|
||||
* variable only keeps the most recent Jam frame.
|
||||
*/
|
||||
extern struct frame * frame_before_python_call;
|
||||
|
||||
void frame_init( FRAME * ); /* implemented in compile.c */
|
||||
void frame_free( FRAME * ); /* implemented in compile.c */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1994 Christopher Seiwald. All rights reserved.
|
||||
* Copyright 1994 Christopher Seiwald. All rights reserved.
|
||||
*
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
@@ -9,149 +9,144 @@
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* * 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
|
||||
* glob() - match a string against a simple pattern
|
||||
*
|
||||
* Internal functions:
|
||||
*
|
||||
* globchars() - build a bitlist to check for character group match
|
||||
* 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 */
|
||||
# define BITLISTSIZE 16 /* bytes used for [chars] in compiled expr */
|
||||
|
||||
static void globchars( char * s, char * e, char * b );
|
||||
|
||||
static void globchars( char *s, char *e, char *b );
|
||||
|
||||
/*
|
||||
* glob() - match a string against a simple pattern
|
||||
* glob() - match a string against a simple pattern.
|
||||
*/
|
||||
|
||||
int
|
||||
glob(
|
||||
register char *c,
|
||||
register char *s )
|
||||
int glob( char * c, char * s )
|
||||
{
|
||||
char bitlist[ BITLISTSIZE ];
|
||||
char *here;
|
||||
char bitlist[ BITLISTSIZE ];
|
||||
char * here;
|
||||
|
||||
for( ;; )
|
||||
switch( *c++ )
|
||||
{
|
||||
case '\0':
|
||||
return *s ? -1 : 0;
|
||||
for ( ; ; )
|
||||
switch ( *c++ )
|
||||
{
|
||||
case '\0':
|
||||
return *s ? -1 : 0;
|
||||
|
||||
case '?':
|
||||
if( !*s++ )
|
||||
return 1;
|
||||
break;
|
||||
case '?':
|
||||
if ( !*s++ )
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
/* scan for matching ] */
|
||||
case '[':
|
||||
/* Scan for matching ]. */
|
||||
|
||||
here = c;
|
||||
do if( !*c++ )
|
||||
return 1;
|
||||
while( here == c || *c != ']' );
|
||||
c++;
|
||||
here = c;
|
||||
do if ( !*c++ ) return 1;
|
||||
while ( ( here == c ) || ( *c != ']' ) );
|
||||
++c;
|
||||
|
||||
/* build character class bitlist */
|
||||
/* Build character class bitlist. */
|
||||
|
||||
globchars( here, c, bitlist );
|
||||
globchars( here, c, bitlist );
|
||||
|
||||
if( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
|
||||
return 1;
|
||||
s++;
|
||||
break;
|
||||
if ( !CHECK_BIT( bitlist, *(unsigned char *)s ) )
|
||||
return 1;
|
||||
++s;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
here = s;
|
||||
case '*':
|
||||
here = s;
|
||||
|
||||
while( *s )
|
||||
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. */
|
||||
/* 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;
|
||||
while ( s != here )
|
||||
{
|
||||
int r;
|
||||
|
||||
/* A fast path for the last token in a pattern */
|
||||
/* A fast path for the last token in a pattern. */
|
||||
r = *c ? glob( c, s ) : *s ? -1 : 0;
|
||||
|
||||
r = *c ? glob( c, s ) : *s ? -1 : 0;
|
||||
if ( !r )
|
||||
return 0;
|
||||
if ( r < 0 )
|
||||
return 1;
|
||||
--s;
|
||||
}
|
||||
break;
|
||||
|
||||
if( !r )
|
||||
return 0;
|
||||
else if( r < 0 )
|
||||
return 1;
|
||||
case '\\':
|
||||
/* Force literal match of next char. */
|
||||
if ( !*c || ( *s++ != *c++ ) )
|
||||
return 1;
|
||||
break;
|
||||
|
||||
--s;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
/* Force literal match of next char. */
|
||||
|
||||
if( !*c || *s++ != *c++ )
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if( *s++ != c[-1] )
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if ( *s++ != c[ -1 ] )
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* globchars() - build a bitlist to check for character group match
|
||||
* globchars() - build a bitlist to check for character group match.
|
||||
*/
|
||||
|
||||
static void
|
||||
globchars(
|
||||
char *s,
|
||||
char *e,
|
||||
char *b )
|
||||
static void globchars( char * s, char * e, char * b )
|
||||
{
|
||||
int neg = 0;
|
||||
int neg = 0;
|
||||
|
||||
memset( b, '\0', BITLISTSIZE );
|
||||
memset( b, '\0', BITLISTSIZE );
|
||||
|
||||
if( *s == '^')
|
||||
neg++, s++;
|
||||
if ( *s == '^' )
|
||||
{
|
||||
++neg;
|
||||
++s;
|
||||
}
|
||||
|
||||
while( s < e )
|
||||
{
|
||||
int c;
|
||||
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;
|
||||
}
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't include \0 in either $[chars] or $[^chars] */
|
||||
if ( neg )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < BITLISTSIZE; ++i )
|
||||
b[ i ] ^= 0377;
|
||||
}
|
||||
|
||||
b[0] &= 0376;
|
||||
/* Do not include \0 in either $[chars] or $[^chars]. */
|
||||
b[0] &= 0376;
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
# include "compile.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* hash.c - simple in-memory hashing routines
|
||||
/*
|
||||
* hash.c - simple in-memory hashing routines
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
@@ -29,64 +29,68 @@
|
||||
#define HASH_DEBUG_PROFILE 1
|
||||
/* */
|
||||
|
||||
char *hashsccssid="@(#)hash.c 1.14 () 6/20/88";
|
||||
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;
|
||||
unsigned int keyval; /* for quick comparisons */
|
||||
} ;
|
||||
struct hashhdr
|
||||
{
|
||||
struct item * next;
|
||||
unsigned int keyval; /* for quick comparisons */
|
||||
};
|
||||
|
||||
/* This structure overlays the one handed to hashenter(). */
|
||||
/* It's actual size is given to hashinit(). */
|
||||
/* This structure overlays the one handed to hashenter(). Its actual size is
|
||||
* given to hashinit().
|
||||
*/
|
||||
|
||||
struct hashdata {
|
||||
char *key;
|
||||
/* rest of user data */
|
||||
} ;
|
||||
struct hashdata
|
||||
{
|
||||
char * key;
|
||||
/* rest of user data */
|
||||
};
|
||||
|
||||
typedef struct item {
|
||||
struct hashhdr hdr;
|
||||
struct hashdata data;
|
||||
typedef struct item
|
||||
{
|
||||
struct hashhdr hdr;
|
||||
struct hashdata data;
|
||||
} ITEM ;
|
||||
|
||||
# define MAX_LISTS 32
|
||||
|
||||
struct hash
|
||||
struct hash
|
||||
{
|
||||
/*
|
||||
* the hash table, just an array of item pointers
|
||||
*/
|
||||
struct {
|
||||
int nel;
|
||||
ITEM **base;
|
||||
} tab;
|
||||
/*
|
||||
* 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 */
|
||||
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 ] */
|
||||
/*
|
||||
* the array of records, maintained by these routines
|
||||
* essentially a microallocator
|
||||
*/
|
||||
struct {
|
||||
int more; /* how many more ITEMs fit in lists[ list ] */
|
||||
ITEM *free; /* free list of items */
|
||||
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[] */
|
||||
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;
|
||||
struct {
|
||||
int nel; /* total ITEMs held by this list */
|
||||
char *base; /* base of ITEMs array */
|
||||
} lists[ MAX_LISTS ];
|
||||
} items;
|
||||
|
||||
char *name; /* just for hashstats() */
|
||||
} ;
|
||||
char * name; /* just for hashstats() */
|
||||
};
|
||||
|
||||
static void hashrehash( struct hash *hp );
|
||||
static void hashstat( struct hash *hp );
|
||||
@@ -96,14 +100,40 @@ static void hash_mem_free(size_t datalen, void * data);
|
||||
static void hash_mem_finalizer(char * key, struct hash * hp);
|
||||
#endif
|
||||
|
||||
static unsigned int hash_keyval( const char * key_ )
|
||||
static unsigned int jenkins_one_at_a_time_hash(const unsigned char *key)
|
||||
{
|
||||
unsigned int hash = 0;
|
||||
|
||||
while ( *key )
|
||||
{
|
||||
hash += *key++;
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 11);
|
||||
hash += (hash << 15);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/*
|
||||
static unsigned int knuth_hash(const unsigned char *key)
|
||||
{
|
||||
const unsigned char * key = (const unsigned char *)key_;
|
||||
unsigned int keyval = *key;
|
||||
while( *key )
|
||||
while ( *key )
|
||||
keyval = keyval * 2147059363 + *key++;
|
||||
return keyval;
|
||||
}
|
||||
*/
|
||||
|
||||
static unsigned int hash_keyval( const char * key_ )
|
||||
{
|
||||
/*
|
||||
return knuth_hash((const unsigned char *)key_);
|
||||
*/
|
||||
return jenkins_one_at_a_time_hash((const unsigned char *)key_);
|
||||
}
|
||||
|
||||
#define hash_bucket(hp,keyval) ((hp)->tab.base + ( (keyval) % (hp)->tab.nel ))
|
||||
|
||||
@@ -116,14 +146,14 @@ static ITEM * hash_search(
|
||||
struct hash *hp,
|
||||
unsigned int keyval,
|
||||
const char * keydata,
|
||||
ITEM ** previous )
|
||||
ITEM * * previous )
|
||||
{
|
||||
ITEM * i = *hash_bucket(hp,keyval);
|
||||
ITEM * p = 0;
|
||||
|
||||
for ( ; i; i = i->hdr.next )
|
||||
{
|
||||
if( keyval == i->hdr.keyval &&
|
||||
if ( ( keyval == i->hdr.keyval ) &&
|
||||
!strcmp( i->data.key, keydata ) )
|
||||
{
|
||||
if (previous)
|
||||
@@ -134,7 +164,7 @@ static ITEM * hash_search(
|
||||
}
|
||||
p = i;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -152,7 +182,7 @@ hash_free(
|
||||
ITEM * i = 0;
|
||||
ITEM * prev = 0;
|
||||
unsigned int keyval = hash_keyval(data->key);
|
||||
|
||||
|
||||
i = hash_search( hp, keyval, data->key, &prev );
|
||||
if (i)
|
||||
{
|
||||
@@ -166,7 +196,7 @@ hash_free(
|
||||
hp->items.free = i;
|
||||
/* we have another item */
|
||||
hp->items.more++;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -178,32 +208,32 @@ hash_free(
|
||||
|
||||
int
|
||||
hashitem(
|
||||
register struct hash *hp,
|
||||
HASHDATA **data,
|
||||
int enter )
|
||||
register struct hash *hp,
|
||||
HASHDATA **data,
|
||||
int enter )
|
||||
{
|
||||
register ITEM *i;
|
||||
char *b = (*data)->key;
|
||||
unsigned int keyval = hash_keyval(b);
|
||||
|
||||
register ITEM *i;
|
||||
char *b = (*data)->key;
|
||||
unsigned int keyval = hash_keyval(b);
|
||||
|
||||
#ifdef HASH_DEBUG_PROFILE
|
||||
profile_frame prof[1];
|
||||
if ( DEBUG_PROFILE )
|
||||
profile_enter( 0, prof );
|
||||
#endif
|
||||
|
||||
if( enter && !hp->items.more )
|
||||
hashrehash( hp );
|
||||
if ( enter && !hp->items.more )
|
||||
hashrehash( hp );
|
||||
|
||||
if( !enter && !hp->items.nel )
|
||||
if ( !enter && !hp->items.nel )
|
||||
{
|
||||
#ifdef HASH_DEBUG_PROFILE
|
||||
if ( DEBUG_PROFILE )
|
||||
profile_exit( prof );
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
i = hash_search( hp, keyval, (*data)->key, 0 );
|
||||
if (i)
|
||||
{
|
||||
@@ -214,10 +244,10 @@ hashitem(
|
||||
return !0;
|
||||
}
|
||||
|
||||
if( enter )
|
||||
if ( enter )
|
||||
{
|
||||
ITEM **base = hash_bucket(hp,keyval);
|
||||
|
||||
ITEM * * base = hash_bucket(hp,keyval);
|
||||
|
||||
/* try to grab one from the free list */
|
||||
if ( hp->items.free )
|
||||
{
|
||||
@@ -248,7 +278,7 @@ hashitem(
|
||||
if ( DEBUG_PROFILE )
|
||||
profile_exit( prof );
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -257,57 +287,56 @@ hashitem(
|
||||
|
||||
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 *)hash_mem_alloc( hp->items.datalen, hp->items.more * hp->items.size );
|
||||
int i = ++hp->items.list;
|
||||
hp->items.more = i ? 2 * hp->items.nel : hp->inel;
|
||||
hp->items.next = (char *)hash_mem_alloc( hp->items.datalen, hp->items.more * hp->items.size );
|
||||
hp->items.free = 0;
|
||||
|
||||
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 )
|
||||
hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
|
||||
hp->items.lists[i].nel = hp->items.more;
|
||||
hp->items.lists[i].base = hp->items.next;
|
||||
hp->items.nel += hp->items.more;
|
||||
|
||||
hp->tab.nel = hp->items.nel * hp->bloat;
|
||||
hp->tab.base = (ITEM **)hash_mem_alloc( hp->items.datalen, hp->tab.nel * sizeof(ITEM **) );
|
||||
if ( hp->tab.base )
|
||||
hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
|
||||
|
||||
memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
|
||||
hp->tab.nel = hp->items.nel * hp->bloat;
|
||||
hp->tab.base = (ITEM **)hash_mem_alloc( hp->items.datalen, 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;
|
||||
memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
|
||||
|
||||
for( ; nel--; next += hp->items.size )
|
||||
{
|
||||
register ITEM *i = (ITEM *)next;
|
||||
ITEM **ip = hp->tab.base + i->hdr.keyval % hp->tab.nel;
|
||||
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;
|
||||
/* code currently assumes rehashing only when there are no free items */
|
||||
assert( i->data.key != 0 );
|
||||
|
||||
i->hdr.next = *ip;
|
||||
*ip = i;
|
||||
}
|
||||
}
|
||||
assert( i->data.key != 0 );
|
||||
|
||||
i->hdr.next = *ip;
|
||||
*ip = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hashenumerate( struct hash *hp, void (*f)(void*,void*), void* data )
|
||||
void hashenumerate( struct hash * hp, void (* f)( void *, void * ), void * data )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i <= hp->items.list; i++ )
|
||||
for ( i = 0; i <= hp->items.list; ++i )
|
||||
{
|
||||
char *next = hp->items.lists[i].base;
|
||||
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 )
|
||||
for ( ; nel--; next += hp->items.size )
|
||||
{
|
||||
register ITEM *i = (ITEM *)next;
|
||||
|
||||
if ( i->data.key != 0 ) /* don't enumerate freed items */
|
||||
f(&i->data, data);
|
||||
ITEM * i = (ITEM *)next;
|
||||
if ( i->data.key != 0 ) /* DO not enumerate freed items. */
|
||||
f( &i->data, data );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -321,25 +350,25 @@ void hashenumerate( struct hash *hp, void (*f)(void*,void*), void* data )
|
||||
*/
|
||||
|
||||
struct hash *
|
||||
hashinit(
|
||||
int datalen,
|
||||
char *name )
|
||||
hashinit(
|
||||
int datalen,
|
||||
char *name )
|
||||
{
|
||||
struct hash *hp = (struct hash *)hash_mem_alloc( datalen, sizeof( *hp ) );
|
||||
struct hash *hp = (struct hash *)hash_mem_alloc( datalen, sizeof( *hp ) );
|
||||
|
||||
hp->bloat = 3;
|
||||
hp->tab.nel = 0;
|
||||
hp->tab.base = (ITEM **)0;
|
||||
hp->items.more = 0;
|
||||
hp->bloat = 3;
|
||||
hp->tab.nel = 0;
|
||||
hp->tab.base = (ITEM **)0;
|
||||
hp->items.more = 0;
|
||||
hp->items.free = 0;
|
||||
hp->items.datalen = datalen;
|
||||
hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
|
||||
hp->items.list = -1;
|
||||
hp->items.nel = 0;
|
||||
hp->inel = /* */ 11 /*/ 47 /* */;
|
||||
hp->name = name;
|
||||
hp->items.datalen = datalen;
|
||||
hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
|
||||
hp->items.list = -1;
|
||||
hp->items.nel = 0;
|
||||
hp->inel = 11 /* 47 */;
|
||||
hp->name = name;
|
||||
|
||||
return hp;
|
||||
return hp;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -349,19 +378,19 @@ hashinit(
|
||||
void
|
||||
hashdone( struct hash *hp )
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if( !hp )
|
||||
return;
|
||||
if ( !hp )
|
||||
return;
|
||||
|
||||
if( DEBUG_MEM || DEBUG_PROFILE )
|
||||
hashstat( hp );
|
||||
if ( DEBUG_MEM || DEBUG_PROFILE )
|
||||
hashstat( hp );
|
||||
|
||||
if( hp->tab.base )
|
||||
hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
|
||||
for( i = 0; i <= hp->items.list; i++ )
|
||||
hash_mem_free( hp->items.datalen, hp->items.lists[i].base );
|
||||
hash_mem_free( hp->items.datalen, (char *)hp );
|
||||
if ( hp->tab.base )
|
||||
hash_mem_free( hp->items.datalen, (char *)hp->tab.base );
|
||||
for ( i = 0; i <= hp->items.list; ++i )
|
||||
hash_mem_free( hp->items.datalen, hp->items.lists[i].base );
|
||||
hash_mem_free( hp->items.datalen, (char *)hp );
|
||||
}
|
||||
|
||||
static void * hash_mem_alloc(size_t datalen, size_t size)
|
||||
@@ -400,31 +429,31 @@ static void hash_mem_finalizer(char * key, struct hash * hp)
|
||||
|
||||
/* ---- */
|
||||
|
||||
static void
|
||||
hashstat( struct hash *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;
|
||||
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;
|
||||
int here;
|
||||
|
||||
for( i = nel; i > 0; i-- )
|
||||
{
|
||||
if( here = ( *tab++ != (ITEM *)0 ) )
|
||||
count++;
|
||||
if( here && !run )
|
||||
sets++;
|
||||
run = 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 );
|
||||
printf( "%s table: %d+%d+%d (%dK+%ldK) 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 );
|
||||
}
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* hash.h - simple in-memory hashing routines
|
||||
* hash.h - simple in-memory hashing routines
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_JAM_HASH_H
|
||||
#define BOOST_JAM_HASH_H
|
||||
|
||||
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 );
|
||||
int hash_free( struct hash *hp, HASHDATA *data);
|
||||
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 );
|
||||
int hash_free ( struct hash * hp, HASHDATA * data);
|
||||
|
||||
# define hashenter( hp, data ) (!hashitem( hp, data, !0 ))
|
||||
# define hashcheck( hp, data ) hashitem( hp, data, 0 )
|
||||
#define hashenter( hp, data ) ( !hashitem( hp, data, !0 ) )
|
||||
#define hashcheck( hp, data ) hashitem( hp, data, 0 )
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,41 +19,41 @@
|
||||
/*
|
||||
* Craig W. McPheeters, Alias|Wavefront.
|
||||
*
|
||||
* hcache.c hcache.h - handle cacheing of #includes in source files
|
||||
* hcache.c hcache.h - handle cacheing of #includes in source files.
|
||||
*
|
||||
* Create a cache of files scanned for headers. When starting jam,
|
||||
* look for the cache file and load it if present. When finished the
|
||||
* binding phase, create a new header cache. The cache contains
|
||||
* files, their timestamps and the header files found in their scan.
|
||||
* During the binding phase of jam, look in the header cache first for
|
||||
* the headers contained in a file. If the cache is present and
|
||||
* valid, use its contents. This results in dramatic speedups with
|
||||
* Create a cache of files scanned for headers. When starting jam, look for the
|
||||
* cache file and load it if present. When finished the binding phase, create a
|
||||
* new header cache. The cache contains files, their timestamps and the header
|
||||
* files found in their scan. During the binding phase of jam, look in the
|
||||
* header cache first for the headers contained in a file. If the cache is
|
||||
* present and valid, use its contents. This results in dramatic speedups with
|
||||
* large projects (eg. 3min -> 1min startup for one project.)
|
||||
*
|
||||
* External routines:
|
||||
* hcache_init() - read and parse the local .jamdeps file.
|
||||
* hcache_done() - write a new .jamdeps file
|
||||
* hcache() - return list of headers on target. Use cache or do a scan.
|
||||
*
|
||||
* The dependency file format is an ascii file with 1 line per target.
|
||||
* Each line has the following fields:
|
||||
* hcache_done() - write a new .jamdeps file.
|
||||
* hcache() - return list of headers on target. Use cache or do a scan.
|
||||
*
|
||||
* The dependency file format is an ASCII file with 1 line per target. Each line
|
||||
* has the following fields:
|
||||
* @boundname@ timestamp @file@ @file@ @file@ ... \n
|
||||
* */
|
||||
|
||||
struct hcachedata {
|
||||
char *boundname;
|
||||
time_t time;
|
||||
LIST *includes;
|
||||
LIST *hdrscan; /* the HDRSCAN value for this target */
|
||||
int age; /* if too old, we'll remove it from cache */
|
||||
struct hcachedata *next;
|
||||
} ;
|
||||
*/
|
||||
|
||||
typedef struct hcachedata HCACHEDATA ;
|
||||
|
||||
struct hcachedata
|
||||
{
|
||||
char * boundname;
|
||||
time_t time;
|
||||
LIST * includes;
|
||||
LIST * hdrscan; /* the HDRSCAN value for this target */
|
||||
int age; /* if too old, we'll remove it from cache */
|
||||
HCACHEDATA * next;
|
||||
};
|
||||
|
||||
static struct hash *hcachehash = 0;
|
||||
static HCACHEDATA *hcachelist = 0;
|
||||
|
||||
static struct hash * hcachehash = 0;
|
||||
static HCACHEDATA * hcachelist = 0;
|
||||
|
||||
static int queries = 0;
|
||||
static int hits = 0;
|
||||
@@ -62,294 +62,305 @@ static int hits = 0;
|
||||
#define CACHE_RECORD_HEADER "header"
|
||||
#define CACHE_RECORD_END "end"
|
||||
|
||||
|
||||
/*
|
||||
* Return the name of the header cache file. May return NULL.
|
||||
* Return the name of the header cache file. May return NULL.
|
||||
*
|
||||
* The user sets this by setting the HCACHEFILE variable in a Jamfile.
|
||||
* We cache the result so the user can't change the cache file during
|
||||
* header scanning.
|
||||
* The user sets this by setting the HCACHEFILE variable in a Jamfile. We cache
|
||||
* the result so the user can not change the cache file during header scanning.
|
||||
*/
|
||||
static char*
|
||||
cache_name(void)
|
||||
|
||||
static char * cache_name( void )
|
||||
{
|
||||
static char* name = 0;
|
||||
if (!name) {
|
||||
LIST *hcachevar = var_get("HCACHEFILE");
|
||||
static char * name = 0;
|
||||
if ( !name )
|
||||
{
|
||||
LIST * hcachevar = var_get( "HCACHEFILE" );
|
||||
|
||||
if (hcachevar) {
|
||||
TARGET *t = bindtarget( hcachevar->string );
|
||||
if ( hcachevar )
|
||||
{
|
||||
TARGET * t = bindtarget( hcachevar->string );
|
||||
|
||||
pushsettings( t->settings );
|
||||
/* Don't expect cache file to be generated, so pass 0
|
||||
as third argument to search. */
|
||||
t->boundname = search( t->name, &t->time, 0 );
|
||||
popsettings( t->settings );
|
||||
pushsettings( t->settings );
|
||||
/* Do not expect the cache file to be generated, so pass 0 as the
|
||||
* third argument to search. Expect the location to be specified via
|
||||
* LOCATE, so pass 0 as the fourth arugment.
|
||||
*/
|
||||
t->boundname = search( t->name, &t->time, 0, 0 );
|
||||
popsettings( t->settings );
|
||||
|
||||
if (hcachevar) {
|
||||
name = copystr(t->boundname);
|
||||
}
|
||||
}
|
||||
if ( hcachevar )
|
||||
name = copystr( t->boundname );
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return the maximum age a cache entry can have before it is purged
|
||||
* from the cache.
|
||||
* Return the maximum age a cache entry can have before it is purged ftom the
|
||||
* cache.
|
||||
*/
|
||||
static int
|
||||
cache_maxage(void)
|
||||
|
||||
static int cache_maxage( void )
|
||||
{
|
||||
int age = 100;
|
||||
LIST *var = var_get("HCACHEMAXAGE");
|
||||
|
||||
if (var) {
|
||||
age = atoi(var->string);
|
||||
if (age < 0)
|
||||
age = 0;
|
||||
LIST * var = var_get( "HCACHEMAXAGE" );
|
||||
if ( var )
|
||||
{
|
||||
age = atoi( var->string );
|
||||
if ( age < 0 )
|
||||
age = 0;
|
||||
}
|
||||
|
||||
return age;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read a netstring. The caveat is that the string can't contain
|
||||
* ASCII 0. The returned value is as returned by newstr(), so it need
|
||||
* not be freed.
|
||||
* Read a netstring. The caveat is that the string can not contain ASCII 0. The
|
||||
* returned value is as returned by newstr(), so it need not be freed.
|
||||
*/
|
||||
char*
|
||||
read_netstring(FILE* f)
|
||||
|
||||
char * read_netstring( FILE * f )
|
||||
{
|
||||
unsigned long len;
|
||||
static char* buf = NULL;
|
||||
static char * buf = NULL;
|
||||
static unsigned long buf_len = 0;
|
||||
|
||||
if (fscanf(f, " %9lu", &len) != 1)
|
||||
return NULL;
|
||||
if (fgetc(f) != (int)'\t')
|
||||
return NULL;
|
||||
if ( fscanf( f, " %9lu", &len ) != 1 )
|
||||
return NULL;
|
||||
if ( fgetc( f ) != (int)'\t' )
|
||||
return NULL;
|
||||
|
||||
if (len > 1024 * 64)
|
||||
return NULL; /* sanity check */
|
||||
if ( len > 1024 * 64 )
|
||||
return NULL; /* sanity check */
|
||||
|
||||
if (len > buf_len)
|
||||
if ( len > buf_len )
|
||||
{
|
||||
unsigned long new_len = buf_len * 2;
|
||||
if (new_len < len)
|
||||
new_len = len;
|
||||
buf = (char*)BJAM_REALLOC(buf, new_len + 1);
|
||||
if (buf)
|
||||
buf_len = new_len;
|
||||
unsigned long new_len = buf_len * 2;
|
||||
if ( new_len < len )
|
||||
new_len = len;
|
||||
buf = (char *)BJAM_REALLOC( buf, new_len + 1 );
|
||||
if ( buf )
|
||||
buf_len = new_len;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
return NULL;
|
||||
if ( !buf )
|
||||
return NULL;
|
||||
|
||||
if (fread(buf, 1, len, f) != len)
|
||||
return NULL;
|
||||
if (fgetc(f) != (int)'\n')
|
||||
return NULL;
|
||||
if ( fread( buf, 1, len, f ) != len )
|
||||
return NULL;
|
||||
if ( fgetc( f ) != (int)'\n' )
|
||||
return NULL;
|
||||
|
||||
buf[len] = 0;
|
||||
return newstr(buf);
|
||||
buf[ len ] = 0;
|
||||
return newstr( buf );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write a netstring.
|
||||
*/
|
||||
void
|
||||
write_netstring(FILE* f, const char* s)
|
||||
|
||||
void write_netstring( FILE * f, char const * s )
|
||||
{
|
||||
if (!s)
|
||||
s = "";
|
||||
fprintf(f, "%lu\t%s\n", strlen(s), s);
|
||||
if ( !s )
|
||||
s = "";
|
||||
fprintf( f, "%lu\t%s\n", strlen( s ), s );
|
||||
}
|
||||
|
||||
void
|
||||
hcache_init()
|
||||
|
||||
void hcache_init()
|
||||
{
|
||||
HCACHEDATA cachedata, *c;
|
||||
FILE *f;
|
||||
char *version;
|
||||
int header_count = 0;
|
||||
char* hcachename;
|
||||
HCACHEDATA cachedata;
|
||||
HCACHEDATA * c;
|
||||
FILE * f;
|
||||
char * version;
|
||||
int header_count = 0;
|
||||
char * hcachename;
|
||||
|
||||
hcachehash = hashinit (sizeof (HCACHEDATA), "hcache");
|
||||
hcachehash = hashinit( sizeof( HCACHEDATA ), "hcache" );
|
||||
|
||||
if (! (hcachename = cache_name()))
|
||||
return;
|
||||
if ( !( hcachename = cache_name() ) )
|
||||
return;
|
||||
|
||||
if (! (f = fopen (hcachename, "rb" )))
|
||||
return;
|
||||
|
||||
version = read_netstring(f);
|
||||
if (!version || strcmp(version, CACHE_FILE_VERSION)) {
|
||||
fclose(f);
|
||||
return;
|
||||
}
|
||||
if ( !( f = fopen( hcachename, "rb" ) ) )
|
||||
return;
|
||||
|
||||
while (1)
|
||||
version = read_netstring( f );
|
||||
if ( !version || strcmp( version, CACHE_FILE_VERSION ) )
|
||||
{
|
||||
char* record_type;
|
||||
char *time_str;
|
||||
char *age_str;
|
||||
char *includes_count_str;
|
||||
char *hdrscan_count_str;
|
||||
int i, count;
|
||||
LIST *l;
|
||||
|
||||
record_type = read_netstring(f);
|
||||
if (!record_type) {
|
||||
fprintf(stderr, "invalid %s\n", hcachename);
|
||||
goto bail;
|
||||
}
|
||||
if (!strcmp(record_type, CACHE_RECORD_END)) {
|
||||
break;
|
||||
}
|
||||
if (strcmp(record_type, CACHE_RECORD_HEADER)) {
|
||||
fprintf(stderr, "invalid %s with record separator <%s>\n",
|
||||
hcachename, record_type ? record_type : "<null>");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
c = &cachedata;
|
||||
|
||||
c->boundname = read_netstring(f);
|
||||
time_str = read_netstring(f);
|
||||
age_str = read_netstring(f);
|
||||
includes_count_str = read_netstring(f);
|
||||
|
||||
if (!c->boundname || !time_str || !age_str
|
||||
|| !includes_count_str)
|
||||
{
|
||||
fprintf(stderr, "invalid %s\n", hcachename);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
c->time = atoi(time_str);
|
||||
c->age = atoi(age_str) + 1;
|
||||
|
||||
count = atoi(includes_count_str);
|
||||
for (l = 0, i = 0; i < count; i++) {
|
||||
char* s = read_netstring(f);
|
||||
if (!s) {
|
||||
fprintf(stderr, "invalid %s\n", hcachename);
|
||||
goto bail;
|
||||
}
|
||||
l = list_new(l, s);
|
||||
}
|
||||
c->includes = l;
|
||||
|
||||
hdrscan_count_str = read_netstring(f);
|
||||
if (!includes_count_str) {
|
||||
list_free(c->includes);
|
||||
fprintf(stderr, "invalid %s\n", hcachename);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
count = atoi(hdrscan_count_str);
|
||||
for (l = 0, i = 0; i < count; i++) {
|
||||
char* s = read_netstring(f);
|
||||
if (!s) {
|
||||
fprintf(stderr, "invalid %s\n", hcachename);
|
||||
goto bail;
|
||||
}
|
||||
l = list_new(l, s);
|
||||
}
|
||||
c->hdrscan = l;
|
||||
|
||||
if (!hashenter(hcachehash, (HASHDATA **)&c)) {
|
||||
fprintf(stderr, "can't insert header cache item, bailing on %s\n",
|
||||
hcachename);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
c->next = hcachelist;
|
||||
hcachelist = c;
|
||||
|
||||
header_count++;
|
||||
fclose( f );
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG_HEADER) {
|
||||
printf("hcache read from file %s\n", hcachename);
|
||||
while ( 1 )
|
||||
{
|
||||
char * record_type;
|
||||
char * time_str;
|
||||
char * age_str;
|
||||
char * includes_count_str;
|
||||
char * hdrscan_count_str;
|
||||
int i;
|
||||
int count;
|
||||
LIST * l;
|
||||
|
||||
record_type = read_netstring( f );
|
||||
if ( !record_type )
|
||||
{
|
||||
fprintf( stderr, "invalid %s\n", hcachename );
|
||||
goto bail;
|
||||
}
|
||||
if ( !strcmp( record_type, CACHE_RECORD_END ) )
|
||||
break;
|
||||
if ( strcmp( record_type, CACHE_RECORD_HEADER ) )
|
||||
{
|
||||
fprintf( stderr, "invalid %s with record separator <%s>\n",
|
||||
hcachename, record_type ? record_type : "<null>" );
|
||||
goto bail;
|
||||
}
|
||||
|
||||
c = &cachedata;
|
||||
|
||||
c->boundname = read_netstring( f );
|
||||
time_str = read_netstring( f );
|
||||
age_str = read_netstring( f );
|
||||
includes_count_str = read_netstring( f );
|
||||
|
||||
if ( !c->boundname || !time_str || !age_str || !includes_count_str )
|
||||
{
|
||||
fprintf( stderr, "invalid %s\n", hcachename );
|
||||
goto bail;
|
||||
}
|
||||
|
||||
c->time = atoi( time_str );
|
||||
c->age = atoi( age_str ) + 1;
|
||||
|
||||
count = atoi( includes_count_str );
|
||||
for ( l = 0, i = 0; i < count; ++i )
|
||||
{
|
||||
char * s = read_netstring( f );
|
||||
if ( !s )
|
||||
{
|
||||
fprintf( stderr, "invalid %s\n", hcachename );
|
||||
goto bail;
|
||||
}
|
||||
l = list_new( l, s );
|
||||
}
|
||||
c->includes = l;
|
||||
|
||||
hdrscan_count_str = read_netstring( f );
|
||||
if ( !includes_count_str )
|
||||
{
|
||||
list_free( c->includes );
|
||||
fprintf( stderr, "invalid %s\n", hcachename );
|
||||
goto bail;
|
||||
}
|
||||
|
||||
count = atoi( hdrscan_count_str );
|
||||
for ( l = 0, i = 0; i < count; ++i )
|
||||
{
|
||||
char * s = read_netstring( f );
|
||||
if ( !s )
|
||||
{
|
||||
fprintf( stderr, "invalid %s\n", hcachename );
|
||||
goto bail;
|
||||
}
|
||||
l = list_new( l, s );
|
||||
}
|
||||
c->hdrscan = l;
|
||||
|
||||
if ( !hashenter( hcachehash, (HASHDATA * *)&c ) )
|
||||
{
|
||||
fprintf( stderr, "can't insert header cache item, bailing on %s\n",
|
||||
hcachename );
|
||||
goto bail;
|
||||
}
|
||||
|
||||
c->next = hcachelist;
|
||||
hcachelist = c;
|
||||
|
||||
++header_count;
|
||||
}
|
||||
|
||||
|
||||
if ( DEBUG_HEADER )
|
||||
printf( "hcache read from file %s\n", hcachename );
|
||||
|
||||
bail:
|
||||
fclose(f);
|
||||
fclose( f );
|
||||
}
|
||||
|
||||
void
|
||||
hcache_done()
|
||||
|
||||
void hcache_done()
|
||||
{
|
||||
FILE *f;
|
||||
HCACHEDATA *c;
|
||||
int header_count = 0;
|
||||
char* hcachename;
|
||||
int maxage;
|
||||
|
||||
if (!hcachehash)
|
||||
return;
|
||||
FILE * f;
|
||||
HCACHEDATA * c;
|
||||
int header_count = 0;
|
||||
char * hcachename;
|
||||
int maxage;
|
||||
|
||||
if (! (hcachename = cache_name()))
|
||||
return;
|
||||
if ( !hcachehash )
|
||||
return;
|
||||
|
||||
if (! (f = fopen (hcachename, "wb" )))
|
||||
return;
|
||||
if ( !( hcachename = cache_name() ) )
|
||||
return;
|
||||
|
||||
if ( !( f = fopen( hcachename, "wb" ) ) )
|
||||
return;
|
||||
|
||||
maxage = cache_maxage();
|
||||
|
||||
/* print out the version */
|
||||
write_netstring(f, CACHE_FILE_VERSION);
|
||||
/* Print out the version. */
|
||||
write_netstring( f, CACHE_FILE_VERSION );
|
||||
|
||||
c = hcachelist;
|
||||
for (c = hcachelist; c; c = c->next) {
|
||||
LIST *l;
|
||||
char time_str[30];
|
||||
char age_str[30];
|
||||
char includes_count_str[30];
|
||||
char hdrscan_count_str[30];
|
||||
for ( c = hcachelist; c; c = c->next )
|
||||
{
|
||||
LIST * l;
|
||||
char time_str[ 30 ];
|
||||
char age_str[ 30 ];
|
||||
char includes_count_str[ 30 ];
|
||||
char hdrscan_count_str[ 30 ];
|
||||
|
||||
if (maxage == 0)
|
||||
c->age = 0;
|
||||
else if (c->age > maxage)
|
||||
continue;
|
||||
if ( maxage == 0 )
|
||||
c->age = 0;
|
||||
else if ( c->age > maxage )
|
||||
continue;
|
||||
|
||||
sprintf(includes_count_str, "%lu", list_length(c->includes));
|
||||
sprintf(hdrscan_count_str, "%lu", list_length(c->hdrscan));
|
||||
sprintf(time_str, "%lu", c->time);
|
||||
sprintf(age_str, "%lu", c->age);
|
||||
sprintf( includes_count_str, "%lu", (long unsigned) list_length( c->includes ) );
|
||||
sprintf( hdrscan_count_str, "%lu", (long unsigned) list_length( c->hdrscan ) );
|
||||
sprintf( time_str, "%lu", (long unsigned) c->time );
|
||||
sprintf( age_str, "%lu", (long unsigned) c->age );
|
||||
|
||||
write_netstring(f, CACHE_RECORD_HEADER);
|
||||
write_netstring(f, c->boundname);
|
||||
write_netstring(f, time_str);
|
||||
write_netstring(f, age_str);
|
||||
write_netstring(f, includes_count_str);
|
||||
for (l = c->includes; l; l = list_next(l)) {
|
||||
write_netstring(f, l->string);
|
||||
}
|
||||
write_netstring(f, hdrscan_count_str);
|
||||
for (l = c->hdrscan; l; l = list_next(l)) {
|
||||
write_netstring(f, l->string);
|
||||
}
|
||||
fputs("\n", f);
|
||||
header_count++;
|
||||
write_netstring( f, CACHE_RECORD_HEADER );
|
||||
write_netstring( f, c->boundname );
|
||||
write_netstring( f, time_str );
|
||||
write_netstring( f, age_str );
|
||||
write_netstring( f, includes_count_str );
|
||||
for ( l = c->includes; l; l = list_next( l ) )
|
||||
write_netstring( f, l->string );
|
||||
write_netstring( f, hdrscan_count_str );
|
||||
for ( l = c->hdrscan; l; l = list_next( l ) )
|
||||
write_netstring( f, l->string );
|
||||
fputs( "\n", f );
|
||||
++header_count;
|
||||
}
|
||||
write_netstring(f, CACHE_RECORD_END);
|
||||
write_netstring( f, CACHE_RECORD_END );
|
||||
|
||||
if (DEBUG_HEADER) {
|
||||
printf("hcache written to %s. %d dependencies, %.0f%% hit rate\n",
|
||||
hcachename, header_count,
|
||||
queries ? 100.0 * hits / queries : 0);
|
||||
}
|
||||
if ( DEBUG_HEADER )
|
||||
printf( "hcache written to %s. %d dependencies, %.0f%% hit rate\n",
|
||||
hcachename, header_count, queries ? 100.0 * hits / queries : 0 );
|
||||
|
||||
fclose (f);
|
||||
fclose ( f );
|
||||
}
|
||||
|
||||
LIST *
|
||||
hcache (TARGET *t, int rec, regexp *re[], LIST *hdrscan)
|
||||
|
||||
LIST * hcache( TARGET * t, int rec, regexp * re[], LIST * hdrscan )
|
||||
{
|
||||
HCACHEDATA cachedata, *c = &cachedata;
|
||||
LIST *l = 0;
|
||||
HCACHEDATA cachedata;
|
||||
HCACHEDATA * c = &cachedata;
|
||||
|
||||
LIST * l = 0;
|
||||
|
||||
++queries;
|
||||
|
||||
@@ -357,58 +368,58 @@ hcache (TARGET *t, int rec, regexp *re[], LIST *hdrscan)
|
||||
|
||||
if (hashcheck (hcachehash, (HASHDATA **) &c))
|
||||
{
|
||||
if (c->time == t->time)
|
||||
{
|
||||
LIST *l1 = hdrscan, *l2 = c->hdrscan;
|
||||
while (l1 && l2) {
|
||||
if (l1->string != l2->string) {
|
||||
l1 = NULL;
|
||||
} else {
|
||||
l1 = list_next(l1);
|
||||
l2 = list_next(l2);
|
||||
}
|
||||
}
|
||||
if (l1 || l2) {
|
||||
if (DEBUG_HEADER)
|
||||
printf("HDRSCAN out of date in cache for %s\n",
|
||||
t->boundname);
|
||||
if (c->time == t->time)
|
||||
{
|
||||
LIST *l1 = hdrscan, *l2 = c->hdrscan;
|
||||
while (l1 && l2) {
|
||||
if (l1->string != l2->string) {
|
||||
l1 = NULL;
|
||||
} else {
|
||||
l1 = list_next(l1);
|
||||
l2 = list_next(l2);
|
||||
}
|
||||
}
|
||||
if (l1 || l2) {
|
||||
if (DEBUG_HEADER)
|
||||
printf("HDRSCAN out of date in cache for %s\n",
|
||||
t->boundname);
|
||||
|
||||
printf("HDRSCAN out of date for %s\n", t->boundname);
|
||||
printf(" real : ");
|
||||
list_print(hdrscan);
|
||||
printf("\n cached: ");
|
||||
list_print(c->hdrscan);
|
||||
printf("\n");
|
||||
printf("HDRSCAN out of date for %s\n", t->boundname);
|
||||
printf(" real : ");
|
||||
list_print(hdrscan);
|
||||
printf("\n cached: ");
|
||||
list_print(c->hdrscan);
|
||||
printf("\n");
|
||||
|
||||
list_free(c->includes);
|
||||
list_free(c->hdrscan);
|
||||
c->includes = 0;
|
||||
c->hdrscan = 0;
|
||||
} else {
|
||||
if (DEBUG_HEADER)
|
||||
printf ("using header cache for %s\n", t->boundname);
|
||||
c->age = 0;
|
||||
++hits;
|
||||
l = list_copy (0, c->includes);
|
||||
return l;
|
||||
}
|
||||
} else {
|
||||
if (DEBUG_HEADER)
|
||||
printf ("header cache out of date for %s\n", t->boundname);
|
||||
list_free (c->includes);
|
||||
list_free(c->hdrscan);
|
||||
c->includes = 0;
|
||||
c->hdrscan = 0;
|
||||
}
|
||||
list_free(c->includes);
|
||||
list_free(c->hdrscan);
|
||||
c->includes = 0;
|
||||
c->hdrscan = 0;
|
||||
} else {
|
||||
if (DEBUG_HEADER)
|
||||
printf ("using header cache for %s\n", t->boundname);
|
||||
c->age = 0;
|
||||
++hits;
|
||||
l = list_copy (0, c->includes);
|
||||
return l;
|
||||
}
|
||||
} else {
|
||||
if (hashenter (hcachehash, (HASHDATA **)&c)) {
|
||||
c->boundname = newstr (c->boundname);
|
||||
c->next = hcachelist;
|
||||
hcachelist = c;
|
||||
}
|
||||
if (DEBUG_HEADER)
|
||||
printf ("header cache out of date for %s\n", t->boundname);
|
||||
list_free (c->includes);
|
||||
list_free(c->hdrscan);
|
||||
c->includes = 0;
|
||||
c->hdrscan = 0;
|
||||
}
|
||||
} else {
|
||||
if (hashenter (hcachehash, (HASHDATA **)&c)) {
|
||||
c->boundname = newstr (c->boundname);
|
||||
c->next = hcachelist;
|
||||
hcachelist = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* 'c' points at the cache entry. Its out of date. */
|
||||
/* 'c' points at the cache entry. Its out of date. */
|
||||
|
||||
l = headers1 (0, t->boundname, rec, re);
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
* #include statements.
|
||||
*
|
||||
* we look for lines like "#define MACRO <....>" or '#define MACRO " "'
|
||||
* in the target file. When found, we
|
||||
* in the target file. When found, we
|
||||
*
|
||||
* we then phony up a rule invocation like:
|
||||
*
|
||||
* $(HDRRULE) <target> : <resolved included files> ;
|
||||
* $(HDRRULE) <target> : <resolved included files> ;
|
||||
*
|
||||
* External routines:
|
||||
* headers1() - scan a target for "#include MACRO" lines and try
|
||||
@@ -42,21 +42,19 @@
|
||||
*
|
||||
* 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.
|
||||
* 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 ?? */
|
||||
|
||||
char * symbol;
|
||||
char * filename; /* we could maybe use a LIST here ?? */
|
||||
} HEADER_MACRO;
|
||||
|
||||
static struct hash* header_macros_hash = 0;
|
||||
|
||||
static struct hash * header_macros_hash = 0;
|
||||
|
||||
|
||||
/*
|
||||
* headers() - scan a target for include files and call HDRRULE
|
||||
@@ -68,9 +66,9 @@ void
|
||||
macro_headers( TARGET *t )
|
||||
{
|
||||
static regexp *re = 0;
|
||||
FILE *f;
|
||||
char buf[ 1024 ];
|
||||
|
||||
FILE *f;
|
||||
char buf[ 1024 ];
|
||||
|
||||
if ( DEBUG_HEADER )
|
||||
printf( "macro header scan for %s\n", t->name );
|
||||
|
||||
@@ -80,23 +78,24 @@ macro_headers( TARGET *t )
|
||||
if ( re == 0 )
|
||||
{
|
||||
re = regex_compile(
|
||||
"^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*"
|
||||
"^[ ]*#[ ]*define[ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*"
|
||||
"[<\"]([^\">]*)[\">].*$" );
|
||||
}
|
||||
|
||||
if( !( f = fopen( t->boundname, "r" ) ) )
|
||||
|
||||
if ( !( f = fopen( t->boundname, "r" ) ) )
|
||||
return;
|
||||
|
||||
while( fgets( buf, sizeof( buf ), f ) )
|
||||
while ( fgets( buf, sizeof( buf ), f ) )
|
||||
{
|
||||
HEADER_MACRO var, *v = &var;
|
||||
HEADER_MACRO var;
|
||||
HEADER_MACRO *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 );
|
||||
@@ -121,19 +120,18 @@ macro_headers( TARGET *t )
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
macro_header_get( const char* macro_name )
|
||||
char * macro_header_get( const char * macro_name )
|
||||
{
|
||||
HEADER_MACRO var, *v = &var;
|
||||
HEADER_MACRO var;
|
||||
HEADER_MACRO * v = &var;
|
||||
|
||||
v->symbol = (char*)macro_name;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
/*
|
||||
* headers.c - handle #includes in source files
|
||||
*
|
||||
* Using regular expressions provided as the variable $(HDRSCAN),
|
||||
* 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> ;
|
||||
*
|
||||
* $(HDRRULE) <target> : <include files> ;
|
||||
*
|
||||
* External routines:
|
||||
* headers() - scan a target for include files and call HDRRULE
|
||||
@@ -41,8 +41,8 @@
|
||||
*
|
||||
* 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.
|
||||
* so that headers() doesn't have to mock up a parse structure
|
||||
* just to invoke a rule.
|
||||
*/
|
||||
|
||||
#ifndef OPT_HEADER_CACHE_EXT
|
||||
@@ -58,31 +58,32 @@ static LIST *headers1( LIST *l, char *file, int rec, regexp *re[]);
|
||||
void
|
||||
headers( TARGET *t )
|
||||
{
|
||||
LIST *hdrscan;
|
||||
LIST *hdrrule;
|
||||
LIST *headlist = 0;
|
||||
regexp *re[ MAXINC ];
|
||||
int rec = 0;
|
||||
|
||||
if( !( hdrscan = var_get( "HDRSCAN" ) ) ||
|
||||
LIST * hdrscan;
|
||||
LIST * hdrrule;
|
||||
#ifndef OPT_HEADER_CACHE_EXT
|
||||
LIST * headlist = 0;
|
||||
#endif
|
||||
regexp * re[ MAXINC ];
|
||||
int rec = 0;
|
||||
|
||||
if ( !( hdrscan = var_get( "HDRSCAN" ) ) ||
|
||||
!( hdrrule = var_get( "HDRRULE" ) ) )
|
||||
return;
|
||||
|
||||
if( DEBUG_HEADER )
|
||||
if ( DEBUG_HEADER )
|
||||
printf( "header scan %s\n", t->name );
|
||||
|
||||
/* Compile all regular expressions in HDRSCAN */
|
||||
|
||||
while( rec < MAXINC && hdrscan )
|
||||
while ( ( rec < MAXINC ) && hdrscan )
|
||||
{
|
||||
re[rec++] = regex_compile( hdrscan->string );
|
||||
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 frame[1];
|
||||
frame_init( frame );
|
||||
lol_add( frame->args, list_new( L0, t->name ) );
|
||||
#ifdef OPT_HEADER_CACHE_EXT
|
||||
@@ -91,7 +92,7 @@ headers( TARGET *t )
|
||||
lol_add( frame->args, headers1( headlist, t->boundname, rec, re ) );
|
||||
#endif
|
||||
|
||||
if( lol_get( frame->args, 1 ) )
|
||||
if ( lol_get( frame->args, 1 ) )
|
||||
{
|
||||
/* The third argument to HDRRULE is the bound name of
|
||||
* $(<) */
|
||||
@@ -100,14 +101,14 @@ headers( TARGET *t )
|
||||
list_free( evaluate_rule( hdrrule->string, frame ) );
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
|
||||
/* Clean up. */
|
||||
frame_free( frame );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* headers1() - using regexp, scan a file and build include LIST
|
||||
* headers1() - using regexp, scan a file and build include LIST.
|
||||
*/
|
||||
|
||||
#ifdef OPT_HEADER_CACHE_EXT
|
||||
@@ -115,91 +116,88 @@ LIST *
|
||||
#else
|
||||
static LIST *
|
||||
#endif
|
||||
headers1(
|
||||
LIST *l,
|
||||
char *file,
|
||||
int rec,
|
||||
regexp *re[] )
|
||||
headers1(
|
||||
LIST * l,
|
||||
char * file,
|
||||
int rec,
|
||||
regexp * re[] )
|
||||
{
|
||||
FILE *f;
|
||||
char buf[ 1024 ];
|
||||
int i;
|
||||
static regexp *re_macros = 0;
|
||||
FILE * f;
|
||||
char buf[ 1024 ];
|
||||
int i;
|
||||
static regexp * re_macros = 0;
|
||||
|
||||
|
||||
#ifdef OPT_IMPROVED_PATIENCE_EXT
|
||||
static int count = 0;
|
||||
++count;
|
||||
if ( ((count == 100) || !( count % 1000 )) && DEBUG_MAKE )
|
||||
printf("...patience...\n");
|
||||
static int count = 0;
|
||||
++count;
|
||||
if ( ((count == 100) || !( count % 1000 )) && DEBUG_MAKE )
|
||||
printf("...patience...\n");
|
||||
#endif
|
||||
|
||||
/* the following regexp is used to detect cases where a */
|
||||
/* file is included through a line line "#include MACRO" */
|
||||
if ( re_macros == 0 )
|
||||
|
||||
/* the following regexp is used to detect cases where a */
|
||||
/* file is included through a line line "#include MACRO" */
|
||||
if ( re_macros == 0 )
|
||||
re_macros = regex_compile(
|
||||
"^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
|
||||
|
||||
if ( !( f = fopen( file, "r" ) ) )
|
||||
return l;
|
||||
|
||||
while ( fgets( buf, sizeof( buf ), f ) )
|
||||
{
|
||||
int size = strlen( buf );
|
||||
/* Remove trailing \r and \n, if any. */
|
||||
while ( ( size > 0 ) &&
|
||||
( buf[ size - 1 ] == '\n' ) &&
|
||||
( buf[ size - 1 ] == '\r' ) )
|
||||
{
|
||||
re_macros = regex_compile(
|
||||
"^[ ]*#[ ]*include[ ]*([A-Za-z][A-Za-z0-9_]*).*$" );
|
||||
buf[ size - 1 ] = '\0';
|
||||
--size;
|
||||
}
|
||||
|
||||
|
||||
if( !( f = fopen( file, "r" ) ) )
|
||||
return l;
|
||||
|
||||
while( fgets( buf, sizeof( buf ), f ) )
|
||||
{
|
||||
int size = strlen (buf);
|
||||
/* Remove trailing \r and \n, if any. */
|
||||
while (size > 0
|
||||
&& (buf[size-1] == '\n' && buf[size-1] == '\r'))
|
||||
for ( i = 0; i < rec; ++i )
|
||||
if ( regexec( re[i], buf ) && re[i]->startp[1] )
|
||||
{
|
||||
buf[size-1] = '\0';
|
||||
--size;
|
||||
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] ) );
|
||||
}
|
||||
|
||||
for( i = 0; i < rec; i++ )
|
||||
if( regexec( re[i], buf ) && re[i]->startp[1] )
|
||||
{
|
||||
re[i]->endp[1][0] = '\0';
|
||||
/* special treatment for #include MACRO */
|
||||
if ( regexec( re_macros, buf ) && re_macros->startp[1] )
|
||||
{
|
||||
char* header_filename;
|
||||
|
||||
if( DEBUG_HEADER )
|
||||
printf( "header found: %s\n", re[i]->startp[1] );
|
||||
re_macros->endp[1][0] = '\0';
|
||||
|
||||
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 )
|
||||
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 );
|
||||
|
||||
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" );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( DEBUG_HEADER )
|
||||
printf( " ignored !!\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose( f );
|
||||
fclose( f );
|
||||
|
||||
return l;
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
regerror( char *s )
|
||||
|
||||
void regerror( char * s )
|
||||
{
|
||||
printf( "re error %s\n", s );
|
||||
printf( "re error %s\n", s );
|
||||
}
|
||||
|
||||
672
src/engine/jam.c
672
src/engine/jam.c
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* /+\
|
||||
* +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
|
||||
* +\ Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
|
||||
* \+/
|
||||
*
|
||||
* This file is part of jam.
|
||||
*
|
||||
* License is hereby granted to use this software and distribute it
|
||||
* freely, as long as this copyright notice is retained and modifications
|
||||
* freely, as long as this copyright notice is retained and modifications
|
||||
* are clearly marked.
|
||||
*
|
||||
* ALL WARRANTIES ARE HEREBY DISCLAIMED.
|
||||
@@ -27,11 +27,11 @@
|
||||
*
|
||||
* The top half of the code is structured such:
|
||||
*
|
||||
* jam
|
||||
* / | \
|
||||
* jam
|
||||
* / | \
|
||||
* +---+ | \
|
||||
* / | \
|
||||
* jamgram option \
|
||||
* / | \
|
||||
* jamgram option \
|
||||
* / | \ \
|
||||
* / | \ \
|
||||
* / | \ |
|
||||
@@ -69,32 +69,32 @@
|
||||
*
|
||||
* Roughly, the modules are:
|
||||
*
|
||||
* builtins.c - jam's built-in rules
|
||||
* command.c - maintain lists of commands
|
||||
* compile.c - compile parsed jam statements
|
||||
* execunix.c - execute a shell script on UNIX
|
||||
* execvms.c - execute a shell script, ala VMS
|
||||
* expand.c - expand a buffer, given variable values
|
||||
* file*.c - scan directories and archives on *
|
||||
* hash.c - simple in-memory hashing routines
|
||||
* builtins.c - jam's built-in rules
|
||||
* command.c - maintain lists of commands
|
||||
* compile.c - compile parsed jam statements
|
||||
* execunix.c - execute a shell script on UNIX
|
||||
* execvms.c - execute a shell script, ala VMS
|
||||
* expand.c - expand a buffer, given variable values
|
||||
* file*.c - scan directories and archives on *
|
||||
* hash.c - simple in-memory hashing routines
|
||||
* 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
|
||||
* path*.c - manipulate file names on *
|
||||
* hash.c - simple in-memory hashing routines
|
||||
* regexp.c - Henry Spencer's regexp
|
||||
* rules.c - access to RULEs, TARGETs, and ACTIONs
|
||||
* scan.c - the jam yacc scanner
|
||||
* search.c - find a target along $(SEARCH) or $(LOCATE)
|
||||
* timestamp.c - get the timestamp of a file or archive member
|
||||
* variable.c - handle jam multi-element variables
|
||||
* headers.c - handle #includes in source files
|
||||
* jambase.c - compilable copy of Jambase
|
||||
* jamgram.y - jam grammar
|
||||
* lists.c - maintain lists of strings
|
||||
* make.c - bring a target up to date, once rules are in place
|
||||
* make1.c - execute command to bring targets up to date
|
||||
* newstr.c - string manipulation routines
|
||||
* option.c - command line option processing
|
||||
* parse.c - make and destroy parse trees as driven by the parser
|
||||
* path*.c - manipulate file names on *
|
||||
* hash.c - simple in-memory hashing routines
|
||||
* regexp.c - Henry Spencer's regexp
|
||||
* rules.c - access to RULEs, TARGETs, and ACTIONs
|
||||
* scan.c - the jam yacc scanner
|
||||
* search.c - find a target along $(SEARCH) or $(LOCATE)
|
||||
* timestamp.c - get the timestamp of a file or archive member
|
||||
* variable.c - handle jam multi-element variables
|
||||
*
|
||||
* 05/04/94 (seiwald) - async multiprocess (-j) support
|
||||
* 02/08/95 (seiwald) - -n implies -d2.
|
||||
@@ -103,132 +103,122 @@
|
||||
* 01/10/01 (seiwald) - pathsys.h split from filesys.h
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "option.h"
|
||||
# include "patchlevel.h"
|
||||
|
||||
#include "jam.h"
|
||||
#include "option.h"
|
||||
#include "patchlevel.h"
|
||||
|
||||
/* These get various function declarations. */
|
||||
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "variable.h"
|
||||
# include "compile.h"
|
||||
# include "builtins.h"
|
||||
# include "rules.h"
|
||||
# include "newstr.h"
|
||||
# include "scan.h"
|
||||
# include "timestamp.h"
|
||||
# include "make.h"
|
||||
# include "strings.h"
|
||||
# include "expand.h"
|
||||
# include "filesys.h"
|
||||
# include "output.h"
|
||||
#include "lists.h"
|
||||
#include "parse.h"
|
||||
#include "variable.h"
|
||||
#include "compile.h"
|
||||
#include "builtins.h"
|
||||
#include "rules.h"
|
||||
#include "newstr.h"
|
||||
#include "scan.h"
|
||||
#include "timestamp.h"
|
||||
#include "make.h"
|
||||
#include "strings.h"
|
||||
#include "expand.h"
|
||||
#include "filesys.h"
|
||||
#include "output.h"
|
||||
|
||||
/* Macintosh is "special" */
|
||||
|
||||
# ifdef OS_MAC
|
||||
# include <QuickDraw.h>
|
||||
# endif
|
||||
|
||||
/* And UNIX for this */
|
||||
|
||||
# ifdef unix
|
||||
# include <sys/utsname.h>
|
||||
# include <signal.h>
|
||||
# endif
|
||||
|
||||
struct globs globs = {
|
||||
0, /* noexec */
|
||||
1, /* jobs */
|
||||
0, /* quitquick */
|
||||
0, /* newestfirst */
|
||||
0, /* pipes action stdout and stderr merged to action output */
|
||||
# ifdef OS_MAC
|
||||
{ 0, 0 }, /* debug - suppress tracing output */
|
||||
# else
|
||||
{ 0, 1 }, /* debug ... */
|
||||
# endif
|
||||
0, /* output commands, not run them */
|
||||
0 /* action timeout */
|
||||
} ;
|
||||
|
||||
/* 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
|
||||
|
||||
# if defined( __MWERKS__)
|
||||
# define use_environ _environ
|
||||
extern char **_environ;
|
||||
#ifdef OS_MAC
|
||||
#include <QuickDraw.h>
|
||||
#endif
|
||||
|
||||
# ifndef use_environ
|
||||
# define use_environ environ
|
||||
# if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
|
||||
extern char **environ;
|
||||
# endif
|
||||
# endif
|
||||
/* And UNIX for this. */
|
||||
#ifdef unix
|
||||
#include <sys/utsname.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
# if YYDEBUG != 0
|
||||
extern int yydebug;
|
||||
# endif
|
||||
struct globs globs =
|
||||
{
|
||||
0, /* noexec */
|
||||
1, /* jobs */
|
||||
0, /* quitquick */
|
||||
0, /* newestfirst */
|
||||
0, /* pipes action stdout and stderr merged to action output */
|
||||
#ifdef OS_MAC
|
||||
{ 0, 0 }, /* debug - suppress tracing output */
|
||||
#else
|
||||
{ 0, 1 }, /* debug ... */
|
||||
#endif
|
||||
0, /* output commands, not run them */
|
||||
0 /* action timeout */
|
||||
};
|
||||
|
||||
/* 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
|
||||
|
||||
# if defined( __MWERKS__)
|
||||
#define use_environ _environ
|
||||
extern char * * _environ;
|
||||
#endif
|
||||
|
||||
#ifndef use_environ
|
||||
#define use_environ environ
|
||||
#if !defined( __WATCOM__ ) && !defined( OS_OS2 ) && !defined( OS_NT )
|
||||
extern char **environ;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if YYDEBUG != 0
|
||||
extern int yydebug;
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void run_unit_tests()
|
||||
{
|
||||
# if defined( USE_EXECNT )
|
||||
#if defined( USE_EXECNT )
|
||||
extern void execnt_unit_test();
|
||||
execnt_unit_test();
|
||||
# endif
|
||||
#endif
|
||||
string_unit_test();
|
||||
var_expand_unit_test();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
extern PyObject*
|
||||
bjam_call(PyObject *self, PyObject *args);
|
||||
|
||||
extern PyObject*
|
||||
bjam_import_rule(PyObject* self, PyObject* args);
|
||||
|
||||
extern PyObject*
|
||||
bjam_define_action(PyObject* self, PyObject* args);
|
||||
|
||||
extern PyObject*
|
||||
bjam_variable(PyObject* self, PyObject* args);
|
||||
|
||||
extern PyObject*
|
||||
bjam_backtrace(PyObject* self, PyObject *args);
|
||||
extern PyObject * bjam_call ( PyObject * self, PyObject * args );
|
||||
extern PyObject * bjam_import_rule ( PyObject * self, PyObject * args );
|
||||
extern PyObject * bjam_define_action( PyObject * self, PyObject * args );
|
||||
extern PyObject * bjam_variable ( PyObject * self, PyObject * args );
|
||||
extern PyObject * bjam_backtrace ( PyObject * self, PyObject * args );
|
||||
#endif
|
||||
|
||||
int main( int argc, char **argv, char **arg_environ )
|
||||
int main( int argc, char * * argv, char * * arg_environ )
|
||||
{
|
||||
int n;
|
||||
char *s;
|
||||
struct option optv[N_OPTS];
|
||||
const char *all = "all";
|
||||
int anyhow = 0;
|
||||
int status;
|
||||
int arg_c = argc;
|
||||
char ** arg_v = argv;
|
||||
const char *progname = argv[0];
|
||||
int n;
|
||||
char * s;
|
||||
struct option optv[N_OPTS];
|
||||
char const * all = "all";
|
||||
int anyhow = 0;
|
||||
int status;
|
||||
int arg_c = argc;
|
||||
char * * arg_v = argv;
|
||||
char const * progname = argv[0];
|
||||
|
||||
BJAM_MEM_INIT();
|
||||
|
||||
@@ -236,9 +226,10 @@ int main( int argc, char **argv, char **arg_environ )
|
||||
InitGraf(&qd.thePort);
|
||||
# endif
|
||||
|
||||
argc--, argv++;
|
||||
--argc;
|
||||
++argv;
|
||||
|
||||
if( getoptions( argc, argv, "-:l:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
|
||||
if ( getoptions( argc, argv, "-:l:d:j:p:f:gs:t:ano:qv", optv ) < 0 )
|
||||
{
|
||||
printf( "\nusage: %s [ options ] targets...\n\n", progname );
|
||||
|
||||
@@ -261,291 +252,276 @@ int main( int argc, char **argv, char **arg_environ )
|
||||
}
|
||||
|
||||
/* Version info. */
|
||||
|
||||
if( ( s = getoptval( optv, 'v', 0 ) ) )
|
||||
if ( ( s = getoptval( optv, 'v', 0 ) ) )
|
||||
{
|
||||
printf( "Boost.Jam " );
|
||||
printf( "Version %s. %s.\n", VERSION, OSMINOR );
|
||||
printf( " Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc. \n" );
|
||||
printf( " Copyright 2001 David Turner.\n" );
|
||||
printf( " Copyright 2001-2004 David Abrahams.\n" );
|
||||
printf( " Copyright 2002-2005 Rene Rivera.\n" );
|
||||
printf( " Copyright 2003-2005 Vladimir Prus.\n" );
|
||||
printf( " Copyright 2002-2008 Rene Rivera.\n" );
|
||||
printf( " Copyright 2003-2008 Vladimir Prus.\n" );
|
||||
|
||||
return EXITOK;
|
||||
}
|
||||
|
||||
/* Pick up interesting options */
|
||||
|
||||
if( ( s = getoptval( optv, 'n', 0 ) ) )
|
||||
/* Pick up interesting options. */
|
||||
if ( ( s = getoptval( optv, 'n', 0 ) ) )
|
||||
globs.noexec++, globs.debug[2] = 1;
|
||||
|
||||
if( ( s = getoptval( optv, 'p', 0 ) ) )
|
||||
if ( ( s = getoptval( optv, 'p', 0 ) ) )
|
||||
{
|
||||
/* undocumented -p3 (acts like both -p1 -p2) means separate pipe action stdout and stderr */
|
||||
globs.pipe_action = atoi(s);
|
||||
if (3 < globs.pipe_action || globs.pipe_action < 0)
|
||||
/* Undocumented -p3 (acts like both -p1 -p2) means separate pipe action
|
||||
* stdout and stderr.
|
||||
*/
|
||||
globs.pipe_action = atoi( s );
|
||||
if ( ( 3 < globs.pipe_action ) || ( globs.pipe_action < 0 ) )
|
||||
{
|
||||
printf( "Invalid pipe descriptor '%d', valid values are -p[0..3].\n", globs.pipe_action);
|
||||
exit(EXITBAD);
|
||||
printf(
|
||||
"Invalid pipe descriptor '%d', valid values are -p[0..3].\n",
|
||||
globs.pipe_action );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
}
|
||||
|
||||
if( ( s = getoptval( optv, 'q', 0 ) ) )
|
||||
globs.quitquick = 1;
|
||||
if ( ( s = getoptval( optv, 'q', 0 ) ) )
|
||||
globs.quitquick = 1;
|
||||
|
||||
if( ( s = getoptval( optv, 'a', 0 ) ) )
|
||||
if ( ( s = getoptval( optv, 'a', 0 ) ) )
|
||||
anyhow++;
|
||||
|
||||
if( ( s = getoptval( optv, 'j', 0 ) ) )
|
||||
if ( ( s = getoptval( optv, 'j', 0 ) ) )
|
||||
globs.jobs = atoi( s );
|
||||
|
||||
if( ( s = getoptval( optv, 'g', 0 ) ) )
|
||||
if ( ( s = getoptval( optv, 'g', 0 ) ) )
|
||||
globs.newestfirst = 1;
|
||||
|
||||
if( ( s = getoptval( optv, 'l', 0 ) ) )
|
||||
if ( ( s = getoptval( optv, 'l', 0 ) ) )
|
||||
globs.timeout = atoi( s );
|
||||
|
||||
/* Turn on/off debugging */
|
||||
|
||||
for( n = 0; s = getoptval( optv, 'd', n ); n++ )
|
||||
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++ )
|
||||
if ( !n )
|
||||
for ( i = 0; i < DEBUG_MAX; ++i )
|
||||
globs.debug[i] = 0;
|
||||
|
||||
i = atoi( s );
|
||||
|
||||
if( i < 0 || i >= DEBUG_MAX )
|
||||
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 == '+' )
|
||||
/* n turns on levels 1-n. */
|
||||
/* +n turns on level n. */
|
||||
if ( *s == '+' )
|
||||
globs.debug[i] = 1;
|
||||
else while( i )
|
||||
else while ( i )
|
||||
globs.debug[i--] = 1;
|
||||
}
|
||||
|
||||
{ PROFILE_ENTER(MAIN);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
{
|
||||
PROFILE_ENTER(MAIN_PYTHON);
|
||||
Py_Initialize();
|
||||
|
||||
PROFILE_ENTER( MAIN );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
{
|
||||
static PyMethodDef BjamMethods[] = {
|
||||
{"call", bjam_call, METH_VARARGS,
|
||||
"Call the specified bjam rule."},
|
||||
{"import_rule", bjam_import_rule, METH_VARARGS,
|
||||
"Imports Python callable to bjam."},
|
||||
{"define_action", bjam_define_action, METH_VARARGS,
|
||||
"Defines a command line action."},
|
||||
{"variable", bjam_variable, METH_VARARGS,
|
||||
"Obtains a variable from bjam's global module."},
|
||||
{"backtrace", bjam_backtrace, METH_VARARGS,
|
||||
"Returns bjam backtrace from the last call into Python."},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
Py_InitModule("bjam", BjamMethods);
|
||||
PROFILE_ENTER( MAIN_PYTHON );
|
||||
Py_Initialize();
|
||||
{
|
||||
static PyMethodDef BjamMethods[] = {
|
||||
{"call", bjam_call, METH_VARARGS,
|
||||
"Call the specified bjam rule."},
|
||||
{"import_rule", bjam_import_rule, METH_VARARGS,
|
||||
"Imports Python callable to bjam."},
|
||||
{"define_action", bjam_define_action, METH_VARARGS,
|
||||
"Defines a command line action."},
|
||||
{"variable", bjam_variable, METH_VARARGS,
|
||||
"Obtains a variable from bjam's global module."},
|
||||
{"backtrace", bjam_backtrace, METH_VARARGS,
|
||||
"Returns bjam backtrace from the last call into Python."},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
Py_InitModule( "bjam", BjamMethods );
|
||||
}
|
||||
PROFILE_EXIT( MAIN_PYTHON );
|
||||
}
|
||||
PROFILE_EXIT(MAIN_PYTHON);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
run_unit_tests();
|
||||
run_unit_tests();
|
||||
#endif
|
||||
#if YYDEBUG != 0
|
||||
if ( DEBUG_PARSE )
|
||||
yydebug = 1;
|
||||
if ( DEBUG_PARSE )
|
||||
yydebug = 1;
|
||||
#endif
|
||||
|
||||
/* Set JAMDATE first */
|
||||
/* Set JAMDATE. */
|
||||
var_set( "JAMDATE", list_new( L0, outf_time(time(0)) ), VAR_SET );
|
||||
|
||||
var_set( "JAMDATE", list_new( L0, outf_time(time(0)) ), VAR_SET );
|
||||
/* Set JAM_VERSION. */
|
||||
var_set( "JAM_VERSION",
|
||||
list_new( list_new( list_new( L0,
|
||||
newstr( VERSION_MAJOR_SYM ) ),
|
||||
newstr( VERSION_MINOR_SYM ) ),
|
||||
newstr( VERSION_PATCH_SYM ) ),
|
||||
VAR_SET );
|
||||
|
||||
|
||||
var_set( "JAM_VERSION",
|
||||
list_new( list_new( list_new( L0, newstr( VERSION_MAJOR_SYM ) ),
|
||||
newstr( VERSION_MINOR_SYM ) ),
|
||||
newstr( VERSION_PATCH_SYM ) ),
|
||||
VAR_SET );
|
||||
|
||||
/* And JAMUNAME */
|
||||
# ifdef unix
|
||||
{
|
||||
struct utsname u;
|
||||
|
||||
if( uname( &u ) >= 0 )
|
||||
/* Set JAMUNAME. */
|
||||
#ifdef unix
|
||||
{
|
||||
var_set( "JAMUNAME",
|
||||
list_new(
|
||||
struct utsname u;
|
||||
|
||||
if ( uname( &u ) >= 0 )
|
||||
{
|
||||
var_set( "JAMUNAME",
|
||||
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 */
|
||||
|
||||
/* load up environment variables */
|
||||
|
||||
/* first into global module, with splitting, for backward compatibility */
|
||||
var_defines( use_environ, 1 );
|
||||
|
||||
/* then into .ENVIRON, without splitting */
|
||||
enter_module( bindmodule(".ENVIRON") );
|
||||
var_defines( use_environ, 0 );
|
||||
exit_module( bindmodule(".ENVIRON") );
|
||||
|
||||
/*
|
||||
* Jam defined variables OS, OSPLAT
|
||||
* We load them after environment, so that
|
||||
* setting OS in environment does not
|
||||
* change Jam notion of the current platform.
|
||||
*/
|
||||
|
||||
var_defines( othersyms, 1 );
|
||||
|
||||
|
||||
/* 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, 1 );
|
||||
enter_module( bindmodule(".ENVIRON") );
|
||||
var_defines( symv, 0 );
|
||||
exit_module( bindmodule(".ENVIRON") );
|
||||
}
|
||||
|
||||
/* Set the ARGV to reflect the complete list of arguments of invocation. */
|
||||
|
||||
for ( n = 0; n < arg_c; ++n )
|
||||
{
|
||||
var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
|
||||
}
|
||||
|
||||
/* Initialize built-in rules */
|
||||
|
||||
load_builtins();
|
||||
|
||||
/* Add the targets in the command line to update list */
|
||||
|
||||
for ( n = 1; n < arg_c; ++n )
|
||||
{
|
||||
if ( arg_v[n][0] == '-' )
|
||||
{
|
||||
char *f = "-:l:d:j:f:gs:t:ano:qv";
|
||||
for( ; *f; f++ ) if( *f == arg_v[n][1] ) break;
|
||||
if ( f[1] == ':' && arg_v[n][2] == '\0' ) { ++n; }
|
||||
}
|
||||
else
|
||||
{
|
||||
mark_target_for_updating(arg_v[n]);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
||||
{
|
||||
PROFILE_ENTER(MAIN_MAKE);
|
||||
|
||||
LIST* targets = targets_to_update();
|
||||
if ( !targets )
|
||||
{
|
||||
status |= make( 1, &all, anyhow );
|
||||
}
|
||||
else
|
||||
{
|
||||
int targets_count = list_length(targets);
|
||||
const char **targets2 = (const char **)BJAM_MALLOC(targets_count * sizeof(char *));
|
||||
int n = 0;
|
||||
for ( ; targets; targets = list_next(targets) )
|
||||
{
|
||||
targets2[n++] = targets->string;
|
||||
list_new(
|
||||
list_new( L0,
|
||||
newstr( u.sysname ) ),
|
||||
newstr( u.nodename ) ),
|
||||
newstr( u.release ) ),
|
||||
newstr( u.version ) ),
|
||||
newstr( u.machine ) ), VAR_SET );
|
||||
}
|
||||
status |= make( targets_count, targets2, anyhow );
|
||||
free(targets);
|
||||
}
|
||||
|
||||
PROFILE_EXIT(MAIN_MAKE);
|
||||
#endif /* unix */
|
||||
|
||||
/* Load up environment variables. */
|
||||
|
||||
/* First into the global module, with splitting, for backward
|
||||
* compatibility.
|
||||
*/
|
||||
var_defines( use_environ, 1 );
|
||||
|
||||
/* Then into .ENVIRON, without splitting. */
|
||||
enter_module( bindmodule(".ENVIRON") );
|
||||
var_defines( use_environ, 0 );
|
||||
exit_module( bindmodule(".ENVIRON") );
|
||||
|
||||
/*
|
||||
* Jam defined variables OS & OSPLAT. We load them after environment, so
|
||||
* that setting OS in environment does not change Jam's notion of the
|
||||
* current platform.
|
||||
*/
|
||||
var_defines( othersyms, 1 );
|
||||
|
||||
/* 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, 1 );
|
||||
enter_module( bindmodule(".ENVIRON") );
|
||||
var_defines( symv, 0 );
|
||||
exit_module( bindmodule(".ENVIRON") );
|
||||
}
|
||||
|
||||
/* Set the ARGV to reflect the complete list of arguments of invocation.
|
||||
*/
|
||||
for ( n = 0; n < arg_c; ++n )
|
||||
var_set( "ARGV", list_new( L0, newstr( arg_v[n] ) ), VAR_APPEND );
|
||||
|
||||
/* Initialize built-in rules. */
|
||||
load_builtins();
|
||||
|
||||
/* Add the targets in the command line to the update list. */
|
||||
for ( n = 1; n < arg_c; ++n )
|
||||
{
|
||||
if ( arg_v[ n ][ 0 ] == '-' )
|
||||
{
|
||||
char * f = "-:l:d:j:f:gs:t:ano:qv";
|
||||
for ( ; *f; ++f ) if ( *f == arg_v[ n ][ 1 ] ) break;
|
||||
if ( ( f[ 1 ] == ':' ) && ( arg_v[ n ][ 2 ] == '\0' ) ) ++n;
|
||||
}
|
||||
else
|
||||
{
|
||||
mark_target_for_updating( arg_v[ n ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 )
|
||||
touch_target( 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. */
|
||||
{
|
||||
PROFILE_ENTER( MAIN_MAKE );
|
||||
|
||||
LIST * targets = targets_to_update();
|
||||
if ( !targets )
|
||||
{
|
||||
status |= make( 1, &all, anyhow );
|
||||
}
|
||||
else
|
||||
{
|
||||
int targets_count = list_length( targets );
|
||||
const char * * targets2 = (const char * *)
|
||||
BJAM_MALLOC( targets_count * sizeof( char * ) );
|
||||
int n = 0;
|
||||
for ( ; targets; targets = list_next( targets ) )
|
||||
targets2[ n++ ] = targets->string;
|
||||
status |= make( targets_count, targets2, anyhow );
|
||||
free( targets );
|
||||
}
|
||||
|
||||
PROFILE_EXIT( MAIN_MAKE );
|
||||
}
|
||||
|
||||
PROFILE_EXIT( MAIN );
|
||||
}
|
||||
|
||||
|
||||
PROFILE_EXIT(MAIN); }
|
||||
|
||||
if ( DEBUG_PROFILE )
|
||||
profile_dump();
|
||||
|
||||
/* Widely scattered cleanup */
|
||||
|
||||
/* Widely scattered cleanup. */
|
||||
var_done();
|
||||
file_done();
|
||||
donerules();
|
||||
donestamps();
|
||||
donestr();
|
||||
rules_done();
|
||||
stamps_done();
|
||||
str_done();
|
||||
|
||||
/* close cmdout */
|
||||
|
||||
if( globs.cmdout )
|
||||
/* Close cmdout. */
|
||||
if ( globs.cmdout )
|
||||
fclose( globs.cmdout );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
Py_Finalize();
|
||||
#endif
|
||||
|
||||
BJAM_MEM_CLOSE();
|
||||
|
||||
BJAM_MEM_CLOSE();
|
||||
|
||||
return status ? EXITBAD : EXITOK;
|
||||
}
|
||||
|
||||
836
src/engine/jam.h
836
src/engine/jam.h
@@ -49,80 +49,81 @@
|
||||
* VMS, OPENVMS
|
||||
*/
|
||||
|
||||
# ifdef VMS
|
||||
#ifdef VMS
|
||||
|
||||
# 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 <unistd.h>
|
||||
# include <unixlib.h>
|
||||
#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 <unistd.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
|
||||
#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
|
||||
/* This may be inaccurate. */
|
||||
#ifndef __DECC
|
||||
#define OSPLAT "OSPLAT=VAX"
|
||||
#endif
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Windows NT
|
||||
*/
|
||||
|
||||
# ifdef NT
|
||||
#ifdef NT
|
||||
|
||||
# include <fcntl.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
# include <ctype.h>
|
||||
# include <malloc.h>
|
||||
# ifndef __MWERKS__
|
||||
# include <memory.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <malloc.h>
|
||||
#ifndef __MWERKS__
|
||||
#include <memory.h>
|
||||
#endif
|
||||
# include <signal.h>
|
||||
# include <string.h>
|
||||
# include <time.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 (maxline()) /* longest 'together' actions */
|
||||
# define USE_EXECNT
|
||||
# define USE_PATHUNIX
|
||||
# define PATH_DELIM '\\'
|
||||
# define DOWNSHIFT_PATHS
|
||||
#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 the problem
|
||||
* in "execnt.c".
|
||||
*/
|
||||
#define MAXLINE (maxline()) /* longest 'together' actions */
|
||||
#define USE_EXECNT
|
||||
#define USE_PATHUNIX
|
||||
#define PATH_DELIM '\\'
|
||||
#define DOWNSHIFT_PATHS
|
||||
|
||||
/* AS400 cross-compile from NT */
|
||||
/* AS400 cross-compile from NT. */
|
||||
|
||||
# ifdef AS400
|
||||
# undef OSMINOR
|
||||
# undef OSMAJOR
|
||||
# define OSMAJOR "AS400=true"
|
||||
# define OSMINOR "OS=AS400"
|
||||
# define OS_AS400
|
||||
# endif
|
||||
#ifdef AS400
|
||||
#undef OSMINOR
|
||||
#undef OSMAJOR
|
||||
#define OSMAJOR "AS400=true"
|
||||
#define OSMINOR "OS=AS400"
|
||||
#define OS_AS400
|
||||
#endif
|
||||
|
||||
/* Metrowerks Standard Library on Windows. */
|
||||
|
||||
# ifdef __MSL__
|
||||
#undef HAVE_POPEN
|
||||
#ifdef __MSL__
|
||||
#undef HAVE_POPEN
|
||||
#endif
|
||||
|
||||
# endif
|
||||
@@ -131,435 +132,440 @@
|
||||
* Windows MingW32
|
||||
*/
|
||||
|
||||
# ifdef MINGW
|
||||
#ifdef MINGW
|
||||
|
||||
# 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>
|
||||
#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 "MINGW=true"
|
||||
# define OSMINOR "OS=MINGW"
|
||||
# define OS_NT
|
||||
# define SPLITPATH ';'
|
||||
# define MAXLINE 996 /* longest 'together' actions */
|
||||
# define USE_EXECUNIX
|
||||
# define USE_PATHUNIX
|
||||
# define PATH_DELIM '\\'
|
||||
# define DOWNSHIFT_PATHS
|
||||
#define OSMAJOR "MINGW=true"
|
||||
#define OSMINOR "OS=MINGW"
|
||||
#define OS_NT
|
||||
#define SPLITPATH ';'
|
||||
#define MAXLINE 996 /* longest 'together' actions */
|
||||
#define USE_EXECUNIX
|
||||
#define USE_PATHUNIX
|
||||
#define PATH_DELIM '\\'
|
||||
#define DOWNSHIFT_PATHS
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* OS2
|
||||
*/
|
||||
|
||||
# ifdef __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>
|
||||
#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
|
||||
#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
|
||||
#ifdef __EMX__
|
||||
#define USE_FILEUNIX
|
||||
#endif
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macintosh MPW
|
||||
*/
|
||||
|
||||
# ifdef macintosh
|
||||
#ifdef macintosh
|
||||
|
||||
# include <time.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <stdio.h>
|
||||
#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 ','
|
||||
#define OSMAJOR "MAC=true"
|
||||
#define OSMINOR "OS=MAC"
|
||||
#define OS_MAC
|
||||
#define SPLITPATH ','
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* God fearing UNIX
|
||||
* God fearing UNIX.
|
||||
*/
|
||||
|
||||
# ifndef OSMINOR
|
||||
#ifndef OSMINOR
|
||||
|
||||
# define OSMAJOR "UNIX=true"
|
||||
# define USE_EXECUNIX
|
||||
# define USE_FILEUNIX
|
||||
# define USE_PATHUNIX
|
||||
# define PATH_DELIM '/'
|
||||
#define OSMAJOR "UNIX=true"
|
||||
#define USE_EXECUNIX
|
||||
#define USE_FILEUNIX
|
||||
#define USE_PATHUNIX
|
||||
#define PATH_DELIM '/'
|
||||
|
||||
# ifdef _AIX
|
||||
# define unix
|
||||
# define MAXLINE 23552 /* 24k - 1k, longest 'together' actions */
|
||||
# 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
|
||||
# if defined(__cygwin__) || defined(__CYGWIN__)
|
||||
# define OSMINOR "OS=CYGWIN"
|
||||
# define OS_CYGWIN
|
||||
# endif
|
||||
# if defined(__FreeBSD__) && !defined(__DragonFly__)
|
||||
# define OSMINOR "OS=FREEBSD"
|
||||
# define OS_FREEBSD
|
||||
# endif
|
||||
# ifdef __DragonFly__
|
||||
# define OSMINOR "OS=DRAGONFLYBSD"
|
||||
# define OS_DRAGONFLYBSD
|
||||
# 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__
|
||||
# define unix
|
||||
# ifdef __QNXNTO__
|
||||
# define OSMINOR "OS=QNXNTO"
|
||||
# define OS_QNXNTO
|
||||
# else
|
||||
# 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__
|
||||
# ifndef unix
|
||||
# define unix
|
||||
# endif
|
||||
# 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
|
||||
# ifdef __OpenBSD__
|
||||
# define OSMINOR "OS=OPENBSD"
|
||||
# define OS_OPENBSD
|
||||
# define unix
|
||||
# endif
|
||||
# if defined (__FreeBSD_kernel__) && !defined(__FreeBSD__)
|
||||
# define OSMINOR "OS=KFREEBSD"
|
||||
# define OS_KFREEBSD
|
||||
# endif
|
||||
# ifndef OSMINOR
|
||||
# define OSMINOR "OS=UNKNOWN"
|
||||
# endif
|
||||
#ifdef _AIX
|
||||
#define unix
|
||||
#define MAXLINE 23552 /* 24k - 1k, longest 'together' actions */
|
||||
#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
|
||||
#if defined(__cygwin__) || defined(__CYGWIN__)
|
||||
#define OSMINOR "OS=CYGWIN"
|
||||
#define OS_CYGWIN
|
||||
#endif
|
||||
#if defined(__FreeBSD__) && !defined(__DragonFly__)
|
||||
#define OSMINOR "OS=FREEBSD"
|
||||
#define OS_FREEBSD
|
||||
#endif
|
||||
#ifdef __DragonFly__
|
||||
#define OSMINOR "OS=DRAGONFLYBSD"
|
||||
#define OS_DRAGONFLYBSD
|
||||
#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__
|
||||
#define unix
|
||||
#ifdef __QNXNTO__
|
||||
#define OSMINOR "OS=QNXNTO"
|
||||
#define OS_QNXNTO
|
||||
#else
|
||||
#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__
|
||||
#ifndef unix
|
||||
#define unix
|
||||
#endif
|
||||
#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
|
||||
#ifdef __OpenBSD__
|
||||
#define OSMINOR "OS=OPENBSD"
|
||||
#define OS_OPENBSD
|
||||
#define unix
|
||||
#endif
|
||||
#if defined (__FreeBSD_kernel__) && !defined(__FreeBSD__)
|
||||
#define OSMINOR "OS=KFREEBSD"
|
||||
#define OS_KFREEBSD
|
||||
#endif
|
||||
#ifndef OSMINOR
|
||||
#define OSMINOR "OS=UNKNOWN"
|
||||
#endif
|
||||
|
||||
/* All the UNIX includes */
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
# ifndef OS_MPEIX
|
||||
# include <sys/file.h>
|
||||
# endif
|
||||
#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>
|
||||
#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_QNX
|
||||
#include <memory.h>
|
||||
#endif
|
||||
|
||||
# ifndef OS_ULTRIX
|
||||
# include <stdlib.h>
|
||||
# endif
|
||||
#ifndef OS_ULTRIX
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
# if !defined(OS_BSDI) && \
|
||||
!defined(OS_FREEBSD) && \
|
||||
!defined(OS_DRAGONFLYBSD) && \
|
||||
!defined(OS_NEXT) && \
|
||||
!defined(OS_MACHTEN) && \
|
||||
!defined(OS_MACOSX) && \
|
||||
!defined(OS_RHAPSODY) && \
|
||||
!defined(OS_MVS) && \
|
||||
!defined(OS_OPENBSD)
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#if !defined( OS_BSDI ) && \
|
||||
!defined( OS_FREEBSD ) && \
|
||||
!defined( OS_DRAGONFLYBSD ) && \
|
||||
!defined( OS_NEXT ) && \
|
||||
!defined( OS_MACHTEN ) && \
|
||||
!defined( OS_MACOSX ) && \
|
||||
!defined( OS_RHAPSODY ) && \
|
||||
!defined( OS_MVS ) && \
|
||||
!defined( OS_OPENBSD )
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* OSPLAT definitions - suppressed when it's a one-of-a-kind
|
||||
/*
|
||||
* OSPLAT definitions - suppressed when it is a one-of-a-kind.
|
||||
*/
|
||||
|
||||
# if defined( _M_PPC ) || \
|
||||
defined( PPC ) || \
|
||||
defined( ppc ) || \
|
||||
defined( __powerpc__ ) || \
|
||||
defined( __ppc__ )
|
||||
# define OSPLAT "OSPLAT=PPC"
|
||||
# endif
|
||||
#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( _ALPHA_ ) || \
|
||||
defined( __alpha__ )
|
||||
#define OSPLAT "OSPLAT=AXP"
|
||||
#endif
|
||||
|
||||
# if defined( _i386_ ) || \
|
||||
defined( __i386__ ) || \
|
||||
defined( _M_IX86 )
|
||||
# define OSPLAT "OSPLAT=X86"
|
||||
# endif
|
||||
#if defined( _i386_ ) || \
|
||||
defined( __i386__ ) || \
|
||||
defined( _M_IX86 )
|
||||
#define OSPLAT "OSPLAT=X86"
|
||||
#endif
|
||||
|
||||
# if defined( __ia64__ ) || defined( __IA64__ ) || defined( __ia64 )
|
||||
# define OSPLAT "OSPLAT=IA64"
|
||||
# endif
|
||||
#if defined( __ia64__ ) || \
|
||||
defined( __IA64__ ) || \
|
||||
defined( __ia64 )
|
||||
#define OSPLAT "OSPLAT=IA64"
|
||||
#endif
|
||||
|
||||
# if \
|
||||
defined( __x86_64__ ) || \
|
||||
defined( __amd64__ ) || \
|
||||
defined( _M_AMD64 )
|
||||
# define OSPLAT "OSPLAT=X86_64"
|
||||
# endif
|
||||
#if defined( __x86_64__ ) || \
|
||||
defined( __amd64__ ) || \
|
||||
defined( _M_AMD64 )
|
||||
#define OSPLAT "OSPLAT=X86_64"
|
||||
#endif
|
||||
|
||||
|
||||
# ifdef __sparc__
|
||||
# define OSPLAT "OSPLAT=SPARC"
|
||||
# endif
|
||||
#ifdef __sparc__
|
||||
#define OSPLAT "OSPLAT=SPARC"
|
||||
#endif
|
||||
|
||||
# ifdef __mips__
|
||||
# define OSPLAT "OSPLAT=MIPS"
|
||||
# endif
|
||||
#ifdef __mips__
|
||||
#define OSPLAT "OSPLAT=MIPS"
|
||||
#endif
|
||||
|
||||
# ifdef __arm__
|
||||
# define OSPLAT "OSPLAT=ARM"
|
||||
# endif
|
||||
#ifdef __arm__
|
||||
#define OSPLAT "OSPLAT=ARM"
|
||||
#endif
|
||||
|
||||
# ifdef __s390__
|
||||
# define OSPLAT "OSPLAT=390"
|
||||
# endif
|
||||
#ifdef __s390__
|
||||
#define OSPLAT "OSPLAT=390"
|
||||
#endif
|
||||
|
||||
# ifdef __hppa
|
||||
# define OSPLAT "OSPLAT=PARISC"
|
||||
# endif
|
||||
#ifdef __hppa
|
||||
#define OSPLAT "OSPLAT=PARISC"
|
||||
#endif
|
||||
|
||||
# ifndef OSPLAT
|
||||
# define OSPLAT ""
|
||||
# endif
|
||||
#ifndef OSPLAT
|
||||
#define OSPLAT ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Jam implementation misc.
|
||||
*/
|
||||
|
||||
# ifndef MAXLINE
|
||||
# define MAXLINE 102400 /* longest 'together' actions' */
|
||||
# endif
|
||||
#ifndef MAXLINE
|
||||
#define MAXLINE 102400 /* longest 'together' actions' */
|
||||
#endif
|
||||
|
||||
# ifndef EXITOK
|
||||
# define EXITOK 0
|
||||
# define EXITBAD 1
|
||||
# endif
|
||||
#ifndef EXITOK
|
||||
#define EXITOK 0
|
||||
#define EXITBAD 1
|
||||
#endif
|
||||
|
||||
# ifndef SPLITPATH
|
||||
# define SPLITPATH ':'
|
||||
# endif
|
||||
#ifndef SPLITPATH
|
||||
#define SPLITPATH ':'
|
||||
#endif
|
||||
|
||||
/* You probably don't need to muck with these. */
|
||||
/* You probably do not need to muck with these. */
|
||||
|
||||
# define MAXSYM 1024 /* longest symbol in the environment */
|
||||
# define MAXJPATH 1024 /* longest filename */
|
||||
#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) */
|
||||
#define MAXJOBS 64 /* silently enforced -j limit */
|
||||
#define MAXARGC 32 /* words in $(JAMSHELL) */
|
||||
|
||||
/* Jam private definitions below. */
|
||||
|
||||
# define DEBUG_MAX 14
|
||||
#define DEBUG_MAX 14
|
||||
|
||||
struct globs {
|
||||
int noexec;
|
||||
int jobs;
|
||||
int quitquick;
|
||||
int newestfirst; /* build newest sources first */
|
||||
int pipe_action;
|
||||
char debug[DEBUG_MAX];
|
||||
FILE *cmdout; /* print cmds, not run them */
|
||||
long timeout; /* number of seconds to limit actions to, default 0 for no limit. */
|
||||
int dart; /* output build and test results formatted for Dart */
|
||||
} ;
|
||||
|
||||
struct globs
|
||||
{
|
||||
int noexec;
|
||||
int jobs;
|
||||
int quitquick;
|
||||
int newestfirst; /* build newest sources first */
|
||||
int pipe_action;
|
||||
char debug[ DEBUG_MAX ];
|
||||
FILE * cmdout; /* print cmds, not run them */
|
||||
long timeout; /* number of seconds to limit actions to,
|
||||
* default 0 for no limit.
|
||||
*/
|
||||
int dart; /* output build and test results formatted for Dart */
|
||||
};
|
||||
|
||||
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_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_EXECCMD ( globs.debug[ 4 ] ) /* show execcmds()'s work */
|
||||
|
||||
# define DEBUG_COMPILE ( globs.debug[ 5 ] ) /* show rule invocations */
|
||||
#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_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_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 */
|
||||
# define DEBUG_GRAPH ( globs.debug[ 12 ] ) /* debug dependencies */
|
||||
# define DEBUG_FATE ( globs.debug[ 13 ] ) /* show changes to fate in make0() */
|
||||
#define DEBUG_PROFILE ( globs.debug[ 10 ] ) /* dump rule execution times */
|
||||
#define DEBUG_PARSE ( globs.debug[ 11 ] ) /* debug parsing */
|
||||
#define DEBUG_GRAPH ( globs.debug[ 12 ] ) /* debug dependencies */
|
||||
#define DEBUG_FATE ( globs.debug[ 13 ] ) /* show changes to fate in make0() */
|
||||
|
||||
/* Everyone gets the memory definitions. */
|
||||
#include "mem.h"
|
||||
|
||||
@@ -34,7 +34,7 @@ char *jambase[] = {
|
||||
"{\n",
|
||||
"if $(.bootstrap-file)\n",
|
||||
"{\n",
|
||||
"EXIT \"Error: Illegal attempt to re-bootstrap the build system by invoking\" ;\n",
|
||||
"ECHO \"Error: Illegal attempt to re-bootstrap the build system by invoking\" ;\n",
|
||||
"ECHO ;\n",
|
||||
"ECHO \" 'boost-build\" $(dir) \";'\" ;\n",
|
||||
"ECHO ;\n",
|
||||
@@ -42,8 +42,7 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"BOOST_BUILD_PATH = $(dir:R=$(.boost-build-file:D)) $(BOOST_BUILD_PATH) ;\n",
|
||||
"_poke .ENVIRON : BOOST_BUILD_PATH : $(BOOST_BUILD_PATH) ;\n",
|
||||
"local bootstrap-file =\n",
|
||||
"[ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;\n",
|
||||
"local bootstrap-file = [ GLOB $(BOOST_BUILD_PATH) : bootstrap.jam ] ;\n",
|
||||
".bootstrap-file = $(bootstrap-file[1]) ;\n",
|
||||
"if ! $(.bootstrap-file)\n",
|
||||
"{\n",
|
||||
@@ -60,13 +59,13 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"if [ MATCH .*(--debug-configuration).* : $(ARGV) ]\n",
|
||||
"{\n",
|
||||
"ECHO \"notice: loading Boost.Build from\" \n",
|
||||
"ECHO \"notice: loading Boost.Build from\"\n",
|
||||
"[ NORMALIZE_PATH $(.bootstrap-file:D) ] ;\n",
|
||||
"}\n",
|
||||
"include $(.bootstrap-file) ;\n",
|
||||
"}\n",
|
||||
"if [ MATCH .*(bjam).* : $(ARGV[1]:BL) ]\n",
|
||||
"|| $(BOOST_ROOT) # A temporary measure so Jam works with Boost.Build v1\n",
|
||||
"|| $(BOOST_ROOT) # A temporary measure so Jam works with Boost.Build v1.\n",
|
||||
"{\n",
|
||||
"local search-path = $(BOOST_BUILD_PATH) $(BOOST_ROOT) ;\n",
|
||||
"local boost-build-files =\n",
|
||||
@@ -88,9 +87,9 @@ char *jambase[] = {
|
||||
"ECHO \"and in these directories from BOOST_BUILD_PATH and BOOST_ROOT: \"$(search-path:J=\", \")\".\" ;\n",
|
||||
"EXIT \"Please consult the documentation at 'http://www.boost.org'.\" ;\n",
|
||||
"}\n",
|
||||
"if [ MATCH .*(--debug-configuration).* : $(ARGV) ] \n",
|
||||
"if [ MATCH .*(--debug-configuration).* : $(ARGV) ]\n",
|
||||
"{\n",
|
||||
"ECHO \"notice: found boost-build.jam at\" \n",
|
||||
"ECHO \"notice: found boost-build.jam at\"\n",
|
||||
"[ NORMALIZE_PATH $(.boost-build-file) ] ;\n",
|
||||
"}\n",
|
||||
"include $(.boost-build-file) ;\n",
|
||||
@@ -217,7 +216,7 @@ char *jambase[] = {
|
||||
"C++FLAGS ?= $(CCFLAGS) ;\n",
|
||||
"LINK ?= $(CC) ;\n",
|
||||
"LINKFLAGS ?= $(CCFLAGS) ;\n",
|
||||
"LINKLIBS ?= \n",
|
||||
"LINKLIBS ?=\n",
|
||||
"\\\"$(VISUALC16)\\\\lib\\\\mlibce.lib\\\"\n",
|
||||
"\\\"$(VISUALC16)\\\\lib\\\\oldnames.lib\\\"\n",
|
||||
";\n",
|
||||
@@ -478,7 +477,7 @@ char *jambase[] = {
|
||||
"SUFEXE ?= .exe ;\n",
|
||||
"SUFLIB ?= .olb ;\n",
|
||||
"SUFOBJ ?= .obj ;\n",
|
||||
"switch $(OS) \n",
|
||||
"switch $(OS)\n",
|
||||
"{\n",
|
||||
"case OPENVMS : CCFLAGS ?= /stand=vaxc ;\n",
|
||||
"case VMS : LINKLIBS ?= sys$library:vaxcrtl.olb/lib ;\n",
|
||||
@@ -495,16 +494,16 @@ char *jambase[] = {
|
||||
"MACLIBS ?=\n",
|
||||
"\"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Interfacelib\"\n",
|
||||
"\"$(CW):MacOS Support:Universal:Libraries:StubLibraries:Mathlib\" ;\n",
|
||||
"MPWLIBS ?= \n",
|
||||
"MPWLIBS ?=\n",
|
||||
"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib\"\n",
|
||||
"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW.Lib\" ;\n",
|
||||
"MPWNLLIBS ?= \n",
|
||||
"MPWNLLIBS ?=\n",
|
||||
"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL MPWCRuntime.lib\"\n",
|
||||
"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC MPW(NL).Lib\" ;\n",
|
||||
"SIOUXHDRS ?= ;\n",
|
||||
"SIOUXLIBS ?= \n",
|
||||
"SIOUXLIBS ?=\n",
|
||||
"\"$(CW):MacOS Support:Libraries:Runtime:Runtime PPC:MSL RuntimePPC.lib\"\n",
|
||||
"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib\" \n",
|
||||
"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL SIOUX.PPC.Lib\"\n",
|
||||
"\"$(CW):MSL:MSL_C:MSL_MacOS:Lib:PPC:MSL C.PPC.Lib\" ;\n",
|
||||
"C++ ?= mwcppc ;\n",
|
||||
"C++FLAGS ?= -w off -nomapcr ;\n",
|
||||
@@ -515,15 +514,15 @@ char *jambase[] = {
|
||||
"DOTDOT ?= \"::\" ;\n",
|
||||
"HDRS ?= $(MACHDRS) $(MPWHDRS) ;\n",
|
||||
"LINK ?= mwlinkppc ;\n",
|
||||
"LINKFLAGS ?= -mpwtool -warn ; \n",
|
||||
"LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ; \n",
|
||||
"LINKFLAGS ?= -mpwtool -warn ;\n",
|
||||
"LINKLIBS ?= $(MACLIBS) $(MPWLIBS) ;\n",
|
||||
"MKDIR ?= newfolder ;\n",
|
||||
"MV ?= rename -y ;\n",
|
||||
"NOARSCAN ?= true ;\n",
|
||||
"OPTIM ?= ;\n",
|
||||
"RM ?= delete -y ;\n",
|
||||
"SLASH ?= \":\" ;\n",
|
||||
"STDHDRS ?= ; \n",
|
||||
"STDHDRS ?= ;\n",
|
||||
"SUFLIB ?= .lib ;\n",
|
||||
"SUFOBJ ?= .o ;\n",
|
||||
"}\n",
|
||||
@@ -543,7 +542,7 @@ char *jambase[] = {
|
||||
"NOARSCAN ?= true ;\n",
|
||||
"STDHDRS ?= /boot/develop/headers/posix ;\n",
|
||||
"}\n",
|
||||
"else if $(OS) = BEOS \n",
|
||||
"else if $(OS) = BEOS\n",
|
||||
"{\n",
|
||||
"BINDIR ?= /boot/apps ;\n",
|
||||
"CC ?= gcc ;\n",
|
||||
@@ -564,7 +563,7 @@ char *jambase[] = {
|
||||
"case AMIGA :\n",
|
||||
"CC ?= gcc ;\n",
|
||||
"YACC ?= \"bison -y\" ;\n",
|
||||
"case CYGWIN : \n",
|
||||
"case CYGWIN :\n",
|
||||
"CC ?= gcc ;\n",
|
||||
"CCFLAGS += -D__cygwin__ ;\n",
|
||||
"LEX ?= flex ;\n",
|
||||
@@ -589,11 +588,11 @@ char *jambase[] = {
|
||||
"C++ ?= gcc ;\n",
|
||||
"CCFLAGS += -D_POSIX_SOURCE ;\n",
|
||||
"HDRS += /usr/include ;\n",
|
||||
"RANLIB ?= \"\" ; \n",
|
||||
"RANLIB ?= \"\" ;\n",
|
||||
"NOARSCAN ?= true ;\n",
|
||||
"NOARUPDATE ?= true ;\n",
|
||||
"case MVS :\n",
|
||||
"RANLIB ?= \"\" ; \n",
|
||||
"RANLIB ?= \"\" ;\n",
|
||||
"case NEXT :\n",
|
||||
"AR ?= libtool -o ;\n",
|
||||
"RANLIB ?= \"\" ;\n",
|
||||
@@ -691,7 +690,7 @@ char *jambase[] = {
|
||||
"YACC ?= ;\n",
|
||||
"YACCFILES ?= ;\n",
|
||||
"YACCFLAGS ?= ;\n",
|
||||
"HDRPATTERN = \n",
|
||||
"HDRPATTERN =\n",
|
||||
"\"^[ ]*#[ ]*include[ ]*[<\\\"]([^\\\">]*)[\\\">].*$\" ;\n",
|
||||
"OSFULL = $(OS)$(OSVER)$(OSPLAT) $(OS)$(OSPLAT) $(OS)$(OSVER) $(OS) ;\n",
|
||||
"DEPENDS all : shell files lib exe obj ;\n",
|
||||
@@ -777,7 +776,7 @@ char *jambase[] = {
|
||||
"{\n",
|
||||
"DEPENDS $(<) : $(>) ;\n",
|
||||
"}\n",
|
||||
"rule GenFile \n",
|
||||
"rule GenFile\n",
|
||||
"{\n",
|
||||
"local _t = [ FGristSourceFiles $(<) ] ;\n",
|
||||
"local _s = [ FAppendSuffix $(>[1]) : $(SUFEXE) ] ;\n",
|
||||
@@ -803,11 +802,11 @@ char *jambase[] = {
|
||||
"rule HdrRule\n",
|
||||
"{\n",
|
||||
"local s ;\n",
|
||||
"if $(HDRGRIST) \n",
|
||||
"{ \n",
|
||||
"if $(HDRGRIST)\n",
|
||||
"{\n",
|
||||
"s = $(>:G=$(HDRGRIST)) ;\n",
|
||||
"} else { \n",
|
||||
"s = $(>) ; \n",
|
||||
"} else {\n",
|
||||
"s = $(>) ;\n",
|
||||
"}\n",
|
||||
"INCLUDES $(<) : $(s) ;\n",
|
||||
"SEARCH on $(s) = $(HDRSEARCH) ;\n",
|
||||
@@ -831,13 +830,13 @@ char *jambase[] = {
|
||||
"Depends $(tt) : $(i) ;\n",
|
||||
"Install $(tt) : $(i) ;\n",
|
||||
"Chmod $(tt) ;\n",
|
||||
"if $(OWNER) && $(CHOWN) \n",
|
||||
"{ \n",
|
||||
"if $(OWNER) && $(CHOWN)\n",
|
||||
"{\n",
|
||||
"Chown $(tt) ;\n",
|
||||
"OWNER on $(tt) = $(OWNER) ;\n",
|
||||
"}\n",
|
||||
"if $(GROUP) && $(CHGRP) \n",
|
||||
"{ \n",
|
||||
"if $(GROUP) && $(CHGRP)\n",
|
||||
"{\n",
|
||||
"Chgrp $(tt) ;\n",
|
||||
"GROUP on $(tt) = $(GROUP) ;\n",
|
||||
"}\n",
|
||||
@@ -910,8 +909,8 @@ char *jambase[] = {
|
||||
"{\n",
|
||||
"MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ;\n",
|
||||
"}\n",
|
||||
"if $(NOARSCAN) \n",
|
||||
"{ \n",
|
||||
"if $(NOARSCAN)\n",
|
||||
"{\n",
|
||||
"DEPENDS $(_l) : $(_s) ;\n",
|
||||
"}\n",
|
||||
"else\n",
|
||||
@@ -972,7 +971,7 @@ char *jambase[] = {
|
||||
"rule MkDir\n",
|
||||
"{\n",
|
||||
"NOUPDATE $(<) ;\n",
|
||||
"if $(<) != $(DOT) && ! $($(<)-mkdir) \n",
|
||||
"if $(<) != $(DOT) && ! $($(<)-mkdir)\n",
|
||||
"{\n",
|
||||
"local s ;\n",
|
||||
"$(<)-mkdir = true ;\n",
|
||||
@@ -1157,13 +1156,13 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"return $(_g) ;\n",
|
||||
"}\n",
|
||||
"rule FGristFiles \n",
|
||||
"rule FGristFiles\n",
|
||||
"{\n",
|
||||
"if ! $(SOURCE_GRIST)\n",
|
||||
"{\n",
|
||||
"return $(<) ;\n",
|
||||
"}\n",
|
||||
"else \n",
|
||||
"else\n",
|
||||
"{\n",
|
||||
"return $(<:G=$(SOURCE_GRIST)) ;\n",
|
||||
"}\n",
|
||||
@@ -1174,7 +1173,7 @@ char *jambase[] = {
|
||||
"{\n",
|
||||
"return $(<) ;\n",
|
||||
"}\n",
|
||||
"else \n",
|
||||
"else\n",
|
||||
"{\n",
|
||||
"local _i _o ;\n",
|
||||
"for _i in $(<)\n",
|
||||
@@ -1201,10 +1200,10 @@ char *jambase[] = {
|
||||
"rule FSubDir\n",
|
||||
"{\n",
|
||||
"local _i _d ;\n",
|
||||
"if ! $(<[1]) \n",
|
||||
"if ! $(<[1])\n",
|
||||
"{\n",
|
||||
"_d = $(DOT) ;\n",
|
||||
"} \n",
|
||||
"}\n",
|
||||
"else\n",
|
||||
"{\n",
|
||||
"_d = $(DOTDOT) ;\n",
|
||||
@@ -1245,7 +1244,7 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"else\n",
|
||||
"{\n",
|
||||
"_s = $(<[1]) ; \n",
|
||||
"_s = $(<[1]) ;\n",
|
||||
"for _i in $(<[2-])\n",
|
||||
"{\n",
|
||||
"_s = $(_i:R=$(_s)) ;\n",
|
||||
@@ -1301,7 +1300,7 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"rule unmakeDir\n",
|
||||
"{\n",
|
||||
"if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\\\\\ \n",
|
||||
"if $(>[1]:D) && $(>[1]:D) != $(>[1]) && $(>[1]:D) != \\\\\\\\\n",
|
||||
"{\n",
|
||||
"unmakeDir $(<) : $(>[1]:D) $(>[1]:BS) $(>[2-]) ;\n",
|
||||
"}\n",
|
||||
@@ -1314,7 +1313,7 @@ char *jambase[] = {
|
||||
"{\n",
|
||||
"local _d, _s, _i ;\n",
|
||||
"unmakeDir _d : $(<) ;\n",
|
||||
"_s = $(_d[1]) ; \n",
|
||||
"_s = $(_d[1]) ;\n",
|
||||
"for _i in $(_d[2-])\n",
|
||||
"{\n",
|
||||
"_s = $(_s)/$(_i) ;\n",
|
||||
@@ -1371,7 +1370,7 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"actions Install\n",
|
||||
"{\n",
|
||||
"$(CP) $(>) $(<) \n",
|
||||
"$(CP) $(>) $(<)\n",
|
||||
"}\n",
|
||||
"actions Lex\n",
|
||||
"{\n",
|
||||
@@ -1383,7 +1382,7 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"actions Link bind NEEDLIBS\n",
|
||||
"{\n",
|
||||
"$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS) \n",
|
||||
"$(LINK) $(LINKFLAGS) -o $(<) $(UNDEFS) $(>) $(NEEDLIBS) $(LINKLIBS)\n",
|
||||
"}\n",
|
||||
"actions MkDir1\n",
|
||||
"{\n",
|
||||
@@ -1520,7 +1519,7 @@ char *jambase[] = {
|
||||
"{\n",
|
||||
"actions together piecemeal Archive\n",
|
||||
"{\n",
|
||||
"$(AR) $(<) +-$(>) \n",
|
||||
"$(AR) $(<) +-$(>)\n",
|
||||
"}\n",
|
||||
"actions Cc\n",
|
||||
"{\n",
|
||||
@@ -1543,7 +1542,7 @@ char *jambase[] = {
|
||||
"{\n",
|
||||
"actions together piecemeal Archive\n",
|
||||
"{\n",
|
||||
"$(AR) /out:$(<) $(>) \n",
|
||||
"$(AR) /out:$(<) $(>)\n",
|
||||
"}\n",
|
||||
"actions Cc\n",
|
||||
"{\n",
|
||||
@@ -1559,13 +1558,13 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"}\n",
|
||||
"}\n",
|
||||
"else if $(OS2) \n",
|
||||
"else if $(OS2)\n",
|
||||
"{\n",
|
||||
"if $(TOOLSET) = WATCOM\n",
|
||||
"{\n",
|
||||
"actions together piecemeal Archive\n",
|
||||
"{\n",
|
||||
"$(AR) $(<) +-$(>) \n",
|
||||
"$(AR) $(<) +-$(>)\n",
|
||||
"}\n",
|
||||
"actions Cc\n",
|
||||
"{\n",
|
||||
@@ -1602,17 +1601,17 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"else if $(VMS)\n",
|
||||
"{\n",
|
||||
"actions updated together piecemeal Archive \n",
|
||||
"actions updated together piecemeal Archive\n",
|
||||
"{\n",
|
||||
"lib/replace $(<) $(>[1]) ,$(>[2-])\n",
|
||||
"}\n",
|
||||
"actions Cc\n",
|
||||
"{ \n",
|
||||
"$(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>) \n",
|
||||
"{\n",
|
||||
"$(CC)/obj=$(<) $(CCFLAGS) $(OPTIM) $(SLASHINC) $(>)\n",
|
||||
"}\n",
|
||||
"actions C++\n",
|
||||
"{ \n",
|
||||
"$(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>) \n",
|
||||
"{\n",
|
||||
"$(C++)/obj=$(<) $(C++FLAGS) $(OPTIM) $(SLASHINC) $(>)\n",
|
||||
"}\n",
|
||||
"actions piecemeal together existing Clean\n",
|
||||
"{\n",
|
||||
@@ -1641,19 +1640,19 @@ char *jambase[] = {
|
||||
"}\n",
|
||||
"else if $(MAC)\n",
|
||||
"{\n",
|
||||
"actions together Archive \n",
|
||||
"actions together Archive\n",
|
||||
"{\n",
|
||||
"$(LINK) -library -o $(<) $(>)\n",
|
||||
"}\n",
|
||||
"actions Cc\n",
|
||||
"{\n",
|
||||
"set -e MWCincludes $(MACINC)\n",
|
||||
"$(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>) \n",
|
||||
"$(CC) -o $(<) $(CCFLAGS) $(OPTIM) $(>)\n",
|
||||
"}\n",
|
||||
"actions C++\n",
|
||||
"{ \n",
|
||||
"{\n",
|
||||
"set -e MWCincludes $(MACINC)\n",
|
||||
"$(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>) \n",
|
||||
"$(CC) -o $(<) $(C++FLAGS) $(OPTIM) $(>)\n",
|
||||
"}\n",
|
||||
"actions Link bind NEEDLIBS\n",
|
||||
"{\n",
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* 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
|
||||
* so that it can be built in to the executable. This is the
|
||||
* declaration for that array.
|
||||
*/
|
||||
|
||||
|
||||
@@ -438,17 +438,17 @@ static const unsigned short yyrline[] =
|
||||
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
|
||||
static const char *const yytname[] =
|
||||
{
|
||||
"$end", "error", "$undefined", "_BANG_t", "_BANG_EQUALS_t", "_AMPER_t",
|
||||
"_AMPERAMPER_t", "_LPAREN_t", "_RPAREN_t", "_PLUS_EQUALS_t", "_COLON_t",
|
||||
"_SEMIC_t", "_LANGLE_t", "_LANGLE_EQUALS_t", "_EQUALS_t", "_RANGLE_t",
|
||||
"_RANGLE_EQUALS_t", "_QUESTION_EQUALS_t", "_LBRACKET_t", "_RBRACKET_t",
|
||||
"ACTIONS_t", "BIND_t", "CASE_t", "CLASS_t", "DEFAULT_t", "ELSE_t",
|
||||
"EXISTING_t", "FOR_t", "IF_t", "IGNORE_t", "IN_t", "INCLUDE_t",
|
||||
"LOCAL_t", "MODULE_t", "ON_t", "PIECEMEAL_t", "QUIETLY_t", "RETURN_t",
|
||||
"RULE_t", "SWITCH_t", "TOGETHER_t", "UPDATED_t", "WHILE_t", "_LBRACE_t",
|
||||
"_BAR_t", "_BARBAR_t", "_RBRACE_t", "ARG", "STRING", "$accept", "run",
|
||||
"block", "rules", "null", "assign_list_opt", "arglist_opt", "local_opt",
|
||||
"rule", "@1", "@2", "assign", "expr", "cases", "case", "lol", "list",
|
||||
"$end", "error", "$undefined", "_BANG_t", "_BANG_EQUALS_t", "_AMPER_t",
|
||||
"_AMPERAMPER_t", "_LPAREN_t", "_RPAREN_t", "_PLUS_EQUALS_t", "_COLON_t",
|
||||
"_SEMIC_t", "_LANGLE_t", "_LANGLE_EQUALS_t", "_EQUALS_t", "_RANGLE_t",
|
||||
"_RANGLE_EQUALS_t", "_QUESTION_EQUALS_t", "_LBRACKET_t", "_RBRACKET_t",
|
||||
"ACTIONS_t", "BIND_t", "CASE_t", "CLASS_t", "DEFAULT_t", "ELSE_t",
|
||||
"EXISTING_t", "FOR_t", "IF_t", "IGNORE_t", "IN_t", "INCLUDE_t",
|
||||
"LOCAL_t", "MODULE_t", "ON_t", "PIECEMEAL_t", "QUIETLY_t", "RETURN_t",
|
||||
"RULE_t", "SWITCH_t", "TOGETHER_t", "UPDATED_t", "WHILE_t", "_LBRACE_t",
|
||||
"_BAR_t", "_BARBAR_t", "_RBRACE_t", "ARG", "STRING", "$accept", "run",
|
||||
"block", "rules", "null", "assign_list_opt", "arglist_opt", "local_opt",
|
||||
"rule", "@1", "@2", "assign", "expr", "cases", "case", "lol", "list",
|
||||
"listp", "arg", "@3", "func", "eflags", "eflag", "bindlist", 0
|
||||
};
|
||||
#endif
|
||||
@@ -1007,7 +1007,7 @@ yyparse ()
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
|
||||
|
||||
register int yystate;
|
||||
register int yyn;
|
||||
int yyresult;
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
*
|
||||
* New "[ rule ]" syntax evals rule into a LIST.
|
||||
*
|
||||
* Lists are now generated by compile_list() and
|
||||
* 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.
|
||||
@@ -81,7 +81,7 @@
|
||||
* New 'return' rule sets the return value, though
|
||||
* other statements also may have return values.
|
||||
*
|
||||
* 'run' production split from 'block' production so
|
||||
* 'run' production split from 'block' production so
|
||||
* that empty blocks can be handled separately.
|
||||
*/
|
||||
|
||||
@@ -201,13 +201,13 @@ rule : _LBRACE_t block _RBRACE_t
|
||||
{ $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
|
||||
| SWITCH_t list _LBRACE_t cases _RBRACE_t
|
||||
{ $$.parse = pswitch( $2.parse, $4.parse ); }
|
||||
| IF_t expr _LBRACE_t block _RBRACE_t
|
||||
| IF_t expr _LBRACE_t block _RBRACE_t
|
||||
{ $$.parse = pif( $2.parse, $4.parse, pnull() ); }
|
||||
| MODULE_t list _LBRACE_t block _RBRACE_t
|
||||
| MODULE_t list _LBRACE_t block _RBRACE_t
|
||||
{ $$.parse = pmodule( $2.parse, $4.parse ); }
|
||||
| CLASS_t lol _LBRACE_t block _RBRACE_t
|
||||
| CLASS_t lol _LBRACE_t block _RBRACE_t
|
||||
{ $$.parse = pclass( $2.parse, $4.parse ); }
|
||||
| WHILE_t expr _LBRACE_t block _RBRACE_t
|
||||
| WHILE_t expr _LBRACE_t block _RBRACE_t
|
||||
{ $$.parse = pwhile( $2.parse, $4.parse ); }
|
||||
| IF_t expr _LBRACE_t block _RBRACE_t ELSE_t rule
|
||||
{ $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
|
||||
@@ -217,7 +217,7 @@ rule : _LBRACE_t block _RBRACE_t
|
||||
{ $$.parse = pon( $2.parse, $3.parse ); }
|
||||
| ACTIONS_t eflags ARG bindlist _LBRACE_t
|
||||
{ yymode( SCAN_STRING ); }
|
||||
STRING
|
||||
STRING
|
||||
{ yymode( SCAN_NORMAL ); }
|
||||
_RBRACE_t
|
||||
{ $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
|
||||
@@ -240,23 +240,23 @@ assign : _EQUALS_t
|
||||
/*
|
||||
* expr - an expression for if
|
||||
*/
|
||||
expr : arg
|
||||
expr : arg
|
||||
{ $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
|
||||
| expr _EQUALS_t expr
|
||||
| expr _EQUALS_t expr
|
||||
{ $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
|
||||
| expr _BANG_EQUALS_t expr
|
||||
{ $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
|
||||
| expr _LANGLE_t expr
|
||||
{ $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
|
||||
| expr _LANGLE_EQUALS_t expr
|
||||
| expr _LANGLE_EQUALS_t expr
|
||||
{ $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
|
||||
| expr _RANGLE_t expr
|
||||
| expr _RANGLE_t expr
|
||||
{ $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
|
||||
| expr _RANGLE_EQUALS_t expr
|
||||
| expr _RANGLE_EQUALS_t expr
|
||||
{ $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
|
||||
| expr _AMPER_t expr
|
||||
| expr _AMPER_t expr
|
||||
{ $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
|
||||
| expr _AMPERAMPER_t expr
|
||||
| expr _AMPERAMPER_t expr
|
||||
{ $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
|
||||
| expr _BAR_t expr
|
||||
{ $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
|
||||
@@ -314,7 +314,7 @@ listp : /* empty */
|
||||
{ $$.parse = pappend( $1.parse, $2.parse ); }
|
||||
;
|
||||
|
||||
arg : ARG
|
||||
arg : ARG
|
||||
{ $$.parse = plist( $1.string ); }
|
||||
| _LBRACKET_t { yymode( SCAN_NORMAL ); } func _RBRACKET_t
|
||||
{ $$.parse = $3.parse; }
|
||||
@@ -329,7 +329,7 @@ func : arg lol
|
||||
{ $$.parse = prule( $1.string, $2.parse ); }
|
||||
| ON_t arg arg lol
|
||||
{ $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
|
||||
| ON_t arg RETURN_t list
|
||||
| ON_t arg RETURN_t list
|
||||
{ $$.parse = pon( $2.parse, $4.parse ); }
|
||||
;
|
||||
|
||||
@@ -369,5 +369,3 @@ bindlist : /* empty */
|
||||
| BIND_t list
|
||||
{ $$.parse = $2.parse; }
|
||||
;
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
*
|
||||
* New "[ rule ]" syntax evals rule into a LIST.
|
||||
*
|
||||
* Lists are now generated by compile_list() and
|
||||
* 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.
|
||||
@@ -37,7 +37,7 @@
|
||||
* New 'return' rule sets the return value, though
|
||||
* other statements also may have return values.
|
||||
*
|
||||
* 'run' production split from 'block' production so
|
||||
* 'run' production split from 'block' production so
|
||||
* that empty blocks can be handled separately.
|
||||
*/
|
||||
|
||||
@@ -157,13 +157,13 @@ rule : `{` block `}`
|
||||
{ $$.parse = pfor( $3.string, $5.parse, $7.parse, $2.number ); }
|
||||
| `switch` list `{` cases `}`
|
||||
{ $$.parse = pswitch( $2.parse, $4.parse ); }
|
||||
| `if` expr `{` block `}`
|
||||
| `if` expr `{` block `}`
|
||||
{ $$.parse = pif( $2.parse, $4.parse, pnull() ); }
|
||||
| `module` list `{` block `}`
|
||||
| `module` list `{` block `}`
|
||||
{ $$.parse = pmodule( $2.parse, $4.parse ); }
|
||||
| `class` lol `{` block `}`
|
||||
| `class` lol `{` block `}`
|
||||
{ $$.parse = pclass( $2.parse, $4.parse ); }
|
||||
| `while` expr `{` block `}`
|
||||
| `while` expr `{` block `}`
|
||||
{ $$.parse = pwhile( $2.parse, $4.parse ); }
|
||||
| `if` expr `{` block `}` `else` rule
|
||||
{ $$.parse = pif( $2.parse, $4.parse, $7.parse ); }
|
||||
@@ -173,7 +173,7 @@ rule : `{` block `}`
|
||||
{ $$.parse = pon( $2.parse, $3.parse ); }
|
||||
| `actions` eflags ARG bindlist `{`
|
||||
{ yymode( SCAN_STRING ); }
|
||||
STRING
|
||||
STRING
|
||||
{ yymode( SCAN_NORMAL ); }
|
||||
`}`
|
||||
{ $$.parse = psete( $3.string,$4.parse,$7.string,$2.number ); }
|
||||
@@ -196,23 +196,23 @@ assign : `=`
|
||||
/*
|
||||
* expr - an expression for if
|
||||
*/
|
||||
expr : arg
|
||||
expr : arg
|
||||
{ $$.parse = peval( EXPR_EXISTS, $1.parse, pnull() ); }
|
||||
| expr `=` expr
|
||||
| expr `=` expr
|
||||
{ $$.parse = peval( EXPR_EQUALS, $1.parse, $3.parse ); }
|
||||
| expr `!=` expr
|
||||
{ $$.parse = peval( EXPR_NOTEQ, $1.parse, $3.parse ); }
|
||||
| expr `<` expr
|
||||
{ $$.parse = peval( EXPR_LESS, $1.parse, $3.parse ); }
|
||||
| expr `<=` expr
|
||||
| expr `<=` expr
|
||||
{ $$.parse = peval( EXPR_LESSEQ, $1.parse, $3.parse ); }
|
||||
| expr `>` expr
|
||||
| expr `>` expr
|
||||
{ $$.parse = peval( EXPR_MORE, $1.parse, $3.parse ); }
|
||||
| expr `>=` expr
|
||||
| expr `>=` expr
|
||||
{ $$.parse = peval( EXPR_MOREEQ, $1.parse, $3.parse ); }
|
||||
| expr `&` expr
|
||||
| expr `&` expr
|
||||
{ $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
|
||||
| expr `&&` expr
|
||||
| expr `&&` expr
|
||||
{ $$.parse = peval( EXPR_AND, $1.parse, $3.parse ); }
|
||||
| expr `|` expr
|
||||
{ $$.parse = peval( EXPR_OR, $1.parse, $3.parse ); }
|
||||
@@ -270,7 +270,7 @@ listp : /* empty */
|
||||
{ $$.parse = pappend( $1.parse, $2.parse ); }
|
||||
;
|
||||
|
||||
arg : ARG
|
||||
arg : ARG
|
||||
{ $$.parse = plist( $1.string ); }
|
||||
| `[` { yymode( SCAN_NORMAL ); } func `]`
|
||||
{ $$.parse = $3.parse; }
|
||||
@@ -285,7 +285,7 @@ func : arg lol
|
||||
{ $$.parse = prule( $1.string, $2.parse ); }
|
||||
| `on` arg arg lol
|
||||
{ $$.parse = pon( $2.parse, prule( $3.string, $4.parse ) ); }
|
||||
| `on` arg `return` list
|
||||
| `on` arg `return` list
|
||||
{ $$.parse = pon( $2.parse, $4.parse ); }
|
||||
;
|
||||
|
||||
|
||||
@@ -13,228 +13,174 @@
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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() */
|
||||
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 )
|
||||
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;
|
||||
}
|
||||
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;
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* list_new() - tack a string onto the end of a list of strings
|
||||
*/
|
||||
|
||||
LIST *
|
||||
list_new(
|
||||
LIST *head,
|
||||
char *string )
|
||||
LIST * list_new( LIST * head, char * string )
|
||||
{
|
||||
LIST *l;
|
||||
LIST * l;
|
||||
|
||||
if( DEBUG_LISTS )
|
||||
printf( "list > %s <\n", string );
|
||||
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 */
|
||||
/* 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
|
||||
{
|
||||
if ( freelist )
|
||||
{
|
||||
l = freelist;
|
||||
freestr( l->string );
|
||||
freelist = freelist->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = (LIST *)BJAM_MALLOC( sizeof( LIST ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* If first on chain, head points here. */
|
||||
/* If adding to chain, tack us on. */
|
||||
/* Tail must point to this new, last element. */
|
||||
/* 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;
|
||||
if ( !head ) head = l;
|
||||
else head->tail->next = l;
|
||||
head->tail = l;
|
||||
l->next = 0;
|
||||
|
||||
l->string = string;
|
||||
l->string = string;
|
||||
|
||||
return head;
|
||||
return head;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* list_copy() - copy a whole list of strings (nl) onto end of another (l)
|
||||
* list_copy() - copy a whole list of strings (nl) onto end of another (l).
|
||||
*/
|
||||
|
||||
LIST *
|
||||
list_copy(
|
||||
LIST *l,
|
||||
LIST *nl )
|
||||
LIST * list_copy( LIST * l, LIST * nl )
|
||||
{
|
||||
for( ; nl; nl = list_next( nl ) )
|
||||
l = list_new( l, copystr( nl->string ) );
|
||||
|
||||
return l;
|
||||
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_sublist() - copy a subset of a list of strings.
|
||||
*/
|
||||
|
||||
LIST *
|
||||
list_sublist(
|
||||
LIST *l,
|
||||
int start,
|
||||
int count )
|
||||
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 * 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 *
|
||||
list_sort(
|
||||
LIST *l)
|
||||
|
||||
static int str_ptr_compare( void const * va, void const * vb )
|
||||
{
|
||||
char * a = *( (char * *)va );
|
||||
char * b = *( (char * *)vb );
|
||||
return strcmp(a, b);
|
||||
}
|
||||
|
||||
LIST* first = 0;
|
||||
LIST* second = 0;
|
||||
LIST* merged = l;
|
||||
LIST* result;
|
||||
|
||||
if (!l)
|
||||
LIST * list_sort( LIST * l )
|
||||
{
|
||||
int len;
|
||||
int ii;
|
||||
char * * strings;
|
||||
LIST * listp;
|
||||
LIST * result = 0;
|
||||
|
||||
if ( !l )
|
||||
return L0;
|
||||
|
||||
for(;;) {
|
||||
|
||||
/* Split the list in two */
|
||||
LIST** dst = &first;
|
||||
LIST* src = merged;
|
||||
|
||||
for(;;) {
|
||||
|
||||
*dst = list_append(*dst, list_new(0, src->string));
|
||||
|
||||
if (!src->next)
|
||||
break;
|
||||
len = list_length( l );
|
||||
strings = (char * *)BJAM_MALLOC( len * sizeof(char*) );
|
||||
|
||||
if (strcmp(src->string, src->next->string) > 0)
|
||||
{
|
||||
if (dst == &first)
|
||||
dst = &second;
|
||||
else
|
||||
dst = &first;
|
||||
}
|
||||
|
||||
src = src->next;
|
||||
}
|
||||
|
||||
if (merged != l)
|
||||
list_free( merged );
|
||||
merged = 0;
|
||||
|
||||
if (second == 0) {
|
||||
result = first;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Merge lists 'first' and 'second' into 'merged' and free
|
||||
'first'/'second'. */
|
||||
{
|
||||
LIST* f = first;
|
||||
LIST* s = second;
|
||||
|
||||
while(f && s)
|
||||
{
|
||||
if (strcmp(f->string, s->string) < 0)
|
||||
{
|
||||
merged = list_append( merged, list_new(0, f->string ));
|
||||
f = f->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
merged = list_append( merged, list_new(0, s->string ));
|
||||
s = s->next;
|
||||
}
|
||||
}
|
||||
|
||||
merged = list_copy( merged, f );
|
||||
merged = list_copy( merged, s );
|
||||
list_free( first );
|
||||
list_free( second );
|
||||
first = 0;
|
||||
second = 0;
|
||||
}
|
||||
listp = l;
|
||||
for ( ii = 0; ii < len; ++ii )
|
||||
{
|
||||
strings[ ii ] = listp->string;
|
||||
listp = listp->next;
|
||||
}
|
||||
|
||||
qsort( strings, len, sizeof( char * ), str_ptr_compare );
|
||||
|
||||
for ( ii = 0; ii < len; ++ii )
|
||||
result = list_append( result, list_new( 0, strings[ ii ] ) );
|
||||
|
||||
BJAM_FREE( strings );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* list_free() - free a list of strings
|
||||
*/
|
||||
|
||||
void
|
||||
list_free( LIST *head )
|
||||
void list_free( LIST * head )
|
||||
{
|
||||
/* Just tack onto freelist. */
|
||||
|
||||
if( head )
|
||||
{
|
||||
head->tail->next = freelist;
|
||||
freelist = head;
|
||||
}
|
||||
/* Just tack onto freelist. */
|
||||
if ( head )
|
||||
{
|
||||
head->tail->next = freelist;
|
||||
freelist = head;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* list_pop_front() - remove the front element from a list of strings
|
||||
*/
|
||||
LIST * list_pop_front( LIST *l )
|
||||
|
||||
LIST * list_pop_front( LIST * l )
|
||||
{
|
||||
LIST * result = l->next;
|
||||
if( result )
|
||||
if ( result )
|
||||
{
|
||||
result->tail = l->tail;
|
||||
l->next = L0;
|
||||
@@ -244,126 +190,116 @@ LIST * list_pop_front( LIST *l )
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* list_print() - print a list of strings to stdout
|
||||
*/
|
||||
|
||||
void
|
||||
list_print( LIST *l )
|
||||
void list_print( LIST * l )
|
||||
{
|
||||
LIST *p = 0;
|
||||
for( ; l; p = l, l = list_next( l ) )
|
||||
if ( p )
|
||||
printf( "%s ", p->string );
|
||||
LIST * p = 0;
|
||||
for ( ; l; p = l, l = list_next( l ) )
|
||||
if ( p )
|
||||
printf( "%s", p->string );
|
||||
printf( "%s ", p->string );
|
||||
if ( p )
|
||||
printf( "%s", p->string );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* list_length() - return the number of items in the list
|
||||
*/
|
||||
|
||||
int
|
||||
list_length( LIST *l )
|
||||
int list_length( LIST * l )
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
for( ; l; l = list_next( l ), ++n )
|
||||
;
|
||||
|
||||
return n;
|
||||
int n = 0;
|
||||
for ( ; l; l = list_next( l ), ++n );
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
list_in(LIST* l, char* value)
|
||||
|
||||
int list_in( LIST * l, char * value )
|
||||
{
|
||||
for(; l; l = l->next)
|
||||
if (strcmp(l->string, value) == 0)
|
||||
for ( ; l; l = l->next )
|
||||
if ( strcmp( l->string, value ) == 0 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
LIST *
|
||||
list_unique( LIST *sorted_list)
|
||||
{
|
||||
LIST* result = 0;
|
||||
LIST* last_added = 0;
|
||||
|
||||
for(; sorted_list; sorted_list = sorted_list->next)
|
||||
LIST * list_unique( LIST * sorted_list )
|
||||
{
|
||||
LIST * result = 0;
|
||||
LIST * last_added = 0;
|
||||
|
||||
for ( ; sorted_list; sorted_list = sorted_list->next )
|
||||
{
|
||||
if (!last_added || strcmp(sorted_list->string, last_added->string) != 0)
|
||||
if ( !last_added || strcmp( sorted_list->string, last_added->string ) != 0 )
|
||||
{
|
||||
result = list_new(result, sorted_list->string);
|
||||
result = list_new( result, sorted_list->string );
|
||||
last_added = sorted_list;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lol_init() - initialize a LOL (list of lists)
|
||||
* lol_init() - initialize a LOL (list of lists).
|
||||
*/
|
||||
|
||||
void
|
||||
lol_init( LOL *lol )
|
||||
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
|
||||
* lol_add() - append a LIST onto an LOL.
|
||||
*/
|
||||
|
||||
void
|
||||
lol_free( LOL *lol )
|
||||
void lol_add( LOL * lol, LIST * l )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < lol->count; i++ )
|
||||
list_free( lol->list[i] );
|
||||
|
||||
lol->count = 0;
|
||||
if ( lol->count < LOL_MAX )
|
||||
lol->list[ lol->count++ ] = l;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lol_get() - return one of the LISTs in the LOL
|
||||
* lol_free() - free the LOL and its LISTs.
|
||||
*/
|
||||
|
||||
LIST *
|
||||
lol_get(
|
||||
LOL *lol,
|
||||
int i )
|
||||
void lol_free( LOL * lol )
|
||||
{
|
||||
return i < lol->count ? lol->list[i] : 0;
|
||||
int i;
|
||||
for ( i = 0; i < lol->count; ++i )
|
||||
list_free( lol->list[ i ] );
|
||||
lol->count = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lol_print() - debug print LISTS separated by ":"
|
||||
* lol_get() - return one of the LISTs in the LOL.
|
||||
*/
|
||||
|
||||
void
|
||||
lol_print( LOL *lol )
|
||||
LIST * lol_get( LOL * lol, int i )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < lol->count; i++ )
|
||||
{
|
||||
if( i )
|
||||
printf( " : " );
|
||||
list_print( lol->list[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 ] );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,24 @@
|
||||
*
|
||||
* Structures defined:
|
||||
*
|
||||
* LIST - list of strings
|
||||
* LOL - list of LISTs
|
||||
* 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
|
||||
* 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 ":"
|
||||
* 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()
|
||||
@@ -52,10 +52,10 @@
|
||||
typedef struct _list LIST;
|
||||
|
||||
struct _list {
|
||||
LIST *next;
|
||||
LIST *tail; /* only valid in head node */
|
||||
char *string; /* private copy */
|
||||
} ;
|
||||
LIST *next;
|
||||
LIST *tail; /* only valid in head node */
|
||||
char *string; /* private copy */
|
||||
};
|
||||
|
||||
/*
|
||||
* LOL - list of LISTs
|
||||
@@ -66,17 +66,17 @@ typedef struct _lol LOL;
|
||||
# define LOL_MAX 9
|
||||
|
||||
struct _lol {
|
||||
int count;
|
||||
LIST *list[ LOL_MAX ];
|
||||
} ;
|
||||
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 );
|
||||
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 );
|
||||
LIST * list_pop_front( LIST *l );
|
||||
LIST * list_sort( LIST *l);
|
||||
LIST * list_unique( LIST *sorted_list);
|
||||
@@ -86,11 +86,11 @@ int list_in(LIST* l, char* value);
|
||||
|
||||
# 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 );
|
||||
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 );
|
||||
void lol_build( LOL* lol, char** elements );
|
||||
|
||||
#endif
|
||||
|
||||
1307
src/engine/make.c
1307
src/engine/make.c
File diff suppressed because it is too large
Load Diff
@@ -14,16 +14,16 @@ int make( int n_targets, const char **targets, int anyhow );
|
||||
int make1( TARGET *t );
|
||||
|
||||
typedef struct {
|
||||
int temp;
|
||||
int updating;
|
||||
int cantfind;
|
||||
int cantmake;
|
||||
int targets;
|
||||
int made;
|
||||
int temp;
|
||||
int updating;
|
||||
int cantfind;
|
||||
int cantmake;
|
||||
int targets;
|
||||
int made;
|
||||
} COUNTS ;
|
||||
|
||||
|
||||
void make0( TARGET *t, TARGET *p, int depth,
|
||||
void make0( TARGET *t, TARGET *p, int depth,
|
||||
COUNTS *counts, int anyhow );
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ void make0( TARGET *t, TARGET *p, int depth,
|
||||
* Specifies that the target should be updated.
|
||||
*/
|
||||
void mark_target_for_updating(char *target);
|
||||
/*
|
||||
/*
|
||||
* Returns the list of all the target previously passed to 'mark_target_for_updating'.
|
||||
*/
|
||||
LIST *targets_to_update();
|
||||
|
||||
1572
src/engine/make1.c
1572
src/engine/make1.c
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
#define ATOMIC_UNCOLLECTABLE
|
||||
#define NO_EXECUTE_PERMISSION
|
||||
#define ALL_INTERIOR_POINTERS
|
||||
|
||||
|
||||
#define LARGE_CONFIG
|
||||
/*
|
||||
#define NO_SIGNALS
|
||||
@@ -25,11 +25,11 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef GC_DEBUG
|
||||
#define NO_DEBUGGING
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GLIBC__
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
|
||||
|
||||
#include "boehm_gc/reclaim.c"
|
||||
#include "boehm_gc/allchblk.c"
|
||||
#include "boehm_gc/misc.c"
|
||||
@@ -60,7 +60,7 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
#include "boehm_gc/gc_dlopen.c"
|
||||
#include "boehm_gc/backgraph.c"
|
||||
#include "boehm_gc/win32_threads.c"
|
||||
|
||||
|
||||
/* Needs to be last. */
|
||||
#include "boehm_gc/finalize.c"
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
#define bjam_calloc_raw_x(n,s) calloc(n,s)
|
||||
#define bjam_realloc_raw_x(p,s) realloc(p,s)
|
||||
#define bjam_free_raw_x(p) free(p)
|
||||
|
||||
|
||||
#ifndef BJAM_NEWSTR_NO_ALLOCATE
|
||||
#define BJAM_NEWSTR_NO_ALLOCATE
|
||||
#endif
|
||||
@@ -54,7 +54,7 @@ http://www.boost.org/LICENSE_1_0.txt)
|
||||
#define bjam_calloc_x(n,s) calloc(n,s)
|
||||
#define bjam_realloc_x(p,s) realloc(p,s)
|
||||
#define bjam_free_x(p) free(p)
|
||||
|
||||
|
||||
#ifndef BJAM_NEWSTR_NO_ALLOCATE
|
||||
#define BJAM_NEWSTR_NO_ALLOCATE
|
||||
#endif
|
||||
|
||||
@@ -17,115 +17,107 @@
|
||||
*
|
||||
* Results look like this:
|
||||
*
|
||||
* char *jambase[] = {
|
||||
* "...\n",
|
||||
* ...
|
||||
* 0 };
|
||||
* char *jambase[] = {
|
||||
* "...\n",
|
||||
* ...
|
||||
* 0 };
|
||||
*
|
||||
* Handles \'s and "'s specially; knows to delete blank and comment lines.
|
||||
*
|
||||
*/
|
||||
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main( int argc, char **argv, char **envp )
|
||||
|
||||
int main( int argc, char * * argv, char * * envp )
|
||||
{
|
||||
char buf[ 1024 ];
|
||||
FILE *fin;
|
||||
FILE *fout;
|
||||
char *p;
|
||||
int doDotC = 0;
|
||||
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 ( 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 ( !( fout = fopen( argv[1], "w" ) ) )
|
||||
{
|
||||
perror( argv[ 1 ] );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If the file ends in .c generate a C source file */
|
||||
/* If the file ends in .c generate a C source file. */
|
||||
if ( ( p = strrchr( argv[1], '.' ) ) && !strcmp( p, ".c" ) )
|
||||
doDotC++;
|
||||
|
||||
if( ( p = strrchr( argv[1], '.' ) ) && !strcmp( p, ".c" ) )
|
||||
doDotC++;
|
||||
/* Now process the files. */
|
||||
|
||||
/* Now process the files */
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
argc -= 2, argv += 2;
|
||||
if ( doDotC )
|
||||
{
|
||||
fprintf( fout, "/* Generated by mkjambase from Jambase */\n" );
|
||||
fprintf( fout, "char *jambase[] = {\n" );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
if( doDotC )
|
||||
{
|
||||
fprintf( fout, "/* %s */\n", *argv );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( fout, "### %s ###\n", *argv );
|
||||
}
|
||||
while ( fgets( buf, sizeof( buf ), fin ) )
|
||||
{
|
||||
if ( doDotC )
|
||||
{
|
||||
char * p = buf;
|
||||
|
||||
while( fgets( buf, sizeof( buf ), fin ) )
|
||||
{
|
||||
if( doDotC )
|
||||
{
|
||||
char *p = buf;
|
||||
/* Strip leading whitespace. */
|
||||
while ( ( *p == ' ' ) || ( *p == '\t' ) || ( *p == '\n' ) )
|
||||
++p;
|
||||
|
||||
/* Strip leading whitespace. */
|
||||
/* Drop comments and empty lines. */
|
||||
if ( ( *p == '#' ) || !*p )
|
||||
continue;
|
||||
|
||||
while( *p == ' ' || *p == '\t' || *p == '\n' )
|
||||
p++;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Drop comments and empty lines. */
|
||||
fprintf( fout, "\\n\",\n" );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( fout, "%s", buf );
|
||||
}
|
||||
}
|
||||
|
||||
if( *p == '#' || !*p )
|
||||
continue;
|
||||
fclose( fin );
|
||||
}
|
||||
|
||||
/* Copy */
|
||||
if ( doDotC )
|
||||
fprintf( fout, "0 };\n" );
|
||||
|
||||
putc( '"', fout );
|
||||
fclose( 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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
#include "strings.h"
|
||||
#include <assert.h>
|
||||
|
||||
static struct hash* module_hash = 0;
|
||||
static struct hash * module_hash = 0;
|
||||
|
||||
static char* new_module_str( module_t* m, char* suffix )
|
||||
|
||||
static char * new_module_str( module_t * m, char * suffix )
|
||||
{
|
||||
char* result;
|
||||
char * result;
|
||||
string s;
|
||||
string_copy( &s, m->name );
|
||||
string_append( &s, suffix );
|
||||
@@ -29,26 +30,28 @@ static char* new_module_str( module_t* m, char* suffix )
|
||||
return result;
|
||||
}
|
||||
|
||||
module_t* bindmodule( char* name )
|
||||
{
|
||||
PROFILE_ENTER(BINDMODULE);
|
||||
|
||||
string s;
|
||||
module_t m_, *m = &m_;
|
||||
|
||||
if( !module_hash )
|
||||
module_t * bindmodule( char * name )
|
||||
{
|
||||
PROFILE_ENTER( BINDMODULE );
|
||||
|
||||
string s;
|
||||
module_t m_;
|
||||
module_t * m = &m_;
|
||||
|
||||
if ( !module_hash )
|
||||
module_hash = hashinit( sizeof( module_t ), "modules" );
|
||||
|
||||
string_new( &s );
|
||||
if (name)
|
||||
if ( name )
|
||||
{
|
||||
string_append( &s, name );
|
||||
string_push_back( &s, '.' );
|
||||
}
|
||||
|
||||
|
||||
m->name = s.value;
|
||||
|
||||
if ( hashenter( module_hash, (HASHDATA **)&m ) )
|
||||
|
||||
if ( hashenter( module_hash, (HASHDATA * *)&m ) )
|
||||
{
|
||||
m->name = newstr( m->name );
|
||||
m->variables = 0;
|
||||
@@ -60,35 +63,38 @@ module_t* bindmodule( char* name )
|
||||
}
|
||||
string_free( &s );
|
||||
|
||||
PROFILE_EXIT(BINDMODULE);
|
||||
PROFILE_EXIT( BINDMODULE );
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
* demand_rules() - Get the module's "rules" hash on demand
|
||||
* demand_rules() - Get the module's "rules" hash on demand.
|
||||
*/
|
||||
struct hash* demand_rules( module_t* m )
|
||||
struct hash * demand_rules( module_t * m )
|
||||
{
|
||||
if ( !m->rules )
|
||||
m->rules = hashinit( sizeof( RULE ), new_module_str( m, "rules" ) );
|
||||
return m->rules;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* delete_module() - wipe out the module's rules and variables
|
||||
* delete_module() - wipe out the module's rules and variables.
|
||||
*/
|
||||
static void delete_rule_( void* xrule, void* data )
|
||||
|
||||
static void delete_rule_( void * xrule, void * data )
|
||||
{
|
||||
rule_free( (RULE*)xrule );
|
||||
rule_free( (RULE *)xrule );
|
||||
}
|
||||
|
||||
void delete_module( module_t* m )
|
||||
|
||||
void delete_module( module_t * m )
|
||||
{
|
||||
/* clear out all the rules */
|
||||
/* Clear out all the rules. */
|
||||
if ( m->rules )
|
||||
{
|
||||
hashenumerate( m->rules, delete_rule_, (void*)0 );
|
||||
hashenumerate( m->rules, delete_rule_, (void *)0 );
|
||||
hashdone( m->rules );
|
||||
m->rules = 0;
|
||||
}
|
||||
@@ -102,59 +108,61 @@ void delete_module( module_t* m )
|
||||
}
|
||||
}
|
||||
|
||||
module_t* root_module()
|
||||
|
||||
module_t * root_module()
|
||||
{
|
||||
static module_t* root = 0;
|
||||
static module_t * root = 0;
|
||||
if ( !root )
|
||||
root = bindmodule(0);
|
||||
root = bindmodule( 0 );
|
||||
return root;
|
||||
}
|
||||
|
||||
void enter_module( module_t* m )
|
||||
void enter_module( module_t * m )
|
||||
{
|
||||
var_hash_swap( &m->variables );
|
||||
}
|
||||
|
||||
void exit_module( module_t* m )
|
||||
|
||||
void exit_module( module_t * m )
|
||||
{
|
||||
var_hash_swap( &m->variables );
|
||||
}
|
||||
|
||||
void import_module(LIST* module_names, module_t* target_module)
|
||||
|
||||
void import_module( LIST * module_names, module_t * target_module )
|
||||
{
|
||||
PROFILE_ENTER(IMPORT_MODULE);
|
||||
|
||||
struct hash* h;
|
||||
|
||||
if (!target_module->imported_modules)
|
||||
target_module->imported_modules = hashinit( sizeof(char*), "imported");
|
||||
PROFILE_ENTER( IMPORT_MODULE );
|
||||
|
||||
struct hash * h;
|
||||
|
||||
if ( !target_module->imported_modules )
|
||||
target_module->imported_modules = hashinit( sizeof( char * ), "imported" );
|
||||
h = target_module->imported_modules;
|
||||
|
||||
for(;module_names; module_names = module_names->next) {
|
||||
|
||||
char* s = module_names->string;
|
||||
char** ss = &s;
|
||||
|
||||
hashenter(h, (HASHDATA**)&ss);
|
||||
for ( ; module_names; module_names = module_names->next )
|
||||
{
|
||||
char * s = module_names->string;
|
||||
char * * ss = &s;
|
||||
hashenter( h, (HASHDATA * *)&ss );
|
||||
}
|
||||
|
||||
PROFILE_EXIT(IMPORT_MODULE);
|
||||
|
||||
PROFILE_EXIT( IMPORT_MODULE );
|
||||
}
|
||||
|
||||
static void add_module_name( void* r_, void* result_ )
|
||||
|
||||
static void add_module_name( void * r_, void * result_ )
|
||||
{
|
||||
char** r = (char**)r_;
|
||||
LIST** result = (LIST**)result_;
|
||||
char * * r = (char * *)r_;
|
||||
LIST * * result = (LIST * *)result_;
|
||||
|
||||
*result = list_new( *result, copystr( *r ) );
|
||||
}
|
||||
|
||||
LIST* imported_modules(module_t* module)
|
||||
{
|
||||
LIST *result = L0;
|
||||
|
||||
LIST * imported_modules( module_t * module )
|
||||
{
|
||||
LIST * result = L0;
|
||||
if ( module->imported_modules )
|
||||
hashenumerate( module->imported_modules, add_module_name, &result );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ LIST *order( PARSE *parse, FRAME *frame )
|
||||
LIST* arg = lol_get( frame->args, 0 );
|
||||
LIST* tmp;
|
||||
LIST* result = 0;
|
||||
int src, dst;
|
||||
int src;
|
||||
|
||||
/* We need to create a graph of order dependencies between
|
||||
the passed objects. We assume that there are no duplicates
|
||||
|
||||
@@ -15,12 +15,12 @@ LIST* get_grist(char* f)
|
||||
char* end = strchr(f, '>');
|
||||
string s[1];
|
||||
LIST* result;
|
||||
|
||||
|
||||
string_new(s);
|
||||
|
||||
string_append_range(s, f, end+1);
|
||||
result = list_new(0, newstr(s->value));
|
||||
|
||||
|
||||
string_free(s);
|
||||
return result;
|
||||
}
|
||||
@@ -28,24 +28,26 @@ LIST* get_grist(char* f)
|
||||
/*
|
||||
rule create ( raw-properties * )
|
||||
{
|
||||
raw-properties = [ sequence.unique
|
||||
raw-properties = [ sequence.unique
|
||||
[ sequence.insertion-sort $(raw-properties) ] ] ;
|
||||
|
||||
|
||||
local key = $(raw-properties:J=-:E=) ;
|
||||
|
||||
if ! $(.ps.$(key))
|
||||
|
||||
if ! $(.ps.$(key))
|
||||
{
|
||||
.ps.$(key) = [ new property-set $(raw-properties) ] ;
|
||||
}
|
||||
return $(.ps.$(key)) ;
|
||||
return $(.ps.$(key)) ;
|
||||
}
|
||||
*/
|
||||
|
||||
LIST *property_set_create( PARSE *parse, FRAME *frame )
|
||||
{
|
||||
LIST* properties = lol_get( frame->args, 0 );
|
||||
LIST* properties = lol_get( frame->args, 0 );
|
||||
LIST* sorted = 0;
|
||||
#if 0
|
||||
LIST* order_sensitive = 0;
|
||||
#endif
|
||||
LIST* unique;
|
||||
LIST* tmp;
|
||||
LIST* val;
|
||||
@@ -63,7 +65,7 @@ LIST *property_set_create( PARSE *parse, FRAME *frame )
|
||||
}
|
||||
list_free(att);
|
||||
}
|
||||
|
||||
|
||||
sorted = list_sort(sorted);
|
||||
sorted = list_append(sorted, order_sensitive);
|
||||
unique = list_unique(sorted);
|
||||
@@ -73,24 +75,24 @@ LIST *property_set_create( PARSE *parse, FRAME *frame )
|
||||
|
||||
string_new(var);
|
||||
string_append(var, ".ps.");
|
||||
|
||||
|
||||
for(tmp = unique; tmp; tmp = tmp->next) {
|
||||
string_append(var, tmp->string);
|
||||
string_push_back(var, '-');
|
||||
}
|
||||
val = var_get(var->value);
|
||||
if (val == 0)
|
||||
{
|
||||
val = call_rule("new", frame,
|
||||
list_append(list_new(0, "property-set"), unique), 0);
|
||||
|
||||
if (val == 0)
|
||||
{
|
||||
val = call_rule("new", frame,
|
||||
list_append(list_new(0, "property-set"), unique), 0);
|
||||
|
||||
var_set(newstr(var->value), list_copy(0, val), VAR_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = list_copy(0, val);
|
||||
}
|
||||
|
||||
|
||||
string_free(var);
|
||||
/* The 'unique' variable is freed in 'call_rule'. */
|
||||
list_free(sorted);
|
||||
@@ -105,5 +107,4 @@ void init_property_set()
|
||||
char* args[] = { "raw-properties", "*", 0 };
|
||||
declare_native_rule("property-set", "create", args, property_set_create, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,15 +9,14 @@
|
||||
# define C0 (char *)0
|
||||
|
||||
|
||||
void declare_native_rule(char* module, char* rule, char** args,
|
||||
void declare_native_rule(char* module, char* rule, char** args,
|
||||
LIST*(*f)(PARSE*, FRAME*), int version)
|
||||
|
||||
{
|
||||
module_t* m = bindmodule(module);
|
||||
if (m->native_rules == 0) {
|
||||
m->native_rules = hashinit( sizeof( native_rule_t ), "native rules");
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
native_rule_t n, *np = &n;
|
||||
n.name = rule;
|
||||
@@ -25,14 +24,13 @@ void declare_native_rule(char* module, char* rule, char** args,
|
||||
{
|
||||
n.arguments = args_new();
|
||||
lol_build( n.arguments->data, args );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
n.arguments = 0;
|
||||
}
|
||||
n.procedure = parse_make( f, P0, P0, P0, C0, C0, 0 );
|
||||
n.procedure = parse_make( f, P0, P0, P0, C0, C0, 0 );
|
||||
n.version = version;
|
||||
hashenter(m->native_rules, (HASHDATA**)&np);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@ struct native_rule_t
|
||||
};
|
||||
|
||||
/* MSVC debugger gets confused unless this is provided */
|
||||
typedef struct native_rule_t native_rule_t ;
|
||||
typedef struct native_rule_t native_rule_t ;
|
||||
|
||||
void declare_native_rule(char* module, char* rule, char** args,
|
||||
void declare_native_rule(char* module, char* rule, char** args,
|
||||
LIST*(*f)(PARSE*, FRAME*), int version);
|
||||
|
||||
|
||||
|
||||
@@ -22,71 +22,74 @@
|
||||
* newstr() - return a dynamically allocated 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
|
||||
* str_done() - 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
|
||||
* 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;
|
||||
typedef char * STRING;
|
||||
|
||||
static struct hash * strhash = 0;
|
||||
static int strtotal = 0;
|
||||
static int strcount_in = 0;
|
||||
static int strcount_out = 0;
|
||||
|
||||
static struct hash *strhash = 0;
|
||||
static int strtotal = 0;
|
||||
static int strcount_in = 0;
|
||||
static int strcount_out = 0;
|
||||
|
||||
/*
|
||||
* Immortal string allocator implementation speeds string allocation
|
||||
* and cuts down on internal fragmentation
|
||||
* Immortal string allocator implementation speeds string allocation and cuts
|
||||
* down on internal fragmentation.
|
||||
*/
|
||||
|
||||
# define STRING_BLOCK 4096
|
||||
typedef struct strblock
|
||||
{
|
||||
struct strblock* next;
|
||||
char data[STRING_BLOCK];
|
||||
struct strblock * next;
|
||||
char data[STRING_BLOCK];
|
||||
} strblock;
|
||||
|
||||
static strblock* strblock_chain = 0;
|
||||
static strblock * strblock_chain = 0;
|
||||
|
||||
/* Storage remaining in the current strblock */
|
||||
static char* storage_start = 0;
|
||||
static char* storage_finish = 0;
|
||||
static char * storage_start = 0;
|
||||
static char * storage_finish = 0;
|
||||
|
||||
|
||||
/*
|
||||
* allocate() - Allocate n bytes of immortal string storage
|
||||
* allocate() - Allocate n bytes of immortal string storage.
|
||||
*/
|
||||
static char* allocate(size_t n)
|
||||
|
||||
static char * allocate( size_t const n )
|
||||
{
|
||||
#ifdef BJAM_NEWSTR_NO_ALLOCATE
|
||||
#ifdef BJAM_NEWSTR_NO_ALLOCATE
|
||||
return (char*)BJAM_MALLOC_ATOMIC(n);
|
||||
#else
|
||||
/* See if we can grab storage from an existing block */
|
||||
#else
|
||||
/* See if we can grab storage from an existing block. */
|
||||
size_t remaining = storage_finish - storage_start;
|
||||
if ( remaining >= n )
|
||||
{
|
||||
char* result = storage_start;
|
||||
char * result = storage_start;
|
||||
storage_start += n;
|
||||
return result;
|
||||
}
|
||||
else /* Must allocate a new block */
|
||||
else /* Must allocate a new block. */
|
||||
{
|
||||
strblock* new_block;
|
||||
strblock * new_block;
|
||||
size_t nalloc = n;
|
||||
if ( nalloc < STRING_BLOCK )
|
||||
nalloc = STRING_BLOCK;
|
||||
|
||||
/* allocate a new block and link into the chain */
|
||||
new_block = (strblock*)BJAM_MALLOC( offsetof( strblock, data[0] ) + nalloc * sizeof(new_block->data[0]) );
|
||||
/* Allocate a new block and link into the chain. */
|
||||
new_block = (strblock *)BJAM_MALLOC( offsetof( strblock, data[0] ) + nalloc * sizeof( new_block->data[0] ) );
|
||||
if ( new_block == 0 )
|
||||
return 0;
|
||||
new_block->next = strblock_chain;
|
||||
strblock_chain = new_block;
|
||||
|
||||
/* Take future allocations out of the larger remaining space */
|
||||
/* Take future allocations out of the larger remaining space. */
|
||||
if ( remaining < nalloc - n )
|
||||
{
|
||||
storage_start = new_block->data + n;
|
||||
@@ -94,77 +97,78 @@ static char* allocate(size_t n)
|
||||
}
|
||||
return new_block->data;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* newstr() - return a dynamically allocated copy of a string
|
||||
* newstr() - return a dynamically allocated copy of a string.
|
||||
*/
|
||||
|
||||
char *
|
||||
newstr( char *string )
|
||||
char * newstr( char * string )
|
||||
{
|
||||
STRING str, *s = &str;
|
||||
STRING str;
|
||||
STRING * s = &str;
|
||||
|
||||
if( !strhash )
|
||||
strhash = hashinit( sizeof( STRING ), "strings" );
|
||||
if ( !strhash )
|
||||
strhash = hashinit( sizeof( STRING ), "strings" );
|
||||
|
||||
*s = string;
|
||||
*s = string;
|
||||
|
||||
if( hashenter( strhash, (HASHDATA **)&s ) )
|
||||
{
|
||||
int l = strlen( string );
|
||||
char *m = (char *)allocate( l + 1 );
|
||||
if ( hashenter( strhash, (HASHDATA **)&s ) )
|
||||
{
|
||||
int l = strlen( string );
|
||||
char * m = (char *)allocate( l + 1 );
|
||||
|
||||
strtotal += l + 1;
|
||||
memcpy( m, string, l + 1 );
|
||||
*s = m;
|
||||
}
|
||||
strtotal += l + 1;
|
||||
memcpy( m, string, l + 1 );
|
||||
*s = m;
|
||||
}
|
||||
|
||||
strcount_in += 1;
|
||||
return *s;
|
||||
return *s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* copystr() - return a copy of a string previously returned by newstr()
|
||||
*/
|
||||
|
||||
char *
|
||||
copystr( char *s )
|
||||
char * copystr( char * s )
|
||||
{
|
||||
strcount_in += 1;
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* freestr() - free a string returned by newstr() or copystr()
|
||||
*/
|
||||
|
||||
void
|
||||
freestr( char *s )
|
||||
void freestr( char * s )
|
||||
{
|
||||
strcount_out += 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* donestr() - free string tables
|
||||
* str_done() - free string tables.
|
||||
*/
|
||||
|
||||
void
|
||||
donestr()
|
||||
void str_done()
|
||||
{
|
||||
/* Reclaim string blocks */
|
||||
/* Reclaim string blocks. */
|
||||
while ( strblock_chain != 0 )
|
||||
{
|
||||
strblock* n = strblock_chain->next;
|
||||
strblock * n = strblock_chain->next;
|
||||
BJAM_FREE(strblock_chain);
|
||||
strblock_chain = n;
|
||||
}
|
||||
|
||||
|
||||
hashdone( strhash );
|
||||
|
||||
if( DEBUG_MEM )
|
||||
|
||||
if ( DEBUG_MEM )
|
||||
printf( "%dK in strings\n", strtotal / 1024 );
|
||||
|
||||
|
||||
/* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* newstr.h - string manipulation routines
|
||||
*/
|
||||
|
||||
char *newstr( char *string );
|
||||
char *copystr( char *s );
|
||||
void freestr( char *s );
|
||||
void donestr();
|
||||
char * copystr ( char * );
|
||||
void freestr ( char * );
|
||||
char * newstr ( char * );
|
||||
void str_done();
|
||||
|
||||
@@ -12,92 +12,83 @@
|
||||
*
|
||||
* {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."
|
||||
* 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 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++ )
|
||||
for ( i = 0; i < argc; ++i )
|
||||
{
|
||||
char *arg;
|
||||
char *arg;
|
||||
|
||||
if( argv[i][0] != '-' || ( argv[i][1] != '-' && !isalpha( argv[i][1] ) ) )
|
||||
continue;
|
||||
if ( ( argv[ i ][ 0 ] != '-' ) ||
|
||||
( ( argv[ i ][ 1 ] != '-' ) && !isalpha( argv[ i ][ 1 ] ) ) )
|
||||
continue;
|
||||
|
||||
if( !optc-- )
|
||||
{
|
||||
printf( "too many options (%d max)\n", N_OPTS );
|
||||
return -1;
|
||||
}
|
||||
if ( !optc-- )
|
||||
{
|
||||
printf( "too many options (%d max)\n", N_OPTS );
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( arg = &argv[i][1]; *arg; arg++ )
|
||||
{
|
||||
char *f;
|
||||
for ( arg = &argv[ i ][ 1 ]; *arg; ++arg )
|
||||
{
|
||||
char * f;
|
||||
|
||||
for( f = opts; *f; f++ )
|
||||
if( *f == *arg )
|
||||
break;
|
||||
for ( f = opts; *f; ++f )
|
||||
if ( *f == *arg )
|
||||
break;
|
||||
|
||||
if( !*f )
|
||||
{
|
||||
printf( "Invalid option: -%c\n", *arg );
|
||||
return -1;
|
||||
}
|
||||
if ( !*f )
|
||||
{
|
||||
printf( "Invalid option: -%c\n", *arg );
|
||||
return -1;
|
||||
}
|
||||
|
||||
optv->flag = *f;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
* Name: getoptval() - find an option given its character.
|
||||
*/
|
||||
|
||||
char *
|
||||
getoptval(
|
||||
option *optv,
|
||||
char opt,
|
||||
int subopt )
|
||||
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;
|
||||
int i;
|
||||
for ( i = 0; i < N_OPTS; ++i, ++optv )
|
||||
if ( ( optv->flag == opt ) && !subopt-- )
|
||||
return optv->val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
typedef struct option
|
||||
{
|
||||
char flag; /* filled in by getoption() */
|
||||
char *val; /* set to random address if true */
|
||||
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 );
|
||||
int getoptions( int argc, char **argv, char *opts, option *optv );
|
||||
char * getoptval( option *optv, char opt, int subopt );
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
Copyright 2007 Rene Rivera
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -12,50 +12,53 @@
|
||||
#define bjam_out (stdout)
|
||||
#define bjam_err (stderr)
|
||||
|
||||
static void out_(
|
||||
const char * data,
|
||||
FILE * io
|
||||
)
|
||||
static void out_
|
||||
(
|
||||
char const * data,
|
||||
FILE * io
|
||||
)
|
||||
{
|
||||
while ( *data )
|
||||
{
|
||||
size_t len = strcspn(data,"\r");
|
||||
fwrite(data,len,1,io);
|
||||
data += len;
|
||||
data += fwrite(data,1,len,io);
|
||||
if ( *data == '\r' ) ++data;
|
||||
}
|
||||
}
|
||||
|
||||
void out_action(
|
||||
const char * action,
|
||||
const char * target,
|
||||
const char * command,
|
||||
const char * out_data,
|
||||
const char * err_data,
|
||||
int exit_reason
|
||||
)
|
||||
|
||||
void out_action
|
||||
(
|
||||
char const * action,
|
||||
char const * target,
|
||||
char const * command,
|
||||
char const * out_data,
|
||||
char const * err_data,
|
||||
int exit_reason
|
||||
)
|
||||
{
|
||||
/* print out the action+target line, if the action is quite
|
||||
the action should be null. */
|
||||
/* Print out the action+target line, if the action is quite the action
|
||||
* should be null.
|
||||
*/
|
||||
if ( action )
|
||||
{
|
||||
fprintf(bjam_out,"%s %s\n",action,target);
|
||||
}
|
||||
|
||||
/* print out the command executed if given -d+2 */
|
||||
if ( DEBUG_EXEC )
|
||||
{
|
||||
fputs(command,bjam_out);
|
||||
fputc('\n',bjam_out);
|
||||
}
|
||||
|
||||
/* print out the command executed to the command stream */
|
||||
if ( globs.cmdout )
|
||||
{
|
||||
fputs(command,globs.cmdout);
|
||||
fprintf( bjam_out, "%s %s\n", action, target );
|
||||
}
|
||||
|
||||
switch (exit_reason)
|
||||
/* Print out the command executed if given -d+2. */
|
||||
if ( DEBUG_EXEC )
|
||||
{
|
||||
fputs( command, bjam_out );
|
||||
fputc( '\n', bjam_out );
|
||||
}
|
||||
|
||||
/* Print out the command executed to the command stream. */
|
||||
if ( globs.cmdout )
|
||||
{
|
||||
fputs( command, globs.cmdout );
|
||||
}
|
||||
|
||||
switch ( exit_reason )
|
||||
{
|
||||
case EXIT_OK:
|
||||
break;
|
||||
@@ -63,59 +66,60 @@ void out_action(
|
||||
break;
|
||||
case EXIT_TIMEOUT:
|
||||
{
|
||||
/* process expired, make user aware with explicit message */
|
||||
/* Process expired, make user aware with explicit message. */
|
||||
if ( action )
|
||||
{
|
||||
/* but only output for non-quietly actions */
|
||||
fprintf(bjam_out, "%d second time limit exceeded\n", globs.timeout);
|
||||
/* But only output for non-quietly actions. */
|
||||
fprintf( bjam_out, "%ld second time limit exceeded\n", globs.timeout );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* print out the command output, if requested */
|
||||
|
||||
/* Print out the command output, if requested. */
|
||||
if ( action )
|
||||
{
|
||||
/* but only output for non-quietly actions */
|
||||
if (0 != out_data &&
|
||||
( globs.pipe_action & 1 /* STDOUT_FILENO */ ||
|
||||
globs.pipe_action == 0))
|
||||
/* But only output for non-quietly actions. */
|
||||
if ( ( 0 != out_data ) &&
|
||||
( ( globs.pipe_action & 1 /* STDOUT_FILENO */ ) ||
|
||||
( globs.pipe_action == 0 ) ) )
|
||||
{
|
||||
out_(out_data,bjam_out);
|
||||
out_( out_data, bjam_out );
|
||||
}
|
||||
if (0 != err_data &&
|
||||
globs.pipe_action & 2 /* STDERR_FILENO */)
|
||||
if ( ( 0 != err_data ) &&
|
||||
( globs.pipe_action & 2 /* STDERR_FILENO */ ) )
|
||||
{
|
||||
out_(err_data,bjam_err);
|
||||
out_( err_data, bjam_err );
|
||||
}
|
||||
}
|
||||
|
||||
fflush(bjam_out);
|
||||
fflush(bjam_err);
|
||||
fflush(globs.cmdout);
|
||||
|
||||
fflush( bjam_out );
|
||||
fflush( bjam_err );
|
||||
fflush( globs.cmdout );
|
||||
}
|
||||
|
||||
|
||||
char * outf_int( int value )
|
||||
{
|
||||
char buffer[50];
|
||||
sprintf(buffer, "%i", value);
|
||||
return newstr(buffer);
|
||||
sprintf( buffer, "%i", value );
|
||||
return newstr( buffer );
|
||||
}
|
||||
|
||||
|
||||
char * outf_double( double value )
|
||||
{
|
||||
char buffer[50];
|
||||
sprintf(buffer, "%f", value);
|
||||
return newstr(buffer);
|
||||
sprintf( buffer, "%f", value );
|
||||
return newstr( buffer );
|
||||
}
|
||||
|
||||
|
||||
char * outf_time( time_t value )
|
||||
{
|
||||
char buffer[50];
|
||||
strftime(buffer,49,"%Y-%m-%d %H:%M:%SZ",gmtime(&value));
|
||||
return newstr(buffer);
|
||||
strftime( buffer, 49, "%Y-%m-%d %H:%M:%SZ", gmtime( &value ) );
|
||||
return newstr( buffer );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
Copyright 2007 Rene Rivera
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -10,128 +10,123 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "parse.h"
|
||||
# include "scan.h"
|
||||
# include "newstr.h"
|
||||
# include "modules.h"
|
||||
# include "frames.h"
|
||||
#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.
|
||||
* as per Matt Armstrong.
|
||||
* 09/11/00 (seiwald) - structure reworked to reflect that (*func)()
|
||||
* returns a LIST *.
|
||||
* returns a LIST *.
|
||||
*/
|
||||
|
||||
static PARSE *yypsave;
|
||||
static PARSE * yypsave;
|
||||
|
||||
void
|
||||
parse_file( char *f, FRAME* frame )
|
||||
void parse_file( char * f, FRAME * frame )
|
||||
{
|
||||
/* Suspend scan of current file */
|
||||
/* and push this new file in the stream */
|
||||
/* Suspend scan of current file and push this new file in the stream. */
|
||||
yyfparse( f );
|
||||
|
||||
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).
|
||||
*/
|
||||
|
||||
/* 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;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
PARSE *p;
|
||||
/* Filled by yyparse() calling parse_save(). */
|
||||
yypsave = 0;
|
||||
|
||||
/* Filled by yyparse() calling parse_save() */
|
||||
/* If parse error or empty parse, outta here. */
|
||||
if ( yyparse() || !( p = yypsave ) )
|
||||
break;
|
||||
|
||||
yypsave = 0;
|
||||
|
||||
/* If parse error or empty parse, outta here */
|
||||
|
||||
if( yyparse() || !( p = yypsave ) )
|
||||
break;
|
||||
|
||||
/* Run the parse tree. */
|
||||
|
||||
parse_evaluate( p, frame );
|
||||
parse_free( p );
|
||||
}
|
||||
/* Run the parse tree. */
|
||||
parse_evaluate( p, frame );
|
||||
parse_free( p );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse_save( PARSE *p )
|
||||
|
||||
void parse_save( PARSE * p )
|
||||
{
|
||||
yypsave = 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 * parse_make(
|
||||
LIST * (* func)( PARSE *, FRAME * ),
|
||||
PARSE * left,
|
||||
PARSE * right,
|
||||
PARSE * third,
|
||||
char * string,
|
||||
char * string1,
|
||||
int num )
|
||||
{
|
||||
PARSE *p = (PARSE *)BJAM_MALLOC( sizeof( PARSE ) );
|
||||
PARSE * p = (PARSE *)BJAM_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->rulename = 0;
|
||||
|
||||
if ( left )
|
||||
{
|
||||
p->file = left->file;
|
||||
p->line = left->line;
|
||||
}
|
||||
else
|
||||
{
|
||||
yyinput_stream( &p->file, &p->line );
|
||||
}
|
||||
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->rulename = 0;
|
||||
|
||||
return p;
|
||||
if ( left )
|
||||
{
|
||||
p->file = left->file;
|
||||
p->line = left->line;
|
||||
}
|
||||
else
|
||||
{
|
||||
yyinput_stream( &p->file, &p->line );
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
parse_refer( PARSE *p )
|
||||
|
||||
void parse_refer( PARSE * p )
|
||||
{
|
||||
++p->refs;
|
||||
++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 );
|
||||
|
||||
BJAM_FREE( (char *)p );
|
||||
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 );
|
||||
|
||||
BJAM_FREE( (char *)p );
|
||||
}
|
||||
|
||||
LIST* parse_evaluate( PARSE *p, FRAME* frame )
|
||||
|
||||
LIST * parse_evaluate( PARSE * p, FRAME * frame )
|
||||
{
|
||||
frame->procedure = p;
|
||||
return (*p->func)(p, frame);
|
||||
return (*p->func)( p, frame );
|
||||
}
|
||||
|
||||
@@ -4,56 +4,56 @@
|
||||
* This file is part of Jam - see jam.c for Copyright information.
|
||||
*/
|
||||
|
||||
/* This file is ALSO:
|
||||
* Copyright 2001-2004 David Abrahams.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
/* This file is ALSO:
|
||||
* Copyright 2001-2004 David Abrahams.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
#ifndef PARSE_DWA20011020_H
|
||||
# define PARSE_DWA20011020_H
|
||||
# include "frames.h"
|
||||
# include "modules.h"
|
||||
# include "lists.h"
|
||||
#define PARSE_DWA20011020_H
|
||||
|
||||
#include "frames.h"
|
||||
#include "modules.h"
|
||||
#include "lists.h"
|
||||
|
||||
/*
|
||||
* parse.h - make and destroy parse trees as driven by the parser
|
||||
* parse.h - make and destroy parse trees as driven by the parser.
|
||||
*/
|
||||
|
||||
/*
|
||||
* parse tree node
|
||||
* Parse tree node.
|
||||
*/
|
||||
|
||||
struct _PARSE {
|
||||
LIST *(*func)( PARSE *p, FRAME *frame );
|
||||
PARSE *left;
|
||||
PARSE *right;
|
||||
PARSE *third;
|
||||
char *string;
|
||||
char *string1;
|
||||
LIST * (* func)( PARSE *, FRAME * );
|
||||
PARSE * left;
|
||||
PARSE * right;
|
||||
PARSE * third;
|
||||
char * string;
|
||||
char * string1;
|
||||
int num;
|
||||
int refs;
|
||||
/* module* module; */
|
||||
char* rulename;
|
||||
char* file;
|
||||
/* module * module; */
|
||||
char * rulename;
|
||||
char * file;
|
||||
int line;
|
||||
} ;
|
||||
};
|
||||
|
||||
void parse_file( char *f, FRAME* frame );
|
||||
void parse_save( PARSE *p );
|
||||
void parse_file( char *, FRAME * );
|
||||
void parse_save( PARSE * );
|
||||
|
||||
PARSE * parse_make(
|
||||
LIST *(*func)( PARSE *p, FRAME* frame ),
|
||||
PARSE *left,
|
||||
PARSE *right,
|
||||
PARSE *third,
|
||||
char *string,
|
||||
char *string1,
|
||||
int num );
|
||||
PARSE * parse_make(
|
||||
LIST * (* func)( PARSE *, FRAME * ),
|
||||
PARSE * left,
|
||||
PARSE * right,
|
||||
PARSE * third,
|
||||
char * string,
|
||||
char * string1,
|
||||
int num );
|
||||
|
||||
void parse_refer( PARSE *p );
|
||||
void parse_free( PARSE *p );
|
||||
LIST* parse_evaluate( PARSE *p, FRAME* frame );
|
||||
void parse_refer ( PARSE * );
|
||||
void parse_free ( PARSE * );
|
||||
LIST * parse_evaluate( PARSE *, FRAME * );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
#define VERSION_MAJOR 3
|
||||
#define VERSION_MINOR 1
|
||||
#define VERSION_PATCH 16
|
||||
#define VERSION_PATCH 17
|
||||
#define VERSION_MAJOR_SYM "03"
|
||||
#define VERSION_MINOR_SYM "1"
|
||||
#define VERSION_PATCH_SYM "16"
|
||||
#define VERSION "3.1.16"
|
||||
#define VERSION_PATCH_SYM "17"
|
||||
#define VERSION "3.1.17"
|
||||
#define JAMVERSYM "JAMVERSION=3.1"
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* path_parse() - split a file name into dir/base/suffix/member
|
||||
* path_build() - build a filename given dir/base/suffix/member
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
* path_parse() - split a file name into dir/base/suffix/member
|
||||
* path_build() - build a filename given dir/base/suffix/member
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
*
|
||||
* File_parse() and path_build() just manipuate a string and a structure;
|
||||
* they do not make system calls.
|
||||
@@ -41,10 +41,10 @@
|
||||
* 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.
|
||||
* don't include the archive member name.
|
||||
* 01/10/01 (seiwald) - path_parse now strips the trailing : from the
|
||||
* directory name, unless the directory name is all
|
||||
* :'s, so that $(d:P) works.
|
||||
* directory name, unless the directory name is all
|
||||
* :'s, so that $(d:P) works.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -52,132 +52,127 @@
|
||||
*/
|
||||
|
||||
void
|
||||
path_parse(
|
||||
char *file,
|
||||
PATHNAME *f )
|
||||
path_parse(
|
||||
char *file,
|
||||
PATHNAME *f )
|
||||
{
|
||||
char *p, *q;
|
||||
char *end;
|
||||
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
char *p, *q;
|
||||
char *end;
|
||||
|
||||
/* Look for <grist> */
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
|
||||
if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
/* Look for <grist> */
|
||||
|
||||
/* Look for dir: */
|
||||
if ( file[0] == '<' && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
if( p = strrchr( file, DELIM ) )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p - file;
|
||||
file = p + 1;
|
||||
/* Look for dir: */
|
||||
|
||||
/* All :'s? Include last : as part of directory name */
|
||||
if ( p = strrchr( file, DELIM ) )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p - file;
|
||||
file = p + 1;
|
||||
|
||||
while( p > f->f_dir.ptr && *--p == DELIM )
|
||||
;
|
||||
|
||||
if( p == f->f_dir.ptr )
|
||||
f->f_dir.len++;
|
||||
}
|
||||
/* All :'s? Include last : as part of directory name */
|
||||
|
||||
end = file + strlen( file );
|
||||
while ( ( p > f->f_dir.ptr ) && ( *--p == DELIM ) );
|
||||
|
||||
/* Look for (member) */
|
||||
if ( p == f->f_dir.ptr )
|
||||
++f->f_dir.len;
|
||||
}
|
||||
|
||||
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
|
||||
{
|
||||
f->f_member.ptr = p + 1;
|
||||
f->f_member.len = end - p - 2;
|
||||
end = p;
|
||||
}
|
||||
end = file + strlen( file );
|
||||
|
||||
/* Look for .suffix */
|
||||
/* This would be memrchr() */
|
||||
/* Look for (member). */
|
||||
|
||||
p = 0;
|
||||
q = file;
|
||||
if ( ( p = strchr( file, '(' ) ) && ( end[-1] == ')' ) )
|
||||
{
|
||||
f->f_member.ptr = p + 1;
|
||||
f->f_member.len = end - p - 2;
|
||||
end = p;
|
||||
}
|
||||
|
||||
while( q = memchr( q, '.', end - q ) )
|
||||
p = q++;
|
||||
/* Look for .suffix */
|
||||
/* This would be memrchr() */
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_suffix.ptr = p;
|
||||
f->f_suffix.len = end - p;
|
||||
end = p;
|
||||
}
|
||||
p = 0;
|
||||
q = file;
|
||||
|
||||
/* Leaves base */
|
||||
while ( q = memchr( q, '.', end - q ) )
|
||||
p = q++;
|
||||
|
||||
f->f_base.ptr = file;
|
||||
f->f_base.len = end - file;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* path_build() - build a filename given dir/base/suffix/member
|
||||
* path_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 */
|
||||
# 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 }
|
||||
} ;
|
||||
/* 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 )
|
||||
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;
|
||||
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
|
||||
path_build(
|
||||
PATHNAME *f,
|
||||
string* file,
|
||||
int binding )
|
||||
|
||||
void path_build( PATHNAME * f, string * file, int binding )
|
||||
{
|
||||
int dflag, rflag, act;
|
||||
int dflag;
|
||||
int rflag;
|
||||
int 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 ] )
|
||||
|
||||
switch ( act = grid[ rflag ][ dflag ] )
|
||||
{
|
||||
case G_DTDR:
|
||||
{
|
||||
@@ -185,77 +180,73 @@ path_build(
|
||||
string_push_back( file, DELIM );
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case G_DIR:
|
||||
|
||||
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:
|
||||
|
||||
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:
|
||||
|
||||
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 )
|
||||
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:
|
||||
|
||||
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 &&
|
||||
/* 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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
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);
|
||||
|
||||
if ( DEBUG_SEARCH )
|
||||
printf( " -> '%s'\n", file->value );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
*/
|
||||
|
||||
void
|
||||
path_parent( PATHNAME *f )
|
||||
void path_parent( PATHNAME * f )
|
||||
{
|
||||
/* just set everything else to nothing */
|
||||
/* Just set everything else to nothing. */
|
||||
|
||||
f->f_base.ptr =
|
||||
f->f_suffix.ptr =
|
||||
f->f_member.ptr = "";
|
||||
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;
|
||||
f->f_base.len =
|
||||
f->f_suffix.len =
|
||||
f->f_member.len = 0;
|
||||
}
|
||||
|
||||
# endif /* OS_MAC */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* pathsys.h - PATHNAME struct
|
||||
* pathsys.h - PATHNAME struct
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* <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
|
||||
* (member) is an archive member name: the syntax is arbitrary, but must
|
||||
* agree in path_parse(), path_build() and the Jambase.
|
||||
*
|
||||
* On VMS, we keep track of whether the original path was a directory
|
||||
@@ -28,38 +28,39 @@
|
||||
typedef struct _pathname PATHNAME;
|
||||
typedef struct _pathpart PATHPART;
|
||||
|
||||
struct _pathpart {
|
||||
char *ptr;
|
||||
int len;
|
||||
struct _pathpart
|
||||
{
|
||||
char * ptr;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct _pathname {
|
||||
PATHPART part[6];
|
||||
# ifdef OS_VMS
|
||||
int parent;
|
||||
# endif
|
||||
struct _pathname
|
||||
{
|
||||
PATHPART 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]
|
||||
#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 path_build( PATHNAME * f, string * file, int binding );
|
||||
void path_build1( PATHNAME * f, string * file );
|
||||
|
||||
void path_build( PATHNAME *f, string *file, int binding );
|
||||
void path_build1( PATHNAME *f, string *file );
|
||||
|
||||
void path_parse( char *file, PATHNAME *f );
|
||||
void path_parent( PATHNAME *f );
|
||||
void path_parse( char * file, PATHNAME * f );
|
||||
void path_parent( PATHNAME * f );
|
||||
|
||||
#ifdef NT
|
||||
|
||||
/** Returns newstr-allocated string with long equivivalent of 'short_name'.
|
||||
If none exists -- i.e. 'short_path' is already long path, it's returned
|
||||
unaltered. */
|
||||
char* short_path_to_long_path(char* short_path);
|
||||
char * short_path_to_long_path( char * short_path );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -67,15 +68,15 @@ char* short_path_to_long_path(char* short_path);
|
||||
/** Returns a static pointer to the system dependent path to the temporary
|
||||
directory. NOTE: *without* a trailing path separator.
|
||||
*/
|
||||
const char * path_tmpdir(void);
|
||||
const char * path_tmpdir( void );
|
||||
|
||||
/** Returns a new temporary name.
|
||||
*/
|
||||
const char * path_tmpnam(void);
|
||||
const char * path_tmpnam( void );
|
||||
|
||||
/** Returns a new temporary path.
|
||||
*/
|
||||
const char * path_tmpfile(void);
|
||||
const char * path_tmpfile( void );
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* path_parse() - split a file name into dir/base/suffix/member
|
||||
* path_build() - build a filename given dir/base/suffix/member
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
* path_parse() - split a file name into dir/base/suffix/member
|
||||
* path_build() - build a filename given dir/base/suffix/member
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
*
|
||||
* File_parse() and path_build() just manipuate a string and a structure;
|
||||
* they do not make system calls.
|
||||
@@ -48,7 +48,7 @@
|
||||
* 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.
|
||||
* don't include the archive member name.
|
||||
* 01/13/01 (seiwald) - turn on \ handling on UNIX, on by accident
|
||||
*/
|
||||
|
||||
@@ -56,88 +56,86 @@
|
||||
* path_parse() - split a file name into dir/base/suffix/member
|
||||
*/
|
||||
|
||||
void
|
||||
path_parse(
|
||||
char *file,
|
||||
PATHNAME *f )
|
||||
void path_parse( char * file, PATHNAME * f )
|
||||
{
|
||||
char *p, *q;
|
||||
char *end;
|
||||
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
char * p;
|
||||
char * q;
|
||||
char * end;
|
||||
|
||||
/* Look for <grist> */
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
|
||||
if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
/* Look for <grist> */
|
||||
|
||||
/* Look for dir/ */
|
||||
if ( ( file[0] == '<' ) && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
p = strrchr( file, '/' );
|
||||
/* Look for dir/ */
|
||||
|
||||
p = strrchr( file, '/' );
|
||||
|
||||
# if PATH_DELIM == '\\'
|
||||
/* On NT, look for dir\ as well */
|
||||
{
|
||||
char *p1 = strrchr( file, '\\' );
|
||||
p = p1 > p ? p1 : p;
|
||||
}
|
||||
/* On NT, look for dir\ as well */
|
||||
{
|
||||
char *p1 = strrchr( file, '\\' );
|
||||
p = p1 > p ? p1 : p;
|
||||
}
|
||||
# endif
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p - file;
|
||||
|
||||
/* Special case for / - dirname is /, not "" */
|
||||
if ( p )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p - file;
|
||||
|
||||
if( !f->f_dir.len )
|
||||
f->f_dir.len = 1;
|
||||
/* Special case for / - dirname is /, not "" */
|
||||
|
||||
if ( !f->f_dir.len )
|
||||
f->f_dir.len = 1;
|
||||
|
||||
# if PATH_DELIM == '\\'
|
||||
/* Special case for D:/ - dirname is D:/, not "D:" */
|
||||
/* Special case for D:/ - dirname is D:/, not "D:" */
|
||||
|
||||
if( f->f_dir.len == 2 && file[1] == ':' )
|
||||
f->f_dir.len = 3;
|
||||
if ( f->f_dir.len == 2 && file[1] == ':' )
|
||||
f->f_dir.len = 3;
|
||||
# endif
|
||||
|
||||
file = p + 1;
|
||||
}
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
end = file + strlen( file );
|
||||
end = file + strlen( file );
|
||||
|
||||
/* Look for (member) */
|
||||
/* Look for (member) */
|
||||
|
||||
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
|
||||
{
|
||||
f->f_member.ptr = p + 1;
|
||||
f->f_member.len = end - p - 2;
|
||||
end = p;
|
||||
}
|
||||
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() */
|
||||
/* Look for .suffix */
|
||||
/* This would be memrchr() */
|
||||
|
||||
p = 0;
|
||||
q = file;
|
||||
p = 0;
|
||||
q = file;
|
||||
|
||||
while( q = (char *)memchr( q, '.', end - q ) )
|
||||
p = q++;
|
||||
while ( ( q = (char *)memchr( q, '.', end - q ) ) )
|
||||
p = q++;
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_suffix.ptr = p;
|
||||
f->f_suffix.len = end - p;
|
||||
end = p;
|
||||
}
|
||||
if ( p )
|
||||
{
|
||||
f->f_suffix.ptr = p;
|
||||
f->f_suffix.len = end - p;
|
||||
end = p;
|
||||
}
|
||||
|
||||
/* Leaves base */
|
||||
/* Leaves base */
|
||||
|
||||
f->f_base.ptr = file;
|
||||
f->f_base.len = end - file;
|
||||
f->f_base.ptr = file;
|
||||
f->f_base.len = end - file;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -188,22 +186,22 @@ static char as_path_delim( char c )
|
||||
|
||||
void
|
||||
path_build(
|
||||
PATHNAME *f,
|
||||
string *file,
|
||||
int binding )
|
||||
PATHNAME *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
|
||||
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
|
||||
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] == '\\' )
|
||||
@@ -213,43 +211,41 @@ path_build(
|
||||
|
||||
{
|
||||
string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len );
|
||||
/* If 'root' already ends with path delimeter,
|
||||
/* If 'root' already ends with path delimeter,
|
||||
don't add yet another one. */
|
||||
if( ! is_path_delim( f->f_root.ptr[f->f_root.len-1] ) )
|
||||
if ( ! is_path_delim( f->f_root.ptr[f->f_root.len-1] ) )
|
||||
string_push_back( file, as_path_delim( f->f_root.ptr[f->f_root.len] ) );
|
||||
}
|
||||
|
||||
if( f->f_dir.len )
|
||||
{
|
||||
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 ) )
|
||||
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] == ':' ) )
|
||||
if ( !( f->f_dir.len == 3 && f->f_dir.ptr[1] == ':' ) )
|
||||
# endif
|
||||
if( !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[0] ) ) )
|
||||
if ( !( f->f_dir.len == 1 && is_path_delim( f->f_dir.ptr[0] ) ) )
|
||||
string_push_back( file, as_path_delim( f->f_dir.ptr[f->f_dir.len] ) );
|
||||
}
|
||||
|
||||
if( f->f_base.len )
|
||||
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 )
|
||||
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 )
|
||||
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 );
|
||||
@@ -258,21 +254,21 @@ path_build(
|
||||
}
|
||||
|
||||
/*
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
*/
|
||||
|
||||
void
|
||||
path_parent( PATHNAME *f )
|
||||
{
|
||||
/* just set everything else to nothing */
|
||||
/* just set everything else to nothing */
|
||||
|
||||
f->f_base.ptr =
|
||||
f->f_suffix.ptr =
|
||||
f->f_member.ptr = "";
|
||||
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;
|
||||
f->f_base.len =
|
||||
f->f_suffix.len =
|
||||
f->f_member.len = 0;
|
||||
}
|
||||
|
||||
#ifdef NT
|
||||
@@ -296,7 +292,7 @@ DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
|
||||
/* Is the string valid? */
|
||||
if (!lpszShortPath) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is the path valid? */
|
||||
@@ -305,7 +301,7 @@ DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
|
||||
|
||||
/* Convert "/" to "\" */
|
||||
for (i=0;i<len;++i) {
|
||||
if (lpszShortPath[i]==_T('/'))
|
||||
if (lpszShortPath[i]==_T('/'))
|
||||
path[i]=_T('\\');
|
||||
else
|
||||
path[i]=lpszShortPath[i];
|
||||
@@ -331,7 +327,7 @@ DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
|
||||
}
|
||||
_tcsncpy(ret,path,2);
|
||||
}
|
||||
|
||||
|
||||
/* Expand the path for each subpath, and strip trailing backslashes */
|
||||
for (prev_pos = pos-1;pos<=len;++pos) {
|
||||
if (path[pos]==_T('\\') || (path[pos]==_T('\0') &&
|
||||
@@ -356,9 +352,9 @@ DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
|
||||
/* If it's ".." element, we need to append it, not
|
||||
the name in parent that FindFirstFile will return.
|
||||
Same goes for "." */
|
||||
|
||||
|
||||
if (new_element[0] == _T('.') && new_element[1] == _T('\0') ||
|
||||
new_element[0] == _T('.') && new_element[1] == _T('.')
|
||||
new_element[0] == _T('.') && new_element[1] == _T('.')
|
||||
&& new_element[2] == _T('\0'))
|
||||
{
|
||||
_tcscat(ret, new_element);
|
||||
@@ -378,21 +374,21 @@ DWORD ShortPathToLongPath(LPCTSTR lpszShortPath,LPTSTR lpszLongPath,DWORD
|
||||
prev_pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
len=_tcslen(ret)+1;
|
||||
if (cchBuffer>=len)
|
||||
_tcscpy(lpszLongPath,ret);
|
||||
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
char* short_path_to_long_path(char* short_path)
|
||||
{
|
||||
{
|
||||
char buffer2[_MAX_PATH];
|
||||
int ret = ShortPathToLongPath(short_path, buffer2, _MAX_PATH);
|
||||
|
||||
if (ret)
|
||||
return newstr(buffer2);
|
||||
return newstr(buffer2);
|
||||
else
|
||||
return newstr(short_path);
|
||||
}
|
||||
@@ -446,14 +442,14 @@ const char * path_tmpnam(void)
|
||||
const char * path_tmpfile(void)
|
||||
{
|
||||
const char * result = 0;
|
||||
|
||||
|
||||
string file_path;
|
||||
string_copy(&file_path,path_tmpdir());
|
||||
string_push_back(&file_path,PATH_DELIM);
|
||||
string_append(&file_path,path_tmpnam());
|
||||
result = newstr(file_path.value);
|
||||
string_free(&file_path);
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
*
|
||||
* External routines:
|
||||
*
|
||||
* path_parse() - split a file name into dir/base/suffix/member
|
||||
* path_build() - build a filename given dir/base/suffix/member
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
* path_parse() - split a file name into dir/base/suffix/member
|
||||
* path_build() - build a filename given dir/base/suffix/member
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
*
|
||||
* File_parse() and path_build() just manipuate a string and a structure;
|
||||
* they do not make system calls.
|
||||
*
|
||||
* WARNING! This file contains voodoo logic, as black magic is
|
||||
* 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.
|
||||
*
|
||||
@@ -38,258 +38,244 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* path_parse() - split a file name into dir/base/suffix/member
|
||||
* path_parse() - split a file name into dir/base/suffix/member.
|
||||
*/
|
||||
|
||||
void
|
||||
path_parse(
|
||||
char *file,
|
||||
PATHNAME *f )
|
||||
void path_parse( char * file, PATHNAME * f )
|
||||
{
|
||||
char *p, *q;
|
||||
char *end;
|
||||
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
char * p;
|
||||
char * q;
|
||||
char * end;
|
||||
|
||||
/* Look for <grist> */
|
||||
memset( (char *)f, 0, sizeof( *f ) );
|
||||
|
||||
if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
/* Look for <grist> */
|
||||
|
||||
/* Look for dev:[dir] or dev: */
|
||||
if ( ( file[0] == '<' ) && ( p = strchr( file, '>' ) ) )
|
||||
{
|
||||
f->f_grist.ptr = file;
|
||||
f->f_grist.len = p - file;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
if( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p + 1 - file;
|
||||
file = p + 1;
|
||||
}
|
||||
/* Look for dev:[dir] or dev: */
|
||||
|
||||
end = file + strlen( file );
|
||||
if ( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
|
||||
{
|
||||
f->f_dir.ptr = file;
|
||||
f->f_dir.len = p + 1 - file;
|
||||
file = p + 1;
|
||||
}
|
||||
|
||||
/* Look for (member) */
|
||||
end = file + strlen( file );
|
||||
|
||||
if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
|
||||
{
|
||||
f->f_member.ptr = p + 1;
|
||||
f->f_member.len = end - p - 2;
|
||||
end = p;
|
||||
}
|
||||
/* Look for (member). */
|
||||
|
||||
/* Look for .suffix */
|
||||
/* This would be memrchr() */
|
||||
if ( ( p = strchr( file, '(' ) ) && ( end[ -1 ] == ')' ) )
|
||||
{
|
||||
f->f_member.ptr = p + 1;
|
||||
f->f_member.len = end - p - 2;
|
||||
end = p;
|
||||
}
|
||||
|
||||
p = 0;
|
||||
q = file;
|
||||
/* Look for .suffix */
|
||||
/* This would be memrchr(). */
|
||||
|
||||
while( q = (char *)memchr( q, '.', end - q ) )
|
||||
p = q++;
|
||||
p = 0;
|
||||
q = file;
|
||||
|
||||
if( p )
|
||||
{
|
||||
f->f_suffix.ptr = p;
|
||||
f->f_suffix.len = end - p;
|
||||
end = p;
|
||||
}
|
||||
while ( q = (char *)memchr( q, '.', end - q ) )
|
||||
p = q++;
|
||||
|
||||
/* Leaves base */
|
||||
if ( p )
|
||||
{
|
||||
f->f_suffix.ptr = p;
|
||||
f->f_suffix.len = end - p;
|
||||
end = p;
|
||||
}
|
||||
|
||||
f->f_base.ptr = file;
|
||||
f->f_base.len = end - file;
|
||||
/* Leaves base. */
|
||||
f->f_base.ptr = file;
|
||||
f->f_base.len = end - file;
|
||||
|
||||
/* Is this a directory without a file spec? */
|
||||
|
||||
f->parent = 0;
|
||||
/* Is this a directory without a file spec? */
|
||||
f->parent = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* dir mods result
|
||||
* --- --- ------
|
||||
* 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=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=[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]
|
||||
* (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 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] */
|
||||
# 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,
|
||||
/* 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 )
|
||||
struct dirinf
|
||||
{
|
||||
while( len-- )
|
||||
if( *buf && *buf++ == c )
|
||||
return buf - 1;
|
||||
int flags;
|
||||
|
||||
return 0;
|
||||
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 )
|
||||
|
||||
static void dir_flags( char * buf, int len, struct dirinf * i )
|
||||
{
|
||||
char *p;
|
||||
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 || !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;
|
||||
}
|
||||
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 */
|
||||
/* But if its rooted in any way. */
|
||||
|
||||
if( i->dir.len == 8 && !strncmp( i->dir.ptr, "[000000]", 8 ) )
|
||||
i->flags = DIR_ROOT;
|
||||
if ( ( i->dir.len == 8 ) && !strncmp( i->dir.ptr, "[000000]", 8 ) )
|
||||
i->flags = DIR_ROOT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* path_build() - build a filename given dir/base/suffix/member
|
||||
*/
|
||||
|
||||
void
|
||||
path_build(
|
||||
PATHNAME *f,
|
||||
string *file,
|
||||
int binding )
|
||||
void path_build( PATHNAME * f, string * file, int binding )
|
||||
{
|
||||
struct dirinf root, dir;
|
||||
struct dirinf root;
|
||||
struct dirinf dir;
|
||||
int g;
|
||||
|
||||
file_build1( f, file );
|
||||
|
||||
/* Get info on root and dir for combining. */
|
||||
|
||||
/* 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 ] )
|
||||
/* Combine. */
|
||||
switch ( g = grid[ root.flags ][ dir.flags ] )
|
||||
{
|
||||
case G_DIR:
|
||||
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:
|
||||
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:
|
||||
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_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] == ']' )
|
||||
if ( file->value[file->size - 1] == ']' )
|
||||
string_pop_back( file );
|
||||
|
||||
/* Add . if separating two -'s */
|
||||
|
||||
if( g == G_DDD )
|
||||
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:
|
||||
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, '[' );
|
||||
@@ -299,51 +285,52 @@ path_build(
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
if( DEBUG_SEARCH && ( root.flags || dir.flags ) )
|
||||
{
|
||||
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
|
||||
# endif
|
||||
|
||||
/*
|
||||
/*
|
||||
* Now do the special :P modifier when no file was present.
|
||||
* (none) (none)
|
||||
* [dir1.dir2] [dir1]
|
||||
* [dir] [000000]
|
||||
* [.dir] (none)
|
||||
* [] []
|
||||
* (none) (none)
|
||||
* [dir1.dir2] [dir1]
|
||||
* [dir] [000000]
|
||||
* [.dir] (none)
|
||||
* [] []
|
||||
*/
|
||||
|
||||
if( file->value[file->size - 1] == ']' && f->parent )
|
||||
if ( ( file->value[ file->size - 1 ] == ']' ) && f->parent )
|
||||
{
|
||||
char* p = file->value + file->size;
|
||||
while( p-- > file->value )
|
||||
char * p = file->value + file->size;
|
||||
while ( p-- > file->value )
|
||||
{
|
||||
if( *p == '.' )
|
||||
if ( *p == '.' )
|
||||
{
|
||||
/* If we've truncated everything and left with '[',
|
||||
return empty string. */
|
||||
if (p == file->value + 1)
|
||||
if ( p == file->value + 1 )
|
||||
string_truncate( file, 0 );
|
||||
else {
|
||||
else
|
||||
{
|
||||
string_truncate( file, p - file->value );
|
||||
string_push_back( file, ']' );
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if( *p == '-' )
|
||||
|
||||
if ( *p == '-' )
|
||||
{
|
||||
/* handle .- or - */
|
||||
if( p > file->value && p[-1] == '.' )
|
||||
if ( ( p > file->value ) && ( p[ -1 ] == '.' ) )
|
||||
--p;
|
||||
|
||||
|
||||
*p++ = ']';
|
||||
break;
|
||||
}
|
||||
else if( *p == '[' )
|
||||
|
||||
if ( *p == '[' )
|
||||
{
|
||||
if( p[1] == ']' )
|
||||
if ( p[ 1 ] == ']' )
|
||||
{
|
||||
/* CONSIDER: I don't see any use of this code. We immediately
|
||||
break, and 'p' is a local variable. */
|
||||
@@ -360,26 +347,21 @@ path_build(
|
||||
}
|
||||
|
||||
/* Now copy the file pieces. */
|
||||
|
||||
if( f->f_base.len )
|
||||
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 )
|
||||
{
|
||||
/* 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 )
|
||||
{
|
||||
else if ( binding && f->f_base.len )
|
||||
string_push_back( file, '.' );
|
||||
}
|
||||
|
||||
if( f->f_member.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 );
|
||||
@@ -387,8 +369,8 @@ path_build(
|
||||
}
|
||||
|
||||
# ifdef DEBUG
|
||||
if( DEBUG_SEARCH )
|
||||
printf("built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n",
|
||||
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,
|
||||
@@ -398,27 +380,27 @@ path_build(
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
* path_parent() - make a PATHNAME point to its parent dir
|
||||
*/
|
||||
|
||||
void
|
||||
path_parent( PATHNAME *f )
|
||||
void path_parent( PATHNAME * f )
|
||||
{
|
||||
if( f->f_base.len )
|
||||
{
|
||||
f->f_base.ptr =
|
||||
f->f_suffix.ptr =
|
||||
f->f_member.ptr = "";
|
||||
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;
|
||||
}
|
||||
f->f_base.len =
|
||||
f->f_suffix.len =
|
||||
f->f_member.len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
f->parent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# endif /* VMS */
|
||||
|
||||
@@ -6,25 +6,29 @@
|
||||
#include "lists.h"
|
||||
#include "newstr.h"
|
||||
#include "pathsys.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* MinGW on windows declares PATH_MAX in limits.h */
|
||||
#if defined(NT) && ! defined(__GNUC__)
|
||||
#include <direct.h>
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#else
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#if defined(__COMO__)
|
||||
#include <linux/limits.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
/* The current directory can't change in bjam, so optimize this to cache
|
||||
** the result.
|
||||
*/
|
||||
static char pwd_buffer[PATH_MAX];
|
||||
static char * pwd_result = NULL;
|
||||
|
||||
|
||||
@@ -33,20 +37,30 @@ pwd(void)
|
||||
{
|
||||
if (!pwd_result)
|
||||
{
|
||||
if (getcwd(pwd_buffer, sizeof(pwd_buffer)) == NULL)
|
||||
{
|
||||
int buffer_size = PATH_MAX;
|
||||
char * result_buffer = 0;
|
||||
do
|
||||
{
|
||||
char * buffer = BJAM_MALLOC_RAW(buffer_size);
|
||||
result_buffer = getcwd(buffer,buffer_size);
|
||||
if (result_buffer)
|
||||
{
|
||||
#ifdef NT
|
||||
pwd_result = short_path_to_long_path(result_buffer);
|
||||
#else
|
||||
pwd_result = newstr(result_buffer);
|
||||
#endif
|
||||
}
|
||||
buffer_size *= 2;
|
||||
BJAM_FREE_RAW(buffer);
|
||||
}
|
||||
while (!pwd_result && errno == ERANGE);
|
||||
|
||||
if (!pwd_result)
|
||||
{
|
||||
perror("can not get current directory");
|
||||
return L0;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef NT
|
||||
pwd_result = short_path_to_long_path(pwd_buffer);
|
||||
#else
|
||||
pwd_result = newstr(pwd_buffer);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return list_new(L0, pwd_result);
|
||||
}
|
||||
|
||||
|
||||
1858
src/engine/regexp.c
1858
src/engine/regexp.c
File diff suppressed because it is too large
Load Diff
@@ -9,13 +9,13 @@
|
||||
|
||||
#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. */
|
||||
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 );
|
||||
@@ -26,7 +26,7 @@ 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
|
||||
#define MAGIC 0234
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,11 +11,12 @@
|
||||
*/
|
||||
|
||||
#ifndef RULES_DWA_20011020_H
|
||||
# define RULES_DWA_20011020_H
|
||||
#define RULES_DWA_20011020_H
|
||||
|
||||
#include "modules.h"
|
||||
#include "jam.h"
|
||||
#include "parse.h"
|
||||
|
||||
# include "modules.h"
|
||||
# include "jam.h"
|
||||
# include "parse.h"
|
||||
|
||||
/*
|
||||
* rules.h - targets, rules, and related information
|
||||
@@ -26,12 +27,12 @@
|
||||
*
|
||||
* 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
|
||||
* 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 - an entity (e.g. a file) 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.
|
||||
@@ -49,217 +50,228 @@ typedef struct _action ACTION;
|
||||
typedef struct _actions ACTIONS;
|
||||
typedef struct _settings SETTINGS ;
|
||||
|
||||
/* RULE - a generic jam rule, the product of RULE and ACTIONS */
|
||||
/* RULE - a generic jam rule, the product of RULE and ACTIONS. */
|
||||
|
||||
/* A rule's argument list */
|
||||
/* A rule's argument list. */
|
||||
struct argument_list
|
||||
{
|
||||
int reference_count;
|
||||
LOL data[1];
|
||||
};
|
||||
|
||||
/* The build actions corresponding to a rule */
|
||||
/* 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 */
|
||||
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 */
|
||||
#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 /* do not 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 */
|
||||
module_t *module; /* module in which this rule is executed */
|
||||
int exported; /* nonzero if this rule is supposed to
|
||||
* appear in the global module and be
|
||||
* automatically imported into other modules
|
||||
*/
|
||||
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 */
|
||||
module_t * module; /* module in which this rule is executed */
|
||||
int exported; /* nonzero if this rule is supposed to appear in
|
||||
* the global module and be automatically
|
||||
* imported into other modules
|
||||
*/
|
||||
#ifdef HAVE_PYTHON
|
||||
PyObject* python_function;
|
||||
#endif
|
||||
PyObject * python_function;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ACTIONS - a chain of ACTIONs */
|
||||
/* ACTIONS - a chain of ACTIONs. */
|
||||
struct _actions
|
||||
{
|
||||
ACTIONS * next;
|
||||
ACTIONS * tail; /* valid only for head */
|
||||
ACTION * action;
|
||||
};
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
/* ACTION - a RULE instance with targets and sources */
|
||||
/* 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() */
|
||||
};
|
||||
|
||||
struct _action {
|
||||
RULE *rule;
|
||||
TARGETS *targets;
|
||||
TARGETS *sources; /* aka $(>) */
|
||||
char running; /* has been started */
|
||||
char status; /* see TARGET status */
|
||||
} ;
|
||||
/* TARGETS - a chain of TARGETs. */
|
||||
struct _targets
|
||||
{
|
||||
TARGETS * next;
|
||||
TARGETS * tail; /* valid only for head */
|
||||
TARGET * target;
|
||||
};
|
||||
|
||||
/* SETTINGS - variables to set when executing a TARGET's ACTIONS */
|
||||
/* TARGET - an entity (e.g. a file) 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 */
|
||||
|
||||
struct _settings {
|
||||
SETTINGS *next;
|
||||
char *symbol; /* symbol name for var_set() */
|
||||
LIST *value; /* symbol value for var_set() */
|
||||
} ;
|
||||
short flags; /* status info */
|
||||
|
||||
/* TARGETS - a chain of TARGETs */
|
||||
#define T_FLAG_TEMP 0x0001 /* TEMPORARY applied */
|
||||
#define T_FLAG_NOCARE 0x0002 /* NOCARE applied */
|
||||
#define T_FLAG_NOTFILE 0x0004 /* NOTFILE applied */
|
||||
#define T_FLAG_TOUCHED 0x0008 /* ALWAYS applied or -t target */
|
||||
#define T_FLAG_LEAVES 0x0010 /* LEAVES applied */
|
||||
#define T_FLAG_NOUPDATE 0x0020 /* NOUPDATE applied */
|
||||
#define T_FLAG_VISITED 0x0040 /* CWM: Used in debugging */
|
||||
|
||||
struct _targets {
|
||||
TARGETS *next;
|
||||
TARGETS *tail; /* valid only for head */
|
||||
TARGET *target;
|
||||
} ;
|
||||
/* This flag has been added to support a new built-in rule named "RMBAD". It is
|
||||
* used to force removal of outdated targets whose dependencies fail to build.
|
||||
*/
|
||||
#define T_FLAG_RMOLD 0x0080 /* RMBAD applied */
|
||||
|
||||
/* TARGET - a file or "thing" that can be built */
|
||||
/* This flag was added to support a new built-in rule named "FAIL_EXPECTED" used
|
||||
* to indicate that the result of running a given action should be inverted,
|
||||
* i.e. ok <=> fail. This is useful for launching certain test runs from a
|
||||
* Jamfile.
|
||||
*/
|
||||
#define T_FLAG_FAIL_EXPECTED 0x0100 /* FAIL_EXPECTED applied */
|
||||
|
||||
struct _target {
|
||||
char *name;
|
||||
char *boundname; /* if search() relocates target */
|
||||
ACTIONS *actions; /* rules to execute, if any */
|
||||
SETTINGS *settings; /* variables to define */
|
||||
#define T_FLAG_INTERNAL 0x0200 /* internal INCLUDES node */
|
||||
|
||||
short flags; /* status info */
|
||||
/* Indicates that the target must be a file. This prevents matching non-files,
|
||||
* like directories, when a target is searched.
|
||||
*/
|
||||
#define T_FLAG_ISFILE 0x0400
|
||||
|
||||
# define T_FLAG_TEMP 0x0001 /* TEMPORARY applied */
|
||||
# define T_FLAG_NOCARE 0x0002 /* NOCARE applied */
|
||||
# define T_FLAG_NOTFILE 0x0004 /* NOTFILE applied */
|
||||
# define T_FLAG_TOUCHED 0x0008 /* ALWAYS applied or -t target */
|
||||
# define T_FLAG_LEAVES 0x0010 /* LEAVES applied */
|
||||
# define T_FLAG_NOUPDATE 0x0020 /* NOUPDATE applied */
|
||||
# define T_FLAG_VISITED 0x0040 /* CWM: Used in debugging */
|
||||
char binding; /* how target relates to a real file or
|
||||
* folder
|
||||
*/
|
||||
|
||||
/* this flag was added to support a new builtin rule named "RMBAD" */
|
||||
/* it is used to force removal of outdated targets whose dependencies
|
||||
* fail to build */
|
||||
|
||||
# define T_FLAG_RMOLD 0x0080 /* RMBAD applied */
|
||||
#define T_BIND_UNBOUND 0 /* a disembodied name */
|
||||
#define T_BIND_MISSING 1 /* could not find real file */
|
||||
#define T_BIND_PARENTS 2 /* using parent's timestamp */
|
||||
#define T_BIND_EXISTS 3 /* real file, timestamp valid */
|
||||
|
||||
/* 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 0x0100 /* FAIL_EXPECTED applied */
|
||||
TARGETS * depends; /* dependencies */
|
||||
TARGETS * dependants; /* the inverse of dependencies */
|
||||
TARGETS * rebuilds; /* targets that should be force-rebuilt
|
||||
* whenever this one is
|
||||
*/
|
||||
TARGET * includes; /* internal includes node */
|
||||
TARGET * original_target; /* original_target->includes = this */
|
||||
char rescanned;
|
||||
|
||||
# define T_FLAG_INTERNAL 0x0200 /* internal INCLUDES node */
|
||||
time_t time; /* update time */
|
||||
time_t leaf; /* update time of leaf sources */
|
||||
|
||||
/* Indicates that the target must be a file. This prevents matching non-files,
|
||||
like directories, when a target is searched. */
|
||||
#define T_FLAG_ISFILE 0x0400
|
||||
char fate; /* make0()'s diagnosis */
|
||||
|
||||
#define T_FATE_INIT 0 /* nothing done to target */
|
||||
#define T_FATE_MAKING 1 /* make0(target) on stack */
|
||||
|
||||
#define T_FATE_STABLE 2 /* target did not 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_REBUILD 6
|
||||
#define T_FATE_MISSING 7 /* is missing, needs updating */
|
||||
#define T_FATE_NEEDTMP 8 /* missing temp that must be rebuild */
|
||||
#define T_FATE_OUTDATED 9 /* is out of date, needs updating */
|
||||
#define T_FATE_UPDATE 10 /* deps updated, needs updating */
|
||||
|
||||
#define T_FATE_BROKEN 11 /* >= BROKEN ruins parents */
|
||||
#define T_FATE_CANTFIND 11 /* no rules to make missing target */
|
||||
#define T_FATE_CANTMAKE 12 /* can not find dependencies */
|
||||
|
||||
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 */
|
||||
|
||||
#ifdef OPT_SEMAPHORE
|
||||
# define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
|
||||
#define T_MAKE_SEMAPHORE 5 /* Special target type for semaphores */
|
||||
#endif
|
||||
|
||||
|
||||
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 */
|
||||
#ifdef OPT_SEMAPHORE
|
||||
TARGET *semaphore; /* used in serialization */
|
||||
#endif
|
||||
# define T_BIND_PARENTS 2 /* using parent's timestamp */
|
||||
# define T_BIND_EXISTS 3 /* real file, timestamp valid */
|
||||
|
||||
TARGETS *depends; /* dependencies */
|
||||
TARGETS *dependents;/* the inverse of dependencies */
|
||||
TARGETS *rebuilds; /* targets that should be force-rebuilt whenever this one is */
|
||||
TARGET *includes; /* includes */
|
||||
TARGET *original_target; /* original_target->includes = this */
|
||||
char rescanned;
|
||||
|
||||
time_t time; /* update time */
|
||||
time_t leaf; /* update time of leaf sources */
|
||||
|
||||
char fate; /* make0()'s diagnosis */
|
||||
|
||||
# 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_REBUILD 6
|
||||
# define T_FATE_MISSING 7 /* is missing, needs updating */
|
||||
# define T_FATE_NEEDTMP 8 /* missing temp that must be rebuild */
|
||||
# define T_FATE_OUTDATED 9 /* is out of date, needs updating */
|
||||
# define T_FATE_UPDATE 10 /* deps updated, needs updating */
|
||||
|
||||
# define T_FATE_BROKEN 11 /* >= BROKEN ruins parents */
|
||||
# define T_FATE_CANTFIND 11 /* no rules to make missing target */
|
||||
# define T_FATE_CANTMAKE 12 /* 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 */
|
||||
|
||||
char* failed;
|
||||
} ;
|
||||
|
||||
RULE *bindrule( char *rulename, module_t* );
|
||||
|
||||
RULE* import_rule( RULE* source, module_t* m, char* name );
|
||||
RULE* new_rule_body( module_t* m, char* rulename, argument_list* args, PARSE* procedure, int exprt );
|
||||
RULE* new_rule_actions( module_t* m, char* rulename, char* command, LIST* bindlist, int flags );
|
||||
TARGET *bindtarget( const char *targetname );
|
||||
TARGET *copytarget( const TARGET *t );
|
||||
void bind_explicitly_located_targets();
|
||||
TARGET* search_for_target( char * name, LIST* search_path );
|
||||
void touchtarget( char *t );
|
||||
TARGETS *targetlist( TARGETS *chain, LIST *targets );
|
||||
TARGETS *targetentry( TARGETS *chain, TARGET *target );
|
||||
TARGETS *targetchain( TARGETS *chain, TARGETS *targets );
|
||||
void freetargets( TARGETS *chain );
|
||||
ACTIONS *actionlist( ACTIONS *chain, ACTION *action );
|
||||
void freeactions( ACTIONS *chain );
|
||||
SETTINGS *addsettings( SETTINGS *head, int flag, char *symbol, LIST *value );
|
||||
void pushsettings( SETTINGS *v );
|
||||
void popsettings( SETTINGS *v );
|
||||
SETTINGS *copysettings( SETTINGS *v );
|
||||
void freesettings( SETTINGS *v );
|
||||
void rule_free( RULE *r );
|
||||
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*);
|
||||
|
||||
TARGET * semaphore; /* used in serialization */
|
||||
#endif
|
||||
|
||||
char status; /* exec_cmd() result */
|
||||
|
||||
int asynccnt; /* child deps outstanding */
|
||||
TARGETS * parents; /* used by make1() for completion */
|
||||
char * cmds; /* type-punned command list */
|
||||
|
||||
char * failed;
|
||||
};
|
||||
|
||||
|
||||
/* Action related functions. */
|
||||
ACTIONS * actionlist ( ACTIONS *, ACTION * );
|
||||
void freeactions ( ACTIONS * );
|
||||
SETTINGS * addsettings ( SETTINGS *, int flag, char * symbol, LIST * value );
|
||||
void pushsettings ( SETTINGS * );
|
||||
void popsettings ( SETTINGS * );
|
||||
SETTINGS * copysettings ( SETTINGS * );
|
||||
void freesettings ( SETTINGS * );
|
||||
void actions_refer( rule_actions * );
|
||||
void actions_free ( rule_actions * );
|
||||
|
||||
/* Argument list related functions. */
|
||||
void args_free ( argument_list * );
|
||||
argument_list * args_new ();
|
||||
void args_refer( argument_list * );
|
||||
|
||||
/* Rule related functions. */
|
||||
RULE * bindrule ( char * rulename, module_t * );
|
||||
RULE * import_rule ( RULE * source, module_t *, char * name );
|
||||
RULE * new_rule_body ( module_t *, char * rulename, argument_list *, PARSE * procedure, int exprt );
|
||||
RULE * new_rule_actions( module_t *, char * rulename, char * command, LIST * bindlist, int flags );
|
||||
void rule_free ( RULE * );
|
||||
|
||||
/* Target related functions. */
|
||||
void bind_explicitly_located_targets();
|
||||
TARGET * bindtarget ( char const * target_name );
|
||||
TARGET * copytarget ( TARGET const * t );
|
||||
void freetargets ( TARGETS * );
|
||||
TARGET * search_for_target ( char * name, LIST * search_path );
|
||||
TARGETS * targetchain ( TARGETS * chain, TARGETS * );
|
||||
TARGETS * targetentry ( TARGETS * chain, TARGET * );
|
||||
void target_include ( TARGET * including, TARGET * included );
|
||||
TARGETS * targetlist ( TARGETS * chain, LIST * target_names );
|
||||
void touch_target ( char * t );
|
||||
|
||||
/* Final module cleanup. */
|
||||
void rules_done();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,414 +4,406 @@
|
||||
* 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"
|
||||
#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().
|
||||
* 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.
|
||||
* defined before Linux's yacc tries to redefine it.
|
||||
*/
|
||||
|
||||
struct keyword {
|
||||
char *word;
|
||||
int type;
|
||||
} keywords[] = {
|
||||
# include "jamgramtab.h"
|
||||
{ 0, 0 }
|
||||
} ;
|
||||
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 */
|
||||
} ;
|
||||
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 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
|
||||
*/
|
||||
static char * symdump( YYSTYPE * );
|
||||
|
||||
void
|
||||
yymode( int n )
|
||||
{
|
||||
scanmode = n;
|
||||
}
|
||||
#define BIGGEST_TOKEN 10240 /* no single token can be larger */
|
||||
|
||||
void
|
||||
yyerror( char *s )
|
||||
{
|
||||
if( incp )
|
||||
printf( "%s:%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 *)BJAM_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
|
||||
* Set parser mode: normal, string, or keyword.
|
||||
*/
|
||||
|
||||
void yymode( int n )
|
||||
{
|
||||
scanmode = n;
|
||||
}
|
||||
|
||||
|
||||
void yyerror( char * s )
|
||||
{
|
||||
/* We use yylval instead of incp to access the error location information as
|
||||
* the incp pointer will already be reset to 0 in case the error occurred at
|
||||
* EOF.
|
||||
*
|
||||
* The two may differ only if we get an error while reading a lexical token
|
||||
* spanning muliple lines, e.g. a multi-line string literal or action body,
|
||||
* in which case yylval location information will hold the information about
|
||||
* where this token started while incp will hold the information about where
|
||||
* reading it broke.
|
||||
*
|
||||
* TODO: Test the theory about when yylval and incp location information are
|
||||
* the same and when they differ.
|
||||
*/
|
||||
printf( "%s:%d: %s at %s\n", yylval.file, yylval.line, s, symdump( &yylval ) );
|
||||
++anyerrors;
|
||||
}
|
||||
|
||||
|
||||
int yyanyerrors()
|
||||
{
|
||||
return anyerrors != 0;
|
||||
}
|
||||
|
||||
|
||||
void yyfparse( char * s )
|
||||
{
|
||||
struct include * i = (struct include *)BJAM_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.
|
||||
* Fabricates a continuous stream of characters across include files, returning
|
||||
* EOF at the bitter end.
|
||||
*/
|
||||
|
||||
int
|
||||
yyline()
|
||||
int yyline()
|
||||
{
|
||||
struct include *i = incp;
|
||||
struct include * i = incp;
|
||||
|
||||
if( !incp )
|
||||
return EOF;
|
||||
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. */
|
||||
/* 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 there is more data in this line, return it. */
|
||||
if ( *i->string )
|
||||
return *i->string++;
|
||||
|
||||
if( *i->string )
|
||||
return *i->string++;
|
||||
/* If we are reading from an internal string list, go to the next string. */
|
||||
if ( i->strings )
|
||||
{
|
||||
if ( *i->strings )
|
||||
{
|
||||
++i->line;
|
||||
i->string = *(i->strings++);
|
||||
return *i->string++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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 we're reading from an internal string list, go to the */
|
||||
/* next string. */
|
||||
/* If there is 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++;
|
||||
}
|
||||
}
|
||||
|
||||
if( i->strings )
|
||||
{
|
||||
if( !*i->strings )
|
||||
goto next;
|
||||
/* This include is done. Free it up and return EOF so yyparse() returns to
|
||||
* parse_file().
|
||||
*/
|
||||
|
||||
i->line++;
|
||||
i->string = *(i->strings++);
|
||||
return *i->string++;
|
||||
}
|
||||
incp = i->next;
|
||||
|
||||
/* If necessary, open the file */
|
||||
/* Close file, free name. */
|
||||
if ( i->file && ( i->file != stdin ) )
|
||||
fclose( i->file );
|
||||
freestr( i->fname );
|
||||
BJAM_FREE( (char *)i );
|
||||
|
||||
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 );
|
||||
BJAM_FREE( (char *)i );
|
||||
|
||||
return EOF;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* yylex() - set yylval to current token; return its type
|
||||
* 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() - 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.
|
||||
* 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-- )
|
||||
#define yychar() ( *incp->string ? *incp->string++ : yyline() )
|
||||
#define yyprev() ( incp->string-- )
|
||||
|
||||
int
|
||||
yylex()
|
||||
int yylex()
|
||||
{
|
||||
int c;
|
||||
char buf[BIGGEST_TOKEN];
|
||||
char *b = buf;
|
||||
int c;
|
||||
char buf[ BIGGEST_TOKEN ];
|
||||
char * b = buf;
|
||||
|
||||
if( !incp )
|
||||
goto eof;
|
||||
if ( !incp )
|
||||
goto eof;
|
||||
|
||||
/* Get first character (whitespace or of token) */
|
||||
/* Get first character (whitespace or of token). */
|
||||
c = yychar();
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
int nest = 1;
|
||||
while ( ( c != EOF ) && ( b < buf + sizeof( buf ) ) )
|
||||
{
|
||||
if ( c == '{' )
|
||||
++nest;
|
||||
|
||||
while( c != EOF && b < buf + sizeof( buf ) )
|
||||
{
|
||||
if( c == '{' )
|
||||
nest++;
|
||||
if ( ( c == '}' ) && !--nest )
|
||||
break;
|
||||
|
||||
if( c == '}' && !--nest )
|
||||
break;
|
||||
*b++ = c;
|
||||
|
||||
*b++ = c;
|
||||
c = yychar();
|
||||
|
||||
c = yychar();
|
||||
/* Turn trailing "\r\n" sequences into plain "\n" for Cygwin. */
|
||||
if ( ( c == '\n' ) && ( b[ -1 ] == '\r' ) )
|
||||
--b;
|
||||
}
|
||||
|
||||
/* turn trailing "\r\n" sequences into plain "\n"
|
||||
* for Cygwin
|
||||
*/
|
||||
if (c == '\n' && b[-1] == '\r')
|
||||
--b;
|
||||
}
|
||||
/* We ate the ending brace -- regurgitate it. */
|
||||
if ( c != EOF )
|
||||
yyprev();
|
||||
|
||||
/* We ate the ending brace -- regurgitate it. */
|
||||
/* Check for obvious errors. */
|
||||
if ( b == buf + sizeof( buf ) )
|
||||
{
|
||||
yyerror( "action block too big" );
|
||||
goto eof;
|
||||
}
|
||||
|
||||
if( c != EOF )
|
||||
yyprev();
|
||||
if ( nest )
|
||||
{
|
||||
yyerror( "unmatched {} in action block" );
|
||||
goto eof;
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
*b = 0;
|
||||
yylval.type = STRING;
|
||||
yylval.string = newstr( buf );
|
||||
yylval.file = incp->fname;
|
||||
yylval.line = incp->line;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
char *b = buf;
|
||||
struct keyword *k;
|
||||
int inquote = 0;
|
||||
int notkeyword;
|
||||
|
||||
/* Eat white space */
|
||||
}
|
||||
else
|
||||
{
|
||||
char * b = buf;
|
||||
struct keyword * k;
|
||||
int inquote = 0;
|
||||
int notkeyword;
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
/* Skip past white space */
|
||||
|
||||
while( c != EOF && isspace( c ) )
|
||||
/* Eat white space. */
|
||||
for ( ;; )
|
||||
{
|
||||
/* Skip past white space. */
|
||||
while ( ( c != EOF ) && isspace( c ) )
|
||||
c = yychar();
|
||||
|
||||
/* Not a comment? Swallow up comment line. */
|
||||
|
||||
if( c != '#' )
|
||||
/* Not a comment? */
|
||||
if ( c != '#' )
|
||||
break;
|
||||
while( ( c = yychar() ) != EOF && c != '\n' )
|
||||
;
|
||||
}
|
||||
|
||||
/* c now points to the first character of a token. */
|
||||
/* Swallow up comment line. */
|
||||
while ( ( ( c = yychar() ) != EOF ) && ( c != '\n' ) ) ;
|
||||
}
|
||||
|
||||
if( c == EOF )
|
||||
goto eof;
|
||||
/* c now points to the first character of a token. */
|
||||
if ( c == EOF )
|
||||
goto eof;
|
||||
|
||||
yylval.file = incp->fname;
|
||||
yylval.line = incp->line;
|
||||
|
||||
/* While scanning the word, disqualify it for (expensive) */
|
||||
/* keyword lookup when we can: $anything, "anything", \anything */
|
||||
|
||||
notkeyword = c == '$';
|
||||
/* While scanning the word, disqualify it for (expensive) keyword lookup
|
||||
* when we can: $anything, "anything", \anything
|
||||
*/
|
||||
notkeyword = c == '$';
|
||||
|
||||
/* look for white space to delimit word */
|
||||
/* "'s get stripped but preserve white space */
|
||||
/* \ protects next character */
|
||||
/* Look for white space to delimit word. "'s get stripped but preserve
|
||||
* white space. \ protects next character.
|
||||
*/
|
||||
while
|
||||
(
|
||||
( c != EOF ) &&
|
||||
( b < buf + sizeof( buf ) ) &&
|
||||
( inquote || !isspace( c ) )
|
||||
)
|
||||
{
|
||||
if ( c == '"' )
|
||||
{
|
||||
/* begin or end " */
|
||||
inquote = !inquote;
|
||||
notkeyword = 1;
|
||||
}
|
||||
else if ( c != '\\' )
|
||||
{
|
||||
/* normal char */
|
||||
*b++ = c;
|
||||
}
|
||||
else if ( ( c = yychar() ) != EOF )
|
||||
{
|
||||
/* \c */
|
||||
if (c == 'n')
|
||||
c = '\n';
|
||||
else if (c == 'r')
|
||||
c = '\r';
|
||||
*b++ = c;
|
||||
notkeyword = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* \EOF */
|
||||
break;
|
||||
}
|
||||
|
||||
while(
|
||||
c != EOF &&
|
||||
b < buf + sizeof( buf ) &&
|
||||
( inquote || !isspace( c ) ) )
|
||||
{
|
||||
if( c == '"' )
|
||||
{
|
||||
/* begin or end " */
|
||||
inquote = !inquote;
|
||||
notkeyword = 1;
|
||||
}
|
||||
else if( c != '\\' )
|
||||
{
|
||||
/* normal char */
|
||||
*b++ = c;
|
||||
}
|
||||
else if( ( c = yychar()) != EOF )
|
||||
{
|
||||
/* \c */
|
||||
*b++ = c;
|
||||
notkeyword = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* \EOF */
|
||||
break;
|
||||
}
|
||||
c = yychar();
|
||||
}
|
||||
|
||||
c = yychar();
|
||||
}
|
||||
/* Check obvious errors. */
|
||||
if ( b == buf + sizeof( buf ) )
|
||||
{
|
||||
yyerror( "string too big" );
|
||||
goto eof;
|
||||
}
|
||||
|
||||
/* Check obvious errors. */
|
||||
if ( inquote )
|
||||
{
|
||||
yyerror( "unmatched \" in string" );
|
||||
goto eof;
|
||||
}
|
||||
|
||||
if( b == buf + sizeof( buf ) )
|
||||
{
|
||||
yyerror( "string too big" );
|
||||
goto eof;
|
||||
}
|
||||
/* We looked ahead a character - back up. */
|
||||
if ( c != EOF )
|
||||
yyprev();
|
||||
|
||||
if( inquote )
|
||||
{
|
||||
yyerror( "unmatched \" in string" );
|
||||
goto eof;
|
||||
}
|
||||
/* Scan token table. Do not scan if it is obviously not a keyword or if
|
||||
* it is an alphabetic when were looking for punctuation.
|
||||
*/
|
||||
|
||||
/* We looked ahead a character - back up. */
|
||||
*b = 0;
|
||||
yylval.type = ARG;
|
||||
|
||||
if( c != EOF )
|
||||
yyprev();
|
||||
if ( !notkeyword && !( 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;
|
||||
}
|
||||
|
||||
/* scan token table */
|
||||
/* don't scan if it's obviously not a keyword or if its */
|
||||
/* an alphabetic when were looking for punctuation */
|
||||
if ( yylval.type == ARG )
|
||||
yylval.string = newstr( buf );
|
||||
}
|
||||
|
||||
*b = 0;
|
||||
yylval.type = ARG;
|
||||
if ( DEBUG_SCAN )
|
||||
printf( "scan %s\n", symdump( &yylval ) );
|
||||
|
||||
if( !notkeyword && !( 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;
|
||||
return yylval.type;
|
||||
|
||||
eof:
|
||||
yylval.file = "end-of-input"; /* just in case */
|
||||
yylval.line = 0;
|
||||
|
||||
yylval.type = EOF;
|
||||
return yylval.type;
|
||||
/* We do not reset yylval.file & yylval.line here so unexpected EOF error
|
||||
* messages would include correct error location information.
|
||||
*/
|
||||
yylval.type = EOF;
|
||||
return yylval.type;
|
||||
}
|
||||
|
||||
static char *
|
||||
symdump( YYSTYPE *s )
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Get information about the current file and line, for those epsilon
|
||||
* transitions that produce a parse
|
||||
|
||||
/*
|
||||
* Get information about the current file and line, for those epsilon
|
||||
* transitions that produce a parse.
|
||||
*/
|
||||
void yyinput_stream( char** name, int* line )
|
||||
|
||||
void yyinput_stream( char * * name, int * line )
|
||||
{
|
||||
if (incp)
|
||||
if ( incp )
|
||||
{
|
||||
*name = incp->fname;
|
||||
*line = incp->line;
|
||||
|
||||
@@ -9,47 +9,48 @@
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
#define YYSTYPE YYSYMBOL
|
||||
|
||||
typedef struct _YYSTYPE {
|
||||
typedef struct _YYSTYPE
|
||||
{
|
||||
int type;
|
||||
char *string;
|
||||
PARSE *parse;
|
||||
LIST *list;
|
||||
char * string;
|
||||
PARSE * parse;
|
||||
LIST * list;
|
||||
int number;
|
||||
char *file;
|
||||
char * file;
|
||||
int line;
|
||||
} YYSTYPE;
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
void yymode( int n );
|
||||
void yyerror( char *s );
|
||||
void yyerror( char * s );
|
||||
int yyanyerrors();
|
||||
void yyfparse( char *s );
|
||||
void yyfparse( char * s );
|
||||
int yyline();
|
||||
int yylex();
|
||||
int yyparse();
|
||||
void yyinput_stream( char** name, int* line );
|
||||
void yyinput_stream( char * * name, int * line );
|
||||
|
||||
# define SCAN_NORMAL 0 /* normal parsing */
|
||||
# define SCAN_STRING 1 /* look only for matching } */
|
||||
# define SCAN_PUNCT 2 /* only punctuation keywords */
|
||||
# define SCAN_NORMAL 0 /* normal parsing */
|
||||
# define SCAN_STRING 1 /* look only for matching } */
|
||||
# define SCAN_PUNCT 2 /* only punctuation keywords */
|
||||
|
||||
@@ -10,74 +10,82 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
# include "jam.h"
|
||||
# include "lists.h"
|
||||
# include "search.h"
|
||||
# include "timestamp.h"
|
||||
# include "pathsys.h"
|
||||
# include "variable.h"
|
||||
# include "newstr.h"
|
||||
# include "compile.h"
|
||||
# include "strings.h"
|
||||
# include "hash.h"
|
||||
# include <string.h>
|
||||
#include "jam.h"
|
||||
#include "lists.h"
|
||||
#include "search.h"
|
||||
#include "timestamp.h"
|
||||
#include "pathsys.h"
|
||||
#include "variable.h"
|
||||
#include "newstr.h"
|
||||
#include "compile.h"
|
||||
#include "strings.h"
|
||||
#include "hash.h"
|
||||
#include "filesys.h"
|
||||
#include <string.h>
|
||||
|
||||
typedef struct _binding {
|
||||
char* binding;
|
||||
char* target;
|
||||
|
||||
typedef struct _binding
|
||||
{
|
||||
char * binding;
|
||||
char * target;
|
||||
} BINDING;
|
||||
|
||||
static struct hash *explicit_bindings = 0;
|
||||
|
||||
void call_bind_rule(
|
||||
char* target_,
|
||||
char* boundname_ )
|
||||
|
||||
void call_bind_rule
|
||||
(
|
||||
char * target_,
|
||||
char * boundname_
|
||||
)
|
||||
{
|
||||
LIST* bind_rule = var_get( "BINDRULE" );
|
||||
if( bind_rule )
|
||||
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 )
|
||||
/* No guarantee that the target is an allocated string, so be on the
|
||||
* safe side.
|
||||
*/
|
||||
char * target = copystr( target_ );
|
||||
|
||||
/* Likewise, do not rely on implementation details of newstr.c: allocate
|
||||
* a copy of boundname.
|
||||
*/
|
||||
char * boundname = copystr( boundname_ );
|
||||
if ( boundname && target )
|
||||
{
|
||||
/* Prepare the argument list */
|
||||
/* Prepare the argument list. */
|
||||
FRAME frame[1];
|
||||
frame_init( frame );
|
||||
|
||||
/* First argument is the target name */
|
||||
|
||||
/* 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 ) )
|
||||
if ( lol_get( frame->args, 1 ) )
|
||||
evaluate_rule( bind_rule->string, frame );
|
||||
|
||||
|
||||
/* Clean up */
|
||||
frame_free( frame );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( boundname )
|
||||
if ( boundname )
|
||||
freestr( boundname );
|
||||
if( target )
|
||||
if ( target )
|
||||
freestr( target );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* search.c - find a target along $(SEARCH) or $(LOCATE)
|
||||
* search.c - find a target along $(SEARCH) or $(LOCATE)
|
||||
* First, check if LOCATE is set. If so, use it to determine
|
||||
* the location of target and return, regardless of whether anything
|
||||
* exists on that location.
|
||||
*
|
||||
* Second, examine all directories in SEARCH. If there's file already
|
||||
* or there's another target with the same name which was placed
|
||||
* to this location via LOCATE setting, stop and return the location.
|
||||
* to this location via LOCATE setting, stop and return the location.
|
||||
* In case of previous target, return it's name via the third argument.
|
||||
*
|
||||
* This bevahiour allow to handle dependency on generated files. If
|
||||
@@ -86,13 +94,14 @@ void call_bind_rule(
|
||||
*/
|
||||
|
||||
char *
|
||||
search(
|
||||
search(
|
||||
char *target,
|
||||
time_t *time,
|
||||
char **another_target
|
||||
char **another_target,
|
||||
int file
|
||||
)
|
||||
{
|
||||
PATHNAME f[1];
|
||||
PATHNAME f[1];
|
||||
LIST *varlist;
|
||||
string buf[1];
|
||||
int found = 0;
|
||||
@@ -100,29 +109,29 @@ search(
|
||||
int explicitly_located = 0;
|
||||
char *boundname = 0;
|
||||
|
||||
if( another_target )
|
||||
if ( another_target )
|
||||
*another_target = 0;
|
||||
|
||||
if (! explicit_bindings )
|
||||
explicit_bindings = hashinit( sizeof(BINDING),
|
||||
explicit_bindings = hashinit( sizeof(BINDING),
|
||||
"explicitly specified locations");
|
||||
|
||||
string_new( buf );
|
||||
/* Parse the filename */
|
||||
|
||||
path_parse( target, f );
|
||||
path_parse( target, f );
|
||||
|
||||
f->f_grist.ptr = 0;
|
||||
f->f_grist.len = 0;
|
||||
|
||||
if( varlist = var_get( "LOCATE" ) )
|
||||
if ( ( varlist = var_get( "LOCATE" ) ) )
|
||||
{
|
||||
f->f_root.ptr = varlist->string;
|
||||
f->f_root.len = strlen( varlist->string );
|
||||
|
||||
path_build( f, buf, 1 );
|
||||
path_build( f, buf, 1 );
|
||||
|
||||
if( DEBUG_SEARCH )
|
||||
if ( DEBUG_SEARCH )
|
||||
printf( "locate %s: %s\n", target, buf->value );
|
||||
|
||||
explicitly_located = 1;
|
||||
@@ -130,11 +139,12 @@ search(
|
||||
timestamp( buf->value, time );
|
||||
found = 1;
|
||||
}
|
||||
else if( varlist = var_get( "SEARCH" ) )
|
||||
else if ( ( varlist = var_get( "SEARCH" ) ) )
|
||||
{
|
||||
while( varlist )
|
||||
while ( varlist )
|
||||
{
|
||||
BINDING b, *ba = &b;
|
||||
file_info_t *ff;
|
||||
|
||||
f->f_root.ptr = varlist->string;
|
||||
f->f_root.len = strlen( varlist->string );
|
||||
@@ -142,34 +152,38 @@ search(
|
||||
string_truncate( buf, 0 );
|
||||
path_build( f, buf, 1 );
|
||||
|
||||
if( DEBUG_SEARCH )
|
||||
if ( DEBUG_SEARCH )
|
||||
printf( "search %s: %s\n", target, buf->value );
|
||||
|
||||
ff = file_query(buf->value);
|
||||
timestamp( buf->value, time );
|
||||
|
||||
b.binding = buf->value;
|
||||
|
||||
if( hashcheck( explicit_bindings, (HASHDATA**)&ba ) )
|
||||
|
||||
if ( hashcheck( explicit_bindings, (HASHDATA**)&ba ) )
|
||||
{
|
||||
if( DEBUG_SEARCH )
|
||||
printf(" search %s: found explicitly located target %s\n",
|
||||
if ( DEBUG_SEARCH )
|
||||
printf(" search %s: found explicitly located target %s\n",
|
||||
target, ba->target);
|
||||
if( another_target )
|
||||
if ( another_target )
|
||||
*another_target = ba->target;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
else if( *time )
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
else if ( ff && ff->time )
|
||||
{
|
||||
if ( !file || ff->is_file )
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
varlist = list_next( varlist );
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
if ( !found )
|
||||
{
|
||||
/* Look for the obvious */
|
||||
/* This is a questionable move. Should we look in the */
|
||||
@@ -181,7 +195,7 @@ search(
|
||||
string_truncate( buf, 0 );
|
||||
path_build( f, buf, 1 );
|
||||
|
||||
if( DEBUG_SEARCH )
|
||||
if ( DEBUG_SEARCH )
|
||||
printf( "search %s: %s\n", target, buf->value );
|
||||
|
||||
timestamp( buf->value, time );
|
||||
@@ -190,17 +204,18 @@ search(
|
||||
boundname = newstr( buf->value );
|
||||
string_free( buf );
|
||||
|
||||
if (explicitly_located)
|
||||
if ( explicitly_located )
|
||||
{
|
||||
BINDING b, *ba = &b;
|
||||
BINDING b;
|
||||
BINDING * ba = &b;
|
||||
b.binding = boundname;
|
||||
b.target = target;
|
||||
/* CONSIDER: we probably should issue a warning is another file
|
||||
is explicitly bound to the same location. This might break
|
||||
compatibility, though. */
|
||||
hashenter(explicit_bindings, (HASHDATA**)&ba);
|
||||
hashenter( explicit_bindings, (HASHDATA * *)&ba );
|
||||
}
|
||||
|
||||
|
||||
/* prepare a call to BINDRULE if the variable is set */
|
||||
call_bind_rule( target, boundname );
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* search.h - find a target along $(SEARCH) or $(LOCATE)
|
||||
* search.h - find a target along $(SEARCH) or $(LOCATE)
|
||||
*/
|
||||
|
||||
char *search( char *target, time_t *time, char **another_target );
|
||||
char *search( char *target, time_t *time, char **another_target, int file );
|
||||
|
||||
@@ -24,7 +24,7 @@ static void assert_invariants( string* self )
|
||||
assert( self->opt[0] == 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
assert( self->size < self->capacity );
|
||||
assert( ( self->capacity <= sizeof(self->opt) ) == ( self->value == self->opt ) );
|
||||
assert( strlen( self->value ) == self->size );
|
||||
@@ -106,10 +106,10 @@ void string_append( string* self, char const* 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;
|
||||
@@ -127,10 +127,10 @@ void string_append_range( string* self, char const* start, char const* 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;
|
||||
@@ -182,7 +182,7 @@ void string_unit_test()
|
||||
int limit = sizeof(buffer) > 254 ? 254 : sizeof(buffer);
|
||||
|
||||
string_new(s);
|
||||
|
||||
|
||||
for (i = 0; i < limit; ++i)
|
||||
{
|
||||
string_push_back( s, (char)(i + 1) );
|
||||
@@ -195,7 +195,7 @@ void string_unit_test()
|
||||
}
|
||||
|
||||
string_free(s);
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -22,13 +22,13 @@ 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;
|
||||
}
|
||||
|
||||
@@ -36,13 +36,13 @@ 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 );
|
||||
@@ -50,7 +50,7 @@ builtin_subst(
|
||||
if ( regexec( repat, (char*)source) )
|
||||
{
|
||||
LIST* subst = list_next(arg1);
|
||||
|
||||
|
||||
while ((subst = list_next(subst)) != L0)
|
||||
{
|
||||
# define BUFLEN 4096
|
||||
@@ -88,7 +88,7 @@ builtin_subst(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,201 +32,195 @@
|
||||
typedef struct _binding BINDING;
|
||||
|
||||
struct _binding {
|
||||
char *name;
|
||||
short flags;
|
||||
char *name;
|
||||
short flags;
|
||||
|
||||
# define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
|
||||
# define BIND_SCANNED 0x01 /* if directory or arch, has been scanned */
|
||||
|
||||
short progress;
|
||||
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 */
|
||||
# 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 */
|
||||
} ;
|
||||
time_t time; /* update time - 0 if not exist */
|
||||
};
|
||||
|
||||
static struct hash *bindhash = 0;
|
||||
static void time_enter( void *, char *, int , time_t );
|
||||
static struct hash * bindhash = 0;
|
||||
static void time_enter( void *, char *, int, time_t );
|
||||
|
||||
static char *time_progress[] =
|
||||
static char * time_progress[] =
|
||||
{
|
||||
"INIT",
|
||||
"NOENTRY",
|
||||
"SPOTTED",
|
||||
"MISSING",
|
||||
"FOUND"
|
||||
} ;
|
||||
"INIT",
|
||||
"NOENTRY",
|
||||
"SPOTTED",
|
||||
"MISSING",
|
||||
"FOUND"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* timestamp() - return timestamp on a file, if present
|
||||
* timestamp() - return timestamp on a file, if present.
|
||||
*/
|
||||
|
||||
void
|
||||
timestamp(
|
||||
char *target,
|
||||
time_t *time )
|
||||
void timestamp( char * target, time_t * time )
|
||||
{
|
||||
PROFILE_ENTER(timestamp);
|
||||
|
||||
PATHNAME f1, f2;
|
||||
BINDING binding, *b = &binding;
|
||||
string buf[1];
|
||||
string path;
|
||||
char *p;
|
||||
PROFILE_ENTER( timestamp );
|
||||
|
||||
# ifdef DOWNSHIFT_PATHS
|
||||
PATHNAME f1;
|
||||
PATHNAME f2;
|
||||
BINDING binding;
|
||||
BINDING * b = &binding;
|
||||
string buf[ 1 ];
|
||||
#ifdef DOWNSHIFT_PATHS
|
||||
string path;
|
||||
char * p;
|
||||
#endif
|
||||
|
||||
string_copy( &path, target );
|
||||
p = path.value;
|
||||
#ifdef DOWNSHIFT_PATHS
|
||||
string_copy( &path, target );
|
||||
p = path.value;
|
||||
|
||||
do
|
||||
do
|
||||
{
|
||||
*p = tolower( *p );
|
||||
# ifdef NT
|
||||
/* On NT, we must use backslashes or the file won't be found. */
|
||||
if (*p == '/')
|
||||
#ifdef NT
|
||||
/* On NT, we must use backslashes or the file will not be found. */
|
||||
if ( *p == '/' )
|
||||
*p = PATH_DELIM;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
while( *p++ );
|
||||
while ( *p++ );
|
||||
|
||||
target = path.value;
|
||||
# endif
|
||||
string_new( buf );
|
||||
target = path.value;
|
||||
#endif /* #ifdef DOWNSHIFT_PATHS */
|
||||
string_new( buf );
|
||||
|
||||
if( !bindhash )
|
||||
bindhash = hashinit( sizeof( BINDING ), "bindings" );
|
||||
if ( !bindhash )
|
||||
bindhash = hashinit( sizeof( BINDING ), "bindings" );
|
||||
|
||||
/* Quick path - is it there? */
|
||||
/* Quick path - is it there? */
|
||||
b->name = target;
|
||||
b->time = b->flags = 0;
|
||||
b->progress = BIND_INIT;
|
||||
|
||||
b->name = target;
|
||||
b->time = b->flags = 0;
|
||||
b->progress = BIND_INIT;
|
||||
if ( hashenter( bindhash, (HASHDATA * *)&b ) )
|
||||
b->name = newstr( target ); /* never freed */
|
||||
|
||||
if( hashenter( bindhash, (HASHDATA **)&b ) )
|
||||
b->name = newstr( target ); /* never freed */
|
||||
if ( b->progress != BIND_INIT )
|
||||
goto afterscanning;
|
||||
|
||||
if( b->progress != BIND_INIT )
|
||||
goto afterscanning;
|
||||
b->progress = BIND_NOENTRY;
|
||||
|
||||
b->progress = BIND_NOENTRY;
|
||||
/* Not found - have to scan for it. */
|
||||
path_parse( target, &f1 );
|
||||
|
||||
/* Not found - have to scan for it */
|
||||
/* Scan directory if not already done so. */
|
||||
{
|
||||
BINDING binding;
|
||||
BINDING * b = &binding;
|
||||
|
||||
path_parse( target, &f1 );
|
||||
f2 = f1;
|
||||
f2.f_grist.len = 0;
|
||||
path_parent( &f2 );
|
||||
path_build( &f2, buf, 0 );
|
||||
|
||||
/* Scan directory if not already done so */
|
||||
b->name = buf->value;
|
||||
b->time = b->flags = 0;
|
||||
b->progress = BIND_INIT;
|
||||
|
||||
{
|
||||
BINDING binding, *b = &binding;
|
||||
if ( hashenter( bindhash, (HASHDATA * *)&b ) )
|
||||
b->name = newstr( buf->value ); /* never freed */
|
||||
|
||||
f2 = f1;
|
||||
f2.f_grist.len = 0;
|
||||
path_parent( &f2 );
|
||||
path_build( &f2, buf, 0 );
|
||||
if ( !( b->flags & BIND_SCANNED ) )
|
||||
{
|
||||
file_dirscan( buf->value, time_enter, bindhash );
|
||||
b->flags |= BIND_SCANNED;
|
||||
}
|
||||
}
|
||||
|
||||
b->name = buf->value;
|
||||
b->time = b->flags = 0;
|
||||
b->progress = BIND_INIT;
|
||||
/* Scan archive if not already done so. */
|
||||
if ( f1.f_member.len )
|
||||
{
|
||||
BINDING binding;
|
||||
BINDING * b = &binding;
|
||||
|
||||
if( hashenter( bindhash, (HASHDATA **)&b ) )
|
||||
b->name = newstr( buf->value ); /* never freed */
|
||||
f2 = f1;
|
||||
f2.f_grist.len = 0;
|
||||
f2.f_member.len = 0;
|
||||
string_truncate( buf, 0 );
|
||||
path_build( &f2, buf, 0 );
|
||||
|
||||
if( !( b->flags & BIND_SCANNED ) )
|
||||
{
|
||||
file_dirscan( buf->value, time_enter, bindhash );
|
||||
b->flags |= BIND_SCANNED;
|
||||
}
|
||||
}
|
||||
b->name = buf->value;
|
||||
b->time = b->flags = 0;
|
||||
b->progress = BIND_INIT;
|
||||
|
||||
/* Scan archive if not already done so */
|
||||
if ( hashenter( bindhash, (HASHDATA * *)&b ) )
|
||||
b->name = newstr( buf->value ); /* never freed */
|
||||
|
||||
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 );
|
||||
path_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, bindhash );
|
||||
b->flags |= BIND_SCANNED;
|
||||
}
|
||||
}
|
||||
if ( !( b->flags & BIND_SCANNED ) )
|
||||
{
|
||||
file_archscan( buf->value, time_enter, bindhash );
|
||||
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;
|
||||
}
|
||||
if ( b->progress == BIND_SPOTTED )
|
||||
{
|
||||
b->progress = file_time( b->name, &b->time ) < 0
|
||||
? BIND_MISSING
|
||||
: BIND_FOUND;
|
||||
}
|
||||
|
||||
*time = b->progress == BIND_FOUND ? b->time : 0;
|
||||
*time = b->progress == BIND_FOUND ? b->time : 0;
|
||||
string_free( buf );
|
||||
# ifdef DOWNSHIFT_PATHS
|
||||
string_free( &path );
|
||||
#ifdef DOWNSHIFT_PATHS
|
||||
string_free( &path );
|
||||
#endif
|
||||
|
||||
PROFILE_EXIT(timestamp);
|
||||
|
||||
PROFILE_EXIT( timestamp );
|
||||
}
|
||||
|
||||
static void
|
||||
time_enter(
|
||||
void *closure,
|
||||
char *target,
|
||||
int found,
|
||||
time_t time )
|
||||
|
||||
static void time_enter( void * closure, char * target, int found, time_t time )
|
||||
{
|
||||
BINDING binding, *b = &binding;
|
||||
struct hash *bindhash = (struct hash *)closure;
|
||||
BINDING binding;
|
||||
BINDING * b = &binding;
|
||||
struct hash * bindhash = (struct hash *)closure;
|
||||
|
||||
# ifdef DOWNSHIFT_PATHS
|
||||
char path[ MAXJPATH ];
|
||||
char *p = path;
|
||||
#ifdef DOWNSHIFT_PATHS
|
||||
char path[ MAXJPATH ];
|
||||
char * p = path;
|
||||
|
||||
do *p++ = tolower( *target );
|
||||
while( *target++ );
|
||||
do *p++ = tolower( *target );
|
||||
while ( *target++ );
|
||||
|
||||
target = path;
|
||||
# endif
|
||||
target = path;
|
||||
#endif
|
||||
|
||||
b->name = target;
|
||||
b->flags = 0;
|
||||
b->name = target;
|
||||
b->flags = 0;
|
||||
|
||||
if( hashenter( bindhash, (HASHDATA **)&b ) )
|
||||
b->name = newstr( target ); /* never freed */
|
||||
if ( hashenter( bindhash, (HASHDATA * *)&b ) )
|
||||
b->name = newstr( target ); /* never freed */
|
||||
|
||||
b->time = time;
|
||||
b->progress = found ? BIND_FOUND : BIND_SPOTTED;
|
||||
b->time = time;
|
||||
b->progress = found ? BIND_FOUND : BIND_SPOTTED;
|
||||
|
||||
if( DEBUG_BINDSCAN )
|
||||
printf( "time ( %s ) : %s\n", target, time_progress[b->progress] );
|
||||
if ( DEBUG_BINDSCAN )
|
||||
printf( "time ( %s ) : %s\n", target, time_progress[ b->progress ] );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* donestamps() - free timestamp tables
|
||||
* stamps_done() - free timestamp tables.
|
||||
*/
|
||||
|
||||
void
|
||||
donestamps()
|
||||
void stamps_done()
|
||||
{
|
||||
hashdone( bindhash );
|
||||
hashdone( bindhash );
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@
|
||||
* timestamp.h - get the timestamp of a file or archive member
|
||||
*/
|
||||
|
||||
void timestamp( char *target, time_t *time );
|
||||
void donestamps();
|
||||
void timestamp( char * target, time_t * time );
|
||||
void stamps_done();
|
||||
|
||||
@@ -12,35 +12,35 @@
|
||||
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
|
||||
*/
|
||||
|
||||
# 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"
|
||||
# include "pathsys.h"
|
||||
# include <stdlib.h>
|
||||
# include <stdio.h>
|
||||
#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"
|
||||
#include "pathsys.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* variable.c - handle jam multi-element variables
|
||||
* 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
|
||||
* 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
|
||||
* 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)
|
||||
@@ -57,28 +57,30 @@ static struct hash *varhash = 0;
|
||||
|
||||
typedef struct _variable VARIABLE ;
|
||||
|
||||
struct _variable {
|
||||
char *symbol;
|
||||
LIST *value;
|
||||
} ;
|
||||
struct _variable
|
||||
{
|
||||
char * symbol;
|
||||
LIST * value;
|
||||
};
|
||||
|
||||
static VARIABLE *var_enter( char *symbol );
|
||||
static void var_dump( char *symbol, LIST *value, char *what );
|
||||
static VARIABLE * var_enter( char * symbol );
|
||||
static void var_dump( char * symbol, LIST * value, char * what );
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* var_hash_swap() - swap all variable settings with those passed
|
||||
*
|
||||
* Used to implement separate settings spaces for modules
|
||||
*/
|
||||
void var_hash_swap( struct hash** new_vars )
|
||||
|
||||
void var_hash_swap( struct hash * * new_vars )
|
||||
{
|
||||
struct hash* old = varhash;
|
||||
struct hash * old = varhash;
|
||||
varhash = *new_vars;
|
||||
*new_vars = old;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* var_defines() - load a bunch of variable=value settings
|
||||
*
|
||||
@@ -92,224 +94,214 @@ void var_hash_swap( struct hash** new_vars )
|
||||
* Otherwise, split the value at blanks.
|
||||
*/
|
||||
|
||||
void
|
||||
var_defines( char *const* e, int preprocess )
|
||||
void var_defines( char * const * e, int preprocess )
|
||||
{
|
||||
string buf[1];
|
||||
|
||||
string_new( buf );
|
||||
|
||||
for( ; *e; e++ )
|
||||
{
|
||||
char *val;
|
||||
for ( ; *e; ++e )
|
||||
{
|
||||
char * val;
|
||||
|
||||
# ifdef OS_MAC
|
||||
/* On the mac (MPW), the var=val is actually var\0val */
|
||||
/* Think different. */
|
||||
|
||||
if( ( val = strchr( *e, '=' ) ) || ( val = *e + strlen( *e ) ) )
|
||||
/* 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, '=' ) )
|
||||
if ( ( val = strchr( *e, '=' ) ) )
|
||||
# endif
|
||||
{
|
||||
LIST *l = L0;
|
||||
char *pp, *p;
|
||||
{
|
||||
LIST * l = L0;
|
||||
char * pp;
|
||||
char * p;
|
||||
# ifdef OPT_NO_EXTERNAL_VARIABLE_SPLIT
|
||||
char split = '\0';
|
||||
char split = '\0';
|
||||
# else
|
||||
# ifdef OS_MAC
|
||||
char split = ',';
|
||||
# else
|
||||
char split = ' ';
|
||||
# ifdef OS_MAC
|
||||
char split = ',';
|
||||
# else
|
||||
char split = ' ';
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
size_t len = strlen(val + 1);
|
||||
size_t len = strlen( val + 1 );
|
||||
|
||||
int quoted = val[1] == '"' && val[len] == '"' && len > 1;
|
||||
|
||||
if ( quoted && preprocess )
|
||||
int quoted = ( val[1] == '"' ) && ( val[len] == '"' ) &&
|
||||
( len > 1 );
|
||||
|
||||
if ( quoted && preprocess )
|
||||
{
|
||||
string_append_range( buf, val + 2, val + len );
|
||||
l = list_new( l, newstr( buf->value ) );
|
||||
string_truncate( buf, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Split *PATH at :'s, not spaces. */
|
||||
if ( val - 4 >= *e )
|
||||
{
|
||||
string_append_range( buf, val + 2, val + len );
|
||||
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;
|
||||
preprocess && ( ( p = strchr( pp, split ) ) != 0 );
|
||||
pp = p + 1
|
||||
)
|
||||
{
|
||||
string_append_range( buf, pp, p );
|
||||
l = list_new( l, newstr( buf->value ) );
|
||||
string_truncate( buf, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
l = list_new( l, newstr( pp ) );
|
||||
}
|
||||
|
||||
/* Do the split */
|
||||
|
||||
for(
|
||||
pp = val + 1;
|
||||
preprocess && (p = strchr( pp, split )) != 0;
|
||||
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 );
|
||||
/* 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 )
|
||||
int var_string( char * in, char * out, int outsize, LOL * lol )
|
||||
{
|
||||
char *out0 = out;
|
||||
char *oute = out + outsize - 1;
|
||||
char * out0 = out;
|
||||
char * oute = out + outsize - 1;
|
||||
|
||||
while( *in )
|
||||
while ( *in )
|
||||
{
|
||||
char *lastword;
|
||||
int dollar = 0;
|
||||
char * lastword;
|
||||
int dollar = 0;
|
||||
|
||||
/* Copy white space */
|
||||
|
||||
while( isspace( *in ) )
|
||||
/* Copy white space. */
|
||||
while ( isspace( *in ) )
|
||||
{
|
||||
if( out >= oute )
|
||||
if ( out >= oute )
|
||||
return -1;
|
||||
|
||||
*out++ = *in++;
|
||||
}
|
||||
|
||||
lastword = out;
|
||||
|
||||
/* Copy non-white space, watching for variables */
|
||||
|
||||
while( *in && !isspace( *in ) )
|
||||
/* Copy non-white space, watching for variables. */
|
||||
while ( *in && !isspace( *in ) )
|
||||
{
|
||||
if( out >= oute )
|
||||
if ( out >= oute )
|
||||
return -1;
|
||||
|
||||
if( in[0] == '$' && in[1] == '(' )
|
||||
if ( ( in[ 0 ] == '$' ) && ( in[ 1 ] == '(' ) )
|
||||
{
|
||||
dollar++;
|
||||
++dollar;
|
||||
*out++ = *in++;
|
||||
}
|
||||
#ifdef OPT_AT_FILES
|
||||
else if ( in[0] == '@' && in[1] == '(' )
|
||||
else if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) )
|
||||
{
|
||||
int depth = 1;
|
||||
char *ine = in + 2;
|
||||
char *split = 0;
|
||||
|
||||
char * ine = in + 2;
|
||||
char * split = 0;
|
||||
|
||||
/* Scan the content of the response file @() section. */
|
||||
|
||||
while( *ine && depth > 0 )
|
||||
while ( *ine && ( depth > 0 ) )
|
||||
{
|
||||
switch( *ine )
|
||||
switch ( *ine )
|
||||
{
|
||||
case '(':
|
||||
++depth;
|
||||
break;
|
||||
case ')':
|
||||
--depth;
|
||||
break;
|
||||
case '(': ++depth; break;
|
||||
case ')': --depth; break;
|
||||
case ':':
|
||||
if( depth == 1 && ine[1] == 'E' && ine[2] == '=' )
|
||||
{
|
||||
if ( ( depth == 1 ) && ( ine[ 1 ] == 'E' ) && ( ine[ 2 ] == '=' ) )
|
||||
split = ine;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++ine;
|
||||
}
|
||||
|
||||
if (!split)
|
||||
|
||||
if ( !split )
|
||||
{
|
||||
/* the @() reference doesn't match the @(foo:E=bar) format.
|
||||
hence we leave it alone by copying directly to output. */
|
||||
int l = 0;
|
||||
if ( out+2 >= oute ) return -1;
|
||||
*(out++) = '@';
|
||||
*(out++) = '(';
|
||||
l = var_string(in+2,out,oute-out,lol);
|
||||
if ( out + 2 >= oute ) return -1;
|
||||
*( out++ ) = '@';
|
||||
*( out++ ) = '(';
|
||||
l = var_string( in + 2, out, oute - out, lol );
|
||||
if ( l < 0 ) return -1;
|
||||
out += l;
|
||||
if ( out+1 >= oute ) return -1;
|
||||
*(out++) = ')';
|
||||
if ( out + 1 >= oute ) return -1;
|
||||
*( out++ ) = ')';
|
||||
}
|
||||
|
||||
else if ( depth == 0 )
|
||||
{
|
||||
string file_name_v;
|
||||
int file_name_l = 0;
|
||||
const char * file_name_s = 0;
|
||||
|
||||
/* expand the temporary file name var inline */
|
||||
|
||||
/* Expand the temporary file name var inline. */
|
||||
#if 0
|
||||
string_copy(&file_name_v,"$(");
|
||||
string_append_range(&file_name_v,in+2,split);
|
||||
string_push_back(&file_name_v,')');
|
||||
string_copy( &file_name_v, "$(" );
|
||||
string_append_range( &file_name_v, in + 2, split );
|
||||
string_push_back( &file_name_v, ')' );
|
||||
#else
|
||||
string_new(&file_name_v);
|
||||
string_append_range(&file_name_v,in+2,split);
|
||||
string_new( &file_name_v );
|
||||
string_append_range( &file_name_v, in + 2, split );
|
||||
#endif
|
||||
file_name_l = var_string(file_name_v.value,out,oute-out+1,lol);
|
||||
string_free(&file_name_v);
|
||||
file_name_l = var_string( file_name_v.value, out, oute - out + 1, lol );
|
||||
string_free( &file_name_v );
|
||||
if ( file_name_l < 0 ) return -1;
|
||||
file_name_s = out;
|
||||
|
||||
/* for stdout/stderr we will create a temp file and generate
|
||||
a command that outputs the content as needed. */
|
||||
if ( strcmp( "STDOUT", out ) == 0 || strcmp( "STDERR", out ) == 0 )
|
||||
|
||||
/* For stdout/stderr we will create a temp file and generate
|
||||
* a command that outputs the content as needed.
|
||||
*/
|
||||
if ( ( strcmp( "STDOUT", out ) == 0 ) ||
|
||||
( strcmp( "STDERR", out ) == 0 ) )
|
||||
{
|
||||
int err_redir = strcmp( "STDERR", out ) == 0;
|
||||
out[0] = '\0';
|
||||
out[ 0 ] = '\0';
|
||||
file_name_s = path_tmpfile();
|
||||
file_name_l = strlen(file_name_s);
|
||||
#ifdef OS_NT
|
||||
if ( (out+7+file_name_l+(err_redir?5:0)) >= oute ) return -1;
|
||||
sprintf( out,"type \"%s\"%s",
|
||||
file_name_s,
|
||||
if ( ( out + 7 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
|
||||
return -1;
|
||||
sprintf( out,"type \"%s\"%s", file_name_s,
|
||||
err_redir ? " 1>&2" : "" );
|
||||
#else
|
||||
if ( (out+6+file_name_l+(err_redir?5:0)) >= oute ) return -1;
|
||||
sprintf( out,"cat \"%s\"%s",
|
||||
file_name_s,
|
||||
if ( ( out + 6 + file_name_l + ( err_redir ? 5 : 0 ) ) >= oute )
|
||||
return -1;
|
||||
sprintf( out,"cat \"%s\"%s", file_name_s,
|
||||
err_redir ? " 1>&2" : "" );
|
||||
#endif
|
||||
/* we also make sure that the temp files created by this
|
||||
get nuked eventually. */
|
||||
/* We also make sure that the temp files created by this
|
||||
* get nuked eventually.
|
||||
*/
|
||||
file_remove_atexit( file_name_s );
|
||||
}
|
||||
|
||||
/* expand the file value into the file reference */
|
||||
var_string_to_file( split+3, ine-split-4, file_name_s, lol );
|
||||
|
||||
/* continue on with the expansion */
|
||||
out += strlen(out);
|
||||
|
||||
/* Expand the file value into the file reference. */
|
||||
var_string_to_file( split + 3, ine - split - 4, file_name_s,
|
||||
lol );
|
||||
|
||||
/* Continue on with the expansion. */
|
||||
out += strlen( out );
|
||||
}
|
||||
|
||||
/* and continue with the parsing just past the @() reference */
|
||||
|
||||
/* And continue with the parsing just past the @() reference. */
|
||||
in = ine;
|
||||
}
|
||||
#endif
|
||||
@@ -320,19 +312,17 @@ var_string(
|
||||
}
|
||||
|
||||
/* Add zero to 'out' so that 'lastword' is correctly zero-terminated. */
|
||||
if (out >= oute)
|
||||
if ( out >= oute )
|
||||
return -1;
|
||||
/* Don't increment, intentionally. */
|
||||
*out= '\0';
|
||||
|
||||
/* If a variable encountered, expand it and and embed the */
|
||||
/* space-separated members of the list in the output. */
|
||||
/* Do not increment, intentionally. */
|
||||
*out = '\0';
|
||||
|
||||
if( dollar )
|
||||
/* 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 );
|
||||
LIST * l = var_expand( L0, lastword, out, lol, 0 );
|
||||
|
||||
out = lastword;
|
||||
|
||||
@@ -340,8 +330,8 @@ var_string(
|
||||
{
|
||||
int so = strlen( l->string );
|
||||
|
||||
if( out + so >= oute )
|
||||
return -1;
|
||||
if ( out + so >= oute )
|
||||
return -1;
|
||||
|
||||
strcpy( out, l->string );
|
||||
out += so;
|
||||
@@ -353,7 +343,7 @@ var_string(
|
||||
}
|
||||
}
|
||||
|
||||
if( out >= oute )
|
||||
if ( out >= oute )
|
||||
return -1;
|
||||
|
||||
*out++ = '\0';
|
||||
@@ -361,9 +351,10 @@ var_string(
|
||||
return out - out0;
|
||||
}
|
||||
|
||||
|
||||
void var_string_to_file( const char * in, int insize, const char * out, LOL * lol )
|
||||
{
|
||||
const char * ine = in+insize;
|
||||
char const * ine = in + insize;
|
||||
FILE * out_file = 0;
|
||||
int out_debug = DEBUG_EXEC ? 1 : 0;
|
||||
if ( globs.noexec )
|
||||
@@ -382,64 +373,57 @@ void var_string_to_file( const char * in, int insize, const char * out, LOL * lo
|
||||
{
|
||||
/* Handle "path to file" filenames. */
|
||||
string out_name;
|
||||
if ( out[0] == '"' && out[strlen(out) - 1] == '"' )
|
||||
if ( ( out[ 0 ] == '"' ) && ( out[ strlen( out ) - 1 ] == '"' ) )
|
||||
{
|
||||
string_copy(&out_name,out+1);
|
||||
string_truncate(&out_name,out_name.size-1);
|
||||
string_copy( &out_name, out + 1 );
|
||||
string_truncate( &out_name, out_name.size - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
string_copy(&out_name,out);
|
||||
string_copy( &out_name,out );
|
||||
}
|
||||
out_file = fopen( out_name.value, "w" );
|
||||
if (!out_file)
|
||||
if ( !out_file )
|
||||
{
|
||||
printf( "failed to write output file '%s'!\n", out_name.value );
|
||||
exit( EXITBAD );
|
||||
}
|
||||
string_free(&out_name);
|
||||
string_free( &out_name );
|
||||
}
|
||||
|
||||
if ( out_debug ) printf("\nfile %s\n",out);
|
||||
if ( out_debug ) printf( "\nfile %s\n", out );
|
||||
|
||||
while( *in && in < ine )
|
||||
while ( *in && ( in < ine ) )
|
||||
{
|
||||
int dollar = 0;
|
||||
const char * output_0 = in;
|
||||
const char * output_1 = in;
|
||||
|
||||
/* Copy white space */
|
||||
|
||||
while ( output_1 < ine && *output_1 && isspace( *output_1 ) )
|
||||
{
|
||||
/* Copy white space. */
|
||||
while ( ( output_1 < ine ) && isspace( *output_1 ) )
|
||||
++output_1;
|
||||
}
|
||||
|
||||
if ( output_0 < output_1 )
|
||||
{
|
||||
if ( out_file ) fwrite(output_0,output_1-output_0,1,out_file);
|
||||
if ( out_debug ) fwrite(output_0,output_1-output_0,1,stdout);
|
||||
if ( out_file ) fwrite( output_0, output_1 - output_0, 1, out_file );
|
||||
if ( out_debug ) fwrite( output_0, output_1 - output_0, 1, stdout );
|
||||
}
|
||||
output_0 = output_1;
|
||||
|
||||
/* Copy non-white space, watching for variables */
|
||||
|
||||
while( output_1 < ine && *output_1 && !isspace( *output_1 ) )
|
||||
/* Copy non-white space, watching for variables. */
|
||||
while ( ( output_1 < ine ) && *output_1 && !isspace( *output_1 ) )
|
||||
{
|
||||
if( output_1[0] == '$' && output_1[1] && output_1[1] == '(' )
|
||||
{
|
||||
dollar++;
|
||||
}
|
||||
if ( ( output_1[ 0 ] == '$' ) && ( output_1[ 1 ] == '(' ) )
|
||||
++dollar;
|
||||
++output_1;
|
||||
}
|
||||
|
||||
/* If a variable encountered, expand it and embed the */
|
||||
/* space-separated members of the list in the output. */
|
||||
|
||||
if( dollar )
|
||||
/* If a variable encountered, expand it and embed the space-separated
|
||||
* members of the list in the output.
|
||||
*/
|
||||
if ( dollar )
|
||||
{
|
||||
LIST *l;
|
||||
|
||||
l = var_expand( L0, (char*)output_0, (char*)output_1, lol, 0 );
|
||||
LIST * l = var_expand( L0, (char *)output_0, (char *)output_1, lol, 0 );
|
||||
|
||||
while ( l )
|
||||
{
|
||||
@@ -457,45 +441,59 @@ void var_string_to_file( const char * in, int insize, const char * out, LOL * lo
|
||||
}
|
||||
else if ( output_0 < output_1 )
|
||||
{
|
||||
if ( out_file ) fwrite(output_0,output_1-output_0,1,out_file);
|
||||
if ( out_debug ) fwrite(output_0,output_1-output_0,1,stdout);
|
||||
if ( out_file )
|
||||
{
|
||||
const char * output_n = output_0;
|
||||
while ( output_n < output_1 )
|
||||
{
|
||||
output_n += fwrite( output_n, 1, output_1-output_n, out_file );
|
||||
}
|
||||
}
|
||||
if ( out_debug )
|
||||
{
|
||||
const char * output_n = output_0;
|
||||
while ( output_n < output_1 )
|
||||
{
|
||||
output_n += fwrite( output_n, 1, output_1-output_n, stdout );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
in = output_1;
|
||||
}
|
||||
|
||||
if ( out_file && out_file != stdout && out_file != stderr )
|
||||
if ( out_file && ( out_file != stdout ) && ( out_file != stderr ) )
|
||||
{
|
||||
fflush( out_file );
|
||||
fclose( out_file );
|
||||
}
|
||||
|
||||
if ( out_debug ) fputc('\n',stdout);
|
||||
if ( out_debug ) fputc( '\n', stdout );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* var_get() - get value of a user defined symbol
|
||||
* var_get() - get value of a user defined symbol.
|
||||
*
|
||||
* Returns NULL if symbol unset.
|
||||
*/
|
||||
|
||||
LIST *
|
||||
var_get( char *symbol )
|
||||
LIST * var_get( char * symbol )
|
||||
{
|
||||
LIST * result = 0;
|
||||
#ifdef OPT_AT_FILES
|
||||
#ifdef OPT_AT_FILES
|
||||
/* Some "fixed" variables... */
|
||||
if ( strcmp( "TMPDIR", symbol ) == 0 )
|
||||
{
|
||||
result = list_new( L0, newstr( (char*)path_tmpdir() ) );
|
||||
result = list_new( L0, newstr( (char *)path_tmpdir() ) );
|
||||
}
|
||||
else if ( strcmp( "TMPNAME", symbol ) == 0 )
|
||||
{
|
||||
result = list_new( L0, newstr( (char*)path_tmpnam() ) );
|
||||
result = list_new( L0, newstr( (char *)path_tmpnam() ) );
|
||||
}
|
||||
else if ( strcmp( "TMPFILE", symbol ) == 0 )
|
||||
{
|
||||
result = list_new( L0, newstr( (char*)path_tmpfile() ) );
|
||||
result = list_new( L0, newstr( (char *)path_tmpfile() ) );
|
||||
}
|
||||
else if ( strcmp( "STDOUT", symbol ) == 0 )
|
||||
{
|
||||
@@ -506,15 +504,16 @@ var_get( char *symbol )
|
||||
result = list_new( L0, newstr( "STDERR" ) );
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
VARIABLE var, *v = &var;
|
||||
|
||||
VARIABLE var;
|
||||
VARIABLE * v = &var;
|
||||
|
||||
v->symbol = symbol;
|
||||
|
||||
if( varhash && hashcheck( varhash, (HASHDATA **)&v ) )
|
||||
|
||||
if ( varhash && hashcheck( varhash, (HASHDATA * *)&v ) )
|
||||
{
|
||||
if( DEBUG_VARGET )
|
||||
if ( DEBUG_VARGET )
|
||||
var_dump( v->symbol, v->value, "get" );
|
||||
result = v->value;
|
||||
}
|
||||
@@ -522,122 +521,111 @@ var_get( char *symbol )
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* var_set() - set a variable in jam's user defined symbol table
|
||||
* 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.
|
||||
* '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.
|
||||
* Copies symbol. Takes ownership of value.
|
||||
*/
|
||||
|
||||
void
|
||||
var_set(
|
||||
char *symbol,
|
||||
LIST *value,
|
||||
int flag )
|
||||
void var_set( char * symbol, LIST * value, int flag )
|
||||
{
|
||||
VARIABLE *v = var_enter( symbol );
|
||||
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;
|
||||
if ( DEBUG_VARSET )
|
||||
var_dump( symbol, value, "set" );
|
||||
|
||||
case VAR_APPEND:
|
||||
/* Append value */
|
||||
v->value = list_append( v->value, value );
|
||||
break;
|
||||
switch ( flag )
|
||||
{
|
||||
case VAR_SET:
|
||||
/* Replace value */
|
||||
list_free( v->value );
|
||||
v->value = value;
|
||||
break;
|
||||
|
||||
case VAR_DEFAULT:
|
||||
/* Set only if unset */
|
||||
if( !v->value )
|
||||
v->value = value;
|
||||
else
|
||||
list_free( 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
|
||||
* var_swap() - swap a variable's value with the given one.
|
||||
*/
|
||||
|
||||
LIST *
|
||||
var_swap(
|
||||
char *symbol,
|
||||
LIST *value )
|
||||
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;
|
||||
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
|
||||
* var_enter() - make new var symbol table entry, returning var ptr.
|
||||
*/
|
||||
|
||||
static VARIABLE *
|
||||
var_enter( char *symbol )
|
||||
static VARIABLE * var_enter( char * symbol )
|
||||
{
|
||||
VARIABLE var, *v = &var;
|
||||
VARIABLE var;
|
||||
VARIABLE * v = &var;
|
||||
|
||||
if( !varhash )
|
||||
varhash = hashinit( sizeof( VARIABLE ), "variables" );
|
||||
if ( !varhash )
|
||||
varhash = hashinit( sizeof( VARIABLE ), "variables" );
|
||||
|
||||
v->symbol = symbol;
|
||||
v->value = 0;
|
||||
v->symbol = symbol;
|
||||
v->value = 0;
|
||||
|
||||
if( hashenter( varhash, (HASHDATA **)&v ) )
|
||||
v->symbol = newstr( symbol ); /* never freed */
|
||||
if ( hashenter( varhash, (HASHDATA * *)&v ) )
|
||||
v->symbol = newstr( symbol ); /* never freed */
|
||||
|
||||
return v;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* var_dump() - dump a variable to stdout
|
||||
* var_dump() - dump a variable to stdout.
|
||||
*/
|
||||
|
||||
static void
|
||||
var_dump(
|
||||
char *symbol,
|
||||
LIST *value,
|
||||
char *what )
|
||||
static void var_dump( char * symbol, LIST * value, char * what )
|
||||
{
|
||||
printf( "%s %s = ", what, symbol );
|
||||
list_print( value );
|
||||
printf( "\n" );
|
||||
printf( "%s %s = ", what, symbol );
|
||||
list_print( value );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* var_done() - free variable tables
|
||||
* var_done() - free variable tables.
|
||||
*/
|
||||
static void delete_var_( void* xvar, void* data )
|
||||
|
||||
static void delete_var_( void * xvar, void * data )
|
||||
{
|
||||
VARIABLE *v = (VARIABLE*)xvar;
|
||||
VARIABLE * v = (VARIABLE *)xvar;
|
||||
freestr( v->symbol );
|
||||
list_free( v-> value );
|
||||
}
|
||||
|
||||
void
|
||||
var_done()
|
||||
|
||||
void var_done()
|
||||
{
|
||||
hashenumerate( varhash, delete_var_, (void*)0 );
|
||||
hashdone( varhash );
|
||||
hashenumerate( varhash, delete_var_, (void *)0 );
|
||||
hashdone( varhash );
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
|
||||
struct hash;
|
||||
|
||||
void var_defines( char* const *e, int preprocess );
|
||||
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();
|
||||
void var_defines( char* const *e, int preprocess );
|
||||
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();
|
||||
void var_hash_swap( struct hash** );
|
||||
|
||||
/** Expands the "in" expression directly into the "out" file.
|
||||
@@ -29,7 +29,7 @@ void var_string_to_file( const char * in, int insize, const char * out, LOL * lo
|
||||
* 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 */
|
||||
# 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 */
|
||||
|
||||
|
||||
@@ -65,23 +65,23 @@ builtin_system_registry(
|
||||
char const* path = lol_get(frame->args, 0)->string;
|
||||
LIST* result = L0;
|
||||
HKEY key = get_key(&path);
|
||||
|
||||
|
||||
if (
|
||||
key != 0
|
||||
&& ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key)
|
||||
&& ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key)
|
||||
)
|
||||
{
|
||||
DWORD type;
|
||||
BYTE data[MAX_REGISTRY_DATA_LENGTH];
|
||||
DWORD len = sizeof(data);
|
||||
LIST const* const field = lol_get(frame->args, 1);
|
||||
|
||||
|
||||
if ( ERROR_SUCCESS ==
|
||||
RegQueryValueEx(key, field ? field->string : 0, 0, &type, data, &len) )
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
||||
|
||||
case REG_EXPAND_SZ:
|
||||
{
|
||||
long len;
|
||||
@@ -101,7 +101,7 @@ builtin_system_registry(
|
||||
string_free( expanded );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case REG_MULTI_SZ:
|
||||
{
|
||||
char* s;
|
||||
@@ -111,7 +111,7 @@ builtin_system_registry(
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case REG_DWORD:
|
||||
{
|
||||
char buf[100];
|
||||
@@ -133,9 +133,9 @@ builtin_system_registry(
|
||||
static LIST* get_subkey_names(HKEY key, char const* path)
|
||||
{
|
||||
LIST* result = 0;
|
||||
|
||||
if ( ERROR_SUCCESS ==
|
||||
RegOpenKeyEx(key, path, 0, KEY_ENUMERATE_SUB_KEYS, &key)
|
||||
|
||||
if ( ERROR_SUCCESS ==
|
||||
RegOpenKeyEx(key, path, 0, KEY_ENUMERATE_SUB_KEYS, &key)
|
||||
)
|
||||
{
|
||||
char name[MAX_REGISTRY_KEYNAME_LENGTH];
|
||||
@@ -143,47 +143,47 @@ static LIST* get_subkey_names(HKEY key, char const* path)
|
||||
DWORD index;
|
||||
FILETIME last_write_time;
|
||||
|
||||
for ( index = 0;
|
||||
for ( index = 0;
|
||||
ERROR_SUCCESS == RegEnumKeyEx(
|
||||
key, index, name, &name_size, 0, 0, 0, &last_write_time);
|
||||
++index,
|
||||
++index,
|
||||
name_size = sizeof(name)
|
||||
)
|
||||
{
|
||||
name[name_size] = 0;
|
||||
result = list_append(result, list_new(0, newstr(name)));
|
||||
}
|
||||
|
||||
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static LIST* get_value_names(HKEY key, char const* path)
|
||||
{
|
||||
LIST* result = 0;
|
||||
|
||||
|
||||
if ( ERROR_SUCCESS == RegOpenKeyEx(key, path, 0, KEY_QUERY_VALUE, &key) )
|
||||
{
|
||||
char name[MAX_REGISTRY_VALUENAME_LENGTH];
|
||||
DWORD name_size = sizeof(name);
|
||||
DWORD index;
|
||||
|
||||
for ( index = 0;
|
||||
for ( index = 0;
|
||||
ERROR_SUCCESS == RegEnumValue(
|
||||
key, index, name, &name_size, 0, 0, 0, 0);
|
||||
++index,
|
||||
++index,
|
||||
name_size = sizeof(name)
|
||||
)
|
||||
{
|
||||
name[name_size] = 0;
|
||||
result = list_append(result, list_new(0, newstr(name)));
|
||||
}
|
||||
|
||||
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ builtin_system_registry_names(
|
||||
{
|
||||
char const* path = lol_get(frame->args, 0)->string;
|
||||
char const* result_type = lol_get(frame->args, 1)->string;
|
||||
|
||||
|
||||
HKEY key = get_key(&path);
|
||||
|
||||
if ( !strcmp(result_type, "subkeys") )
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
/*
|
||||
# yyacc - yacc wrapper
|
||||
#
|
||||
# Allows tokens to be written as `literal` and then automatically
|
||||
# Allows tokens to be written as `literal` and then automatically
|
||||
# substituted with #defined tokens.
|
||||
#
|
||||
# Usage:
|
||||
# yyacc file.y filetab.h file.yy
|
||||
# yyacc file.y filetab.h file.yy
|
||||
#
|
||||
# inputs:
|
||||
# file.yy yacc grammar with ` literals
|
||||
@@ -59,7 +59,7 @@ int main(int argc, char ** argv)
|
||||
FILE * token_output_f = 0;
|
||||
FILE * grammar_output_f = 0;
|
||||
FILE * grammar_source_f = 0;
|
||||
|
||||
|
||||
grammar_source_f = fopen(argv[3],"r");
|
||||
if (grammar_source_f == 0) { result = 1; }
|
||||
if (result == 0)
|
||||
@@ -223,7 +223,7 @@ char * tokenize_string(char * s)
|
||||
char * literal = s;
|
||||
int l;
|
||||
int c;
|
||||
|
||||
|
||||
if (strcmp(s,":") == 0) literal = "_colon";
|
||||
else if (strcmp(s,"!") == 0) literal = "_bang";
|
||||
else if (strcmp(s,"!=") == 0) literal = "_bang_equals";
|
||||
|
||||
Reference in New Issue
Block a user