From 8e4fd9daa89baf13fd587b49078a2ddded143017 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sat, 10 Jan 2009 19:42:28 +0000 Subject: [PATCH] Merge Boost Jam 3.1.17 release to Boost release. [SVN r50535] --- src/engine/Jambase | 290 ++--- src/engine/boost-jam.spec | 10 +- src/engine/build.bat | 213 +-- src/engine/build.jam | 99 +- src/engine/build.sh | 34 +- src/engine/build_vms.com | 30 +- src/engine/builtins.c | 2016 +++++++++++++++-------------- src/engine/class.c | 156 +-- src/engine/command.c | 64 +- src/engine/command.h | 51 +- src/engine/compile.c | 1152 ++++++++--------- src/engine/compile.h | 40 +- src/engine/debug.c | 95 +- src/engine/debug.h | 15 +- src/engine/execcmd.h | 29 +- src/engine/execmac.c | 50 +- src/engine/execnt.c | 1302 ++++++++++--------- src/engine/execunix.c | 717 +++++----- src/engine/execvms.c | 214 ++- src/engine/expand.c | 754 +++++------ src/engine/expand.h | 2 +- src/engine/filemac.c | 135 +- src/engine/filent.c | 263 ++-- src/engine/fileos2.c | 53 +- src/engine/filesys.c | 43 +- src/engine/filesys.h | 31 +- src/engine/fileunix.c | 304 +++-- src/engine/filevms.c | 212 ++- src/engine/frames.c | 2 +- src/engine/frames.h | 42 +- src/engine/glob.c | 201 ++- src/engine/hash.c | 331 ++--- src/engine/hash.h | 18 +- src/engine/hcache.c | 593 ++++----- src/engine/hdrmacro.c | 62 +- src/engine/headers.c | 174 ++- src/engine/jam.c | 672 +++++----- src/engine/jam.h | 836 ++++++------ src/engine/jambase.c | 111 +- src/engine/jambase.h | 2 +- src/engine/jamgram.c | 24 +- src/engine/jamgram.y | 34 +- src/engine/jamgram.yy | 32 +- src/engine/lists.c | 380 +++--- src/engine/lists.h | 66 +- src/engine/make.c | 1307 +++++++++---------- src/engine/make.h | 16 +- src/engine/make1.c | 1572 +++++++++++----------- src/engine/mem.c | 8 +- src/engine/mem.h | 4 +- src/engine/mkjambase.c | 166 ++- src/engine/modules.c | 108 +- src/engine/modules/order.c | 2 +- src/engine/modules/property-set.c | 35 +- src/engine/native.c | 10 +- src/engine/native.h | 4 +- src/engine/newstr.c | 116 +- src/engine/newstr.h | 8 +- src/engine/option.c | 117 +- src/engine/option.h | 8 +- src/engine/output.c | 116 +- src/engine/output.h | 2 +- src/engine/parse.c | 177 ++- src/engine/parse.h | 68 +- src/engine/patchlevel.h | 6 +- src/engine/pathmac.c | 255 ++-- src/engine/pathsys.h | 53 +- src/engine/pathunix.c | 192 ++- src/engine/pathvms.c | 424 +++--- src/engine/pwd.c | 40 +- src/engine/regexp.c | 1858 +++++++++++++------------- src/engine/regexp.h | 16 +- src/engine/rules.c | 745 +++++------ src/engine/rules.h | 376 +++--- src/engine/scan.c | 628 +++++---- src/engine/scan.h | 47 +- src/engine/search.c | 145 ++- src/engine/search.h | 4 +- src/engine/strings.c | 14 +- src/engine/subst.c | 16 +- src/engine/timestamp.c | 272 ++-- src/engine/timestamp.h | 4 +- src/engine/variable.c | 588 +++++---- src/engine/variable.h | 18 +- src/engine/w32_getreg.c | 38 +- src/engine/yyacc.c | 8 +- 86 files changed, 10782 insertions(+), 10763 deletions(-) diff --git a/src/engine/Jambase b/src/engine/Jambase index fe4e128f4..5a9449983 100644 --- a/src/engine/Jambase +++ b/src/engine/Jambase @@ -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 diff --git a/src/engine/boost-jam.spec b/src/engine/boost-jam.spec index 0733b56a0..8026c0563 100644 --- a/src/engine/boost-jam.spec +++ b/src/engine/boost-jam.spec @@ -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 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) diff --git a/src/engine/build.bat b/src/engine/build.bat index 377db20c0..6ec1bb662 100644 --- a/src/engine/build.bat +++ b/src/engine/build.bat @@ -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 diff --git a/src/engine/build.jam b/src/engine/build.jam index f4c989619..99a7c7e34 100644 --- a/src/engine/build.jam +++ b/src/engine/build.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 $() + "$(--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) ; } diff --git a/src/engine/build.sh b/src/engine/build.sh index f79ef42a2..9fb037036 100755 --- a/src/engine/build.sh +++ b/src/engine/build.sh @@ -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" ;; diff --git a/src/engine/build_vms.com b/src/engine/build_vms.com index dc014cf3b..965b63424 100644 --- a/src/engine/build_vms.com +++ b/src/engine/build_vms.com @@ -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 diff --git a/src/engine/builtins.c b/src/engine/builtins.c index 802baf4fe..9e12d7a14 100644 --- a/src/engine/builtins.c +++ b/src/engine/builtins.c @@ -4,69 +4,72 @@ * This file is part of Jam - see jam.c for Copyright information. */ -# include "jam.h" +#include "jam.h" + +#include "lists.h" +#include "parse.h" +#include "builtins.h" +#include "rules.h" +#include "filesys.h" +#include "newstr.h" +#include "regexp.h" +#include "frames.h" +#include "hash.h" +#include "strings.h" +#include "pwd.h" +#include "pathsys.h" +#include "make.h" +#include "hdrmacro.h" +#include "compile.h" +#include "native.h" +#include "variable.h" +#include "timestamp.h" +#include -# include "lists.h" -# include "parse.h" -# include "builtins.h" -# include "rules.h" -# include "filesys.h" -# include "newstr.h" -# include "regexp.h" -# include "frames.h" -# include "hash.h" -# include "strings.h" -# include "pwd.h" -# include "pathsys.h" -# include "make.h" -# include "hdrmacro.h" -# include "compile.h" -# include "native.h" -# include "variable.h" -# include "timestamp.h" -# include /* * builtins.c - builtin jam rules * * External routines: * - * load_builtin() - define builtin rules + * load_builtin() - define builtin rules * * Internal routines: * - * builtin_depends() - DEPENDS/INCLUDES rule - * builtin_echo() - ECHO rule - * builtin_exit() - EXIT rule - * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule - * builtin_glob() - GLOB rule - * builtin_match() - MATCH rule + * builtin_depends() - DEPENDS/INCLUDES rule. + * builtin_echo() - ECHO rule. + * builtin_exit() - EXIT rule. + * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule. + * builtin_glob() - GLOB rule. + * builtin_match() - MATCH rule. * * 01/10/01 (seiwald) - split from compile.c */ + /* * compile_builtin() - define builtin rules */ -# define P0 (PARSE *)0 -# define C0 (char *)0 +#define P0 (PARSE *)0 +#define C0 (char *)0 -# if defined( OS_NT ) || defined( OS_CYGWIN ) -LIST* builtin_system_registry( PARSE *parse, FRAME *frame ); -LIST* builtin_system_registry_names( PARSE *parse, FRAME *frame ); -# endif +#if defined( OS_NT ) || defined( OS_CYGWIN ) + LIST * builtin_system_registry ( PARSE *, FRAME * ); + LIST * builtin_system_registry_names( PARSE *, FRAME * ); +#endif -int glob( char *s, char *c ); +int glob( char * s, char * c ); -void backtrace( FRAME *frame ); -void backtrace_line( FRAME *frame ); -void print_source_line( PARSE* p ); +void backtrace ( FRAME * ); +void backtrace_line ( FRAME * ); +void print_source_line( PARSE * ); -RULE* bind_builtin( char* name, LIST*(*f)(PARSE*, FRAME*), int flags, char** args ) + +RULE * bind_builtin( char * name, LIST * (* f)( PARSE *, FRAME * ), int flags, char * * args ) { argument_list* arg_list = 0; - + if ( args ) { arg_list = args_new(); @@ -77,166 +80,163 @@ RULE* bind_builtin( char* name, LIST*(*f)(PARSE*, FRAME*), int flags, char** arg parse_make( f, P0, P0, P0, C0, C0, flags ), 1 ); } -RULE* duplicate_rule( char* name, RULE* other ) + +RULE * duplicate_rule( char * name, RULE * other ) { return import_rule( other, root_module(), name ); } -void -load_builtins() + +void load_builtins() { - duplicate_rule( "Always" , - bind_builtin( "ALWAYS" , + duplicate_rule( "Always", + bind_builtin( "ALWAYS", builtin_flags, T_FLAG_TOUCHED, 0 ) ); - duplicate_rule( "Depends" , - bind_builtin( "DEPENDS" , + duplicate_rule( "Depends", + bind_builtin( "DEPENDS", builtin_depends, 0, 0 ) ); - duplicate_rule( "echo" , - duplicate_rule( "Echo" , - bind_builtin( "ECHO" , + duplicate_rule( "echo", + duplicate_rule( "Echo", + bind_builtin( "ECHO", builtin_echo, 0, 0 ) ) ); - { char * args[] = { "message", "*", ":", "result-value", "?", 0 }; - duplicate_rule( "exit" , - duplicate_rule( "Exit" , - bind_builtin( "EXIT" , + duplicate_rule( "exit", + duplicate_rule( "Exit", + bind_builtin( "EXIT", builtin_exit, 0, args ) ) ); } { char * args[] = { "directories", "*", ":", "patterns", "*", ":", "case-insensitive", "?", 0 }; - duplicate_rule( - "Glob" , - bind_builtin( "GLOB" , builtin_glob, 0, args ) - ); + duplicate_rule( "Glob", + bind_builtin( "GLOB", builtin_glob, 0, args ) ); } { char * args[] = { "patterns", "*", 0 }; - bind_builtin( "GLOB-RECURSIVELY" , builtin_glob_recursive, 0, args ); + bind_builtin( "GLOB-RECURSIVELY", + builtin_glob_recursive, 0, args ); } - - duplicate_rule( "Includes" , - bind_builtin( "INCLUDES" , + duplicate_rule( "Includes", + bind_builtin( "INCLUDES", builtin_depends, 1, 0 ) ); { char * args[] = { "targets", "*", ":", "targets-to-rebuild", "*", 0 }; - bind_builtin( "REBUILDS" , + bind_builtin( "REBUILDS", builtin_rebuilds, 0, args ); } - - duplicate_rule( "Leaves" , - bind_builtin( "LEAVES" , + + duplicate_rule( "Leaves", + bind_builtin( "LEAVES", builtin_flags, T_FLAG_LEAVES, 0 ) ); - duplicate_rule( "Match" , - bind_builtin( "MATCH" , + duplicate_rule( "Match", + bind_builtin( "MATCH", builtin_match, 0, 0 ) ); - duplicate_rule( "NoCare" , - bind_builtin( "NOCARE" , + duplicate_rule( "NoCare", + bind_builtin( "NOCARE", builtin_flags, T_FLAG_NOCARE, 0 ) ); - duplicate_rule( "NOTIME" , - duplicate_rule( "NotFile" , - bind_builtin( "NOTFILE" , + duplicate_rule( "NOTIME", + duplicate_rule( "NotFile", + bind_builtin( "NOTFILE", builtin_flags, T_FLAG_NOTFILE, 0 ) ) ); - duplicate_rule( "NoUpdate" , - bind_builtin( "NOUPDATE" , + duplicate_rule( "NoUpdate", + bind_builtin( "NOUPDATE", builtin_flags, T_FLAG_NOUPDATE, 0 ) ); - duplicate_rule( "Temporary" , - bind_builtin( "TEMPORARY" , + duplicate_rule( "Temporary", + bind_builtin( "TEMPORARY", builtin_flags, T_FLAG_TEMP, 0 ) ); - { - char * args[] = { "targets", "*", 0 }; - bind_builtin( - "ISFILE", - builtin_flags, T_FLAG_ISFILE, 0 ); - } + bind_builtin( "ISFILE", + builtin_flags, T_FLAG_ISFILE, 0 ); - duplicate_rule( "HdrMacro" , - bind_builtin( "HDRMACRO" , + duplicate_rule( "HdrMacro", + bind_builtin( "HDRMACRO", builtin_hdrmacro, 0, 0 ) ); - /* FAIL_EXPECTED is used to indicate that the result of a target build */ - /* action should be inverted (ok <=> fail) this can be useful when */ - /* performing test runs from Jamfiles.. */ - bind_builtin( "FAIL_EXPECTED" , + /* FAIL_EXPECTED is used to indicate that the result of a target build + * action should be inverted (ok <=> fail) this can be useful when + * performing test runs from Jamfiles. + */ + bind_builtin( "FAIL_EXPECTED", builtin_flags, T_FLAG_FAIL_EXPECTED, 0 ); - bind_builtin( "RMOLD" , builtin_flags, T_FLAG_RMOLD, 0 ); - + bind_builtin( "RMOLD", + builtin_flags, T_FLAG_RMOLD, 0 ); + { char * args[] = { "targets", "*", 0 }; - bind_builtin( "UPDATE", builtin_update, 0, args ); + bind_builtin( "UPDATE", + builtin_update, 0, args ); } { char * args[] = { "string", "pattern", "replacements", "+", 0 }; - duplicate_rule( "subst" , - bind_builtin( "SUBST" , + duplicate_rule( "subst", + bind_builtin( "SUBST", builtin_subst, 0, args ) ); } { char * args[] = { "module", "?", 0 }; - bind_builtin( "RULENAMES" , + bind_builtin( "RULENAMES", builtin_rulenames, 0, args ); } { char * args[] = { "module", "?", 0 }; - bind_builtin( "VARNAMES" , + bind_builtin( "VARNAMES", builtin_varnames, 0, args ); } { char * args[] = { "module", "?", 0 }; - bind_builtin( "DELETE_MODULE" , + bind_builtin( "DELETE_MODULE", builtin_delete_module, 0, args ); } { - char * args[] = { "source_module", "?", - ":", "source_rules", "*", - ":", "target_module", "?", - ":", "target_rules", "*", - ":", "localize", "?", 0 }; - bind_builtin( "IMPORT" , - builtin_import, 0, args ); + char * args[] = { "source_module", "?", + ":", "source_rules", "*", + ":", "target_module", "?", + ":", "target_rules", "*", + ":", "localize", "?", 0 }; + bind_builtin( "IMPORT", + builtin_import, 0, args ); } { char * args[] = { "module", "?", ":", "rules", "*", 0 }; - bind_builtin( "EXPORT" , + bind_builtin( "EXPORT", builtin_export, 0, args ); } { char * args[] = { "levels", "?", 0 }; - bind_builtin( "CALLER_MODULE" , + bind_builtin( "CALLER_MODULE", builtin_caller_module, 0, args ); } { char * args[] = { "levels", "?", 0 }; - bind_builtin( "BACKTRACE" , + bind_builtin( "BACKTRACE", builtin_backtrace, 0, args ); } { char * args[] = { 0 }; - bind_builtin( "PWD" , + bind_builtin( "PWD", builtin_pwd, 0, args ); } @@ -273,38 +273,37 @@ load_builtins() { char * args[] = { "path_parts", "*", 0 }; bind_builtin( "NORMALIZE_PATH", - builtin_normalize_path, 0, args ); + builtin_normalize_path, 0, args ); } { char * args[] = { "args", "*", 0 }; bind_builtin( "CALC", - builtin_calc, 0, args ); + builtin_calc, 0, args ); } { char * args[] = { "module", ":", "rule", 0 }; bind_builtin( "NATIVE_RULE", - builtin_native_rule, 0, args ); + builtin_native_rule, 0, args ); } { char * args[] = { "module", ":", "rule", ":", "version", 0 }; bind_builtin( "HAS_NATIVE_RULE", - builtin_has_native_rule, 0, args ); + builtin_has_native_rule, 0, args ); } - { char * args[] = { "module", "*", 0 }; bind_builtin( "USER_MODULE", - builtin_user_module, 0, args ); + builtin_user_module, 0, args ); } { char * args[] = { 0 }; bind_builtin( "NEAREST_USER_LOCATION", - builtin_nearest_user_location, 0, args ); + builtin_nearest_user_location, 0, args ); } { @@ -315,10 +314,10 @@ load_builtins() #ifdef HAVE_PYTHON { - char * args[] = { "python-module", ":", "function", ":", + char * args[] = { "python-module", ":", "function", ":", "jam-module", ":", "rule-name", 0 }; bind_builtin( "PYTHON_IMPORT_RULE", - builtin_python_import_rule, 0, args ); + builtin_python_import_rule, 0, args ); } #endif @@ -326,25 +325,24 @@ load_builtins() { char * args[] = { "key_path", ":", "data", "?", 0 }; bind_builtin( "W32_GETREG", - builtin_system_registry, 0, args ); + builtin_system_registry, 0, args ); } { char * args[] = { "key_path", ":", "result-type", 0 }; bind_builtin( "W32_GETREGNAMES", - builtin_system_registry_names, 0, args ); + builtin_system_registry_names, 0, args ); } # endif { char * args[] = { "command", ":", "*", 0 }; - bind_builtin( "SHELL", - builtin_shell, 0, args ); - bind_builtin( "COMMAND", - builtin_shell, 0, args ); + duplicate_rule( "SHELL", + bind_builtin( "COMMAND", + builtin_shell, 0, args ) ); } - /* Initialize builtin modules */ + /* Initialize builtin modules. */ init_set(); init_path(); init_regex(); @@ -353,47 +351,45 @@ load_builtins() init_order(); } + /* -* builtin_calc() - CALC rule -* -* The CALC rule performs simple mathematical operations on two arguments. -*/ + * builtin_calc() - CALC rule. + * + * The CALC rule performs simple mathematical operations on two arguments. + */ -LIST * -builtin_calc( - PARSE *parse, - FRAME *frame ) +LIST * builtin_calc( PARSE * parse, FRAME * frame ) { - LIST *arg = lol_get( frame->args, 0 ); + LIST * arg = lol_get( frame->args, 0 ); - LIST *result = 0; + LIST * result = 0; long lhs_value; long rhs_value; long result_value; - char buffer [16]; - const char* lhs; - const char* op; - const char* rhs; + char buffer [ 16 ]; + char const * lhs; + char const * op; + char const * rhs; - if (arg == 0) return L0; + if ( arg == 0 ) return L0; lhs = arg->string; arg = list_next( arg ); - if (arg == 0) return L0; + if ( arg == 0 ) return L0; op = arg->string; arg = list_next( arg ); - if (arg == 0) return L0; + if ( arg == 0 ) return L0; rhs = arg->string; - lhs_value = atoi (lhs); - rhs_value = atoi (rhs); + lhs_value = atoi( lhs ); + rhs_value = atoi( rhs ); - if (strcmp ("+", op) == 0) + if ( strcmp( "+", op ) == 0 ) { result_value = lhs_value + rhs_value; } - else if (strcmp ("-", op) == 0) + else if ( strcmp( "-", op ) == 0 ) { result_value = lhs_value - rhs_value; } @@ -402,657 +398,630 @@ builtin_calc( return L0; } - sprintf (buffer, "%ld", result_value); + sprintf( buffer, "%ld", result_value ); result = list_new( result, newstr( buffer ) ); return result; } + /* - * builtin_depends() - DEPENDS/INCLUDES rule + * builtin_depends() - DEPENDS/INCLUDES rule. * - * The DEPENDS builtin rule appends each of the listed sources on the - * dependency list of each of the listed targets. It binds both the + * The DEPENDS/INCLUDES builtin rule appends each of the listed sources on the + * dependency/includes list of each of the listed targets. It binds both the * targets and sources as TARGETs. */ -LIST * -builtin_depends( - PARSE *parse, - FRAME *frame ) +LIST * builtin_depends( PARSE * parse, FRAME * frame ) { - LIST *targets = lol_get( frame->args, 0 ); - LIST *sources = lol_get( frame->args, 1 ); - LIST *l; + LIST * targets = lol_get( frame->args, 0 ); + LIST * sources = lol_get( frame->args, 1 ); + LIST * l; - for( l = targets; l; l = list_next( l ) ) - { - TARGET *t = bindtarget( l->string ); + for ( l = targets; l; l = list_next( l ) ) + { + TARGET * t = bindtarget( l->string ); - /* If doing INCLUDES, switch to the TARGET's include */ - /* TARGET, creating it if needed. The internal include */ - /* TARGET shares the name of its parent. */ + /* If doing INCLUDES, switch to the TARGET's include */ + /* TARGET, creating it if needed. The internal include */ + /* TARGET shares the name of its parent. */ - if( parse->num ) - { - if( !t->includes ) { + if ( parse->num ) + { + if ( !t->includes ) + { t->includes = copytarget( t ); t->includes->original_target = t; } t = t->includes; - } + } - t->depends = targetlist( t->depends, sources ); - } - - /* Enter reverse links */ - for( l = sources; l; l = list_next( l ) ) - { - TARGET *s = bindtarget( l->string ); - s->dependents = targetlist( s->dependents, targets ); + t->depends = targetlist( t->depends, sources ); } - return L0; + /* Enter reverse links */ + for ( l = sources; l; l = list_next( l ) ) + { + TARGET * s = bindtarget( l->string ); + s->dependants = targetlist( s->dependants, targets ); + } + + return L0; } + /* - * builtin_rebuilds() - REBUILDS rule + * builtin_rebuilds() - REBUILDS rule. * - * The REBUILDS builtin rule appends each of the listed - * rebuild-targets in its 2nd argument on the rebuilds list of each of - * the listed targets in its first argument. + * The REBUILDS builtin rule appends each of the listed rebuild-targets in its + * 2nd argument on the rebuilds list of each of the listed targets in its first + * argument. */ -LIST * -builtin_rebuilds( - PARSE *parse, - FRAME *frame ) +LIST * builtin_rebuilds( PARSE * parse, FRAME * frame ) { - LIST *targets = lol_get( frame->args, 0 ); - LIST *rebuilds = lol_get( frame->args, 1 ); - LIST *l; + LIST * targets = lol_get( frame->args, 0 ); + LIST * rebuilds = lol_get( frame->args, 1 ); + LIST * l; - for( l = targets; l; l = list_next( l ) ) - { - TARGET *t = bindtarget( l->string ); - t->rebuilds = targetlist( t->rebuilds, rebuilds ); - } + for ( l = targets; l; l = list_next( l ) ) + { + TARGET * t = bindtarget( l->string ); + t->rebuilds = targetlist( t->rebuilds, rebuilds ); + } - return L0; + return L0; } + /* - * builtin_echo() - ECHO rule + * builtin_echo() - ECHO rule. * - * The ECHO builtin rule echoes the targets to the user. No other - * actions are taken. + * The ECHO builtin rule echoes the targets to the user. No other actions are + * taken. */ -LIST * -builtin_echo( - PARSE *parse, - FRAME *frame ) +LIST * builtin_echo( PARSE * parse, FRAME * frame ) { - list_print( lol_get( frame->args, 0 ) ); - printf( "\n" ); - return L0; + list_print( lol_get( frame->args, 0 ) ); + printf( "\n" ); + fflush( stdout ); + return L0; } + /* - * builtin_exit() - EXIT rule + * builtin_exit() - EXIT rule. * - * The EXIT builtin rule echoes the targets to the user and exits - * the program with a failure status. + * The EXIT builtin rule echoes the targets to the user and exits the program + * with a failure status. */ -LIST * -builtin_exit( - PARSE *parse, - FRAME *frame ) +LIST * builtin_exit( PARSE * parse, FRAME * frame ) { list_print( lol_get( frame->args, 0 ) ); printf( "\n" ); if ( lol_get( frame->args, 1 ) ) { - exit ( atoi( lol_get( frame->args, 1 )->string ) ); + exit( atoi( lol_get( frame->args, 1 )->string ) ); } else { - exit( EXITBAD ); /* yeech */ + exit( EXITBAD ); /* yeech */ } return L0; } + /* - * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule + * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule. * - * Builtin_flags() marks the target with the appropriate flag, for use - * by make0(). It binds each target as a TARGET. + * Builtin_flags() marks the target with the appropriate flag, for use by make0(). + * It binds each target as a TARGET. */ -LIST * -builtin_flags( - PARSE *parse, - FRAME *frame ) +LIST * builtin_flags( PARSE * parse, FRAME * frame ) { - LIST *l = lol_get( frame->args, 0 ); - - for( ; l; l = list_next( l ) ) - bindtarget( l->string )->flags |= parse->num; - - return L0; + LIST * l = lol_get( frame->args, 0 ); + for ( ; l; l = list_next( l ) ) + bindtarget( l->string )->flags |= parse->num; + return L0; } + /* - * builtin_globbing() - GLOB rule + * builtin_globbing() - GLOB rule. */ -struct globbing { - LIST *patterns; - LIST *results; - LIST *case_insensitive; -} ; +struct globbing +{ + LIST * patterns; + LIST * results; + LIST * case_insensitive; +}; -static void downcase_inplace( char* p ) + +static void downcase_inplace( char * p ) { for ( ; *p; ++p ) - { - *p = tolower(*p); - } + *p = tolower( *p ); } - -static void -builtin_glob_back( - void *closure, - char *file, - int status, - time_t time ) -{ - PROFILE_ENTER(BUILTIN_GLOB_BACK); - - struct globbing *globbing = (struct globbing *)closure; - LIST *l; - PATHNAME f; - string buf[1]; - - /* Null out directory for matching. */ - /* We wish we had file_dirscan() pass up a PATHNAME. */ + +static void builtin_glob_back +( + void * closure, + char * file, + int status, + time_t time +) +{ + PROFILE_ENTER( BUILTIN_GLOB_BACK ); + + struct globbing * globbing = (struct globbing *)closure; + LIST * l; + PATHNAME f; + string buf[ 1 ]; + + /* Null out directory for matching. We wish we had file_dirscan() pass up a + * PATHNAME. + */ path_parse( file, &f ); f.f_dir.len = 0; - /* For globbing, we unconditionally ignore current and parent - directory items. Since they items always exist, there's not - reason why caller of GLOB would want to see them. - We could also change file_dirscan, but then paths with embedded - "." and ".." won't work anywhere. + /* For globbing, we unconditionally ignore current and parent directory + * items. Since they items always exist, there is no reason why caller of + * GLOB would want to see them. We could also change file_dirscan(), but + * then paths with embedded "." and ".." would not work anywhere. */ - if (strcmp(f.f_base.ptr, ".") == 0 || strcmp(f.f_base.ptr, "..") == 0) + if ( !strcmp( f.f_base.ptr, "." ) || !strcmp( f.f_base.ptr, ".." ) ) { - PROFILE_EXIT(BUILTIN_GLOB_BACK); + PROFILE_EXIT( BUILTIN_GLOB_BACK ); return; } string_new( buf ); path_build( &f, buf, 0 ); - if (globbing->case_insensitive) { + if ( globbing->case_insensitive ) downcase_inplace( buf->value ); - } - for( l = globbing->patterns; l; l = l->next ) + for ( l = globbing->patterns; l; l = l->next ) { - if( !glob( l->string, buf->value ) ) + if ( !glob( l->string, buf->value ) ) { globbing->results = list_new( globbing->results, newstr( file ) ); break; } } - + string_free( buf ); - - PROFILE_EXIT(BUILTIN_GLOB_BACK); + + PROFILE_EXIT( BUILTIN_GLOB_BACK ); } -static LIST* downcase_list( LIST *in ) + +static LIST * downcase_list( LIST * in ) { - LIST* result = 0; - - string s[1]; + LIST * result = 0; + + string s[ 1 ]; string_new( s ); - - while (in) + + while ( in ) { string_copy( s, in->string ); downcase_inplace( s->value ); result = list_append( result, list_new( 0, newstr( s->value ) ) ); in = in->next; } - + string_free( s ); return result; } -LIST * -builtin_glob( - PARSE *parse, - FRAME *frame ) + +LIST * builtin_glob( PARSE * parse, FRAME * frame ) { - LIST *l = lol_get( frame->args, 0 ); - LIST *r = lol_get( frame->args, 1 ); - + LIST * l = lol_get( frame->args, 0 ); + LIST * r = lol_get( frame->args, 1 ); + struct globbing globbing; globbing.results = L0; globbing.patterns = r; - + globbing.case_insensitive # if defined( OS_NT ) || defined( OS_CYGWIN ) - = l; /* always case-insensitive if any files can be found */ -# else + = l; /* Always case-insensitive if any files can be found. */ +# else = lol_get( frame->args, 2 ); # endif if ( globbing.case_insensitive ) - { globbing.patterns = downcase_list( r ); - } - - for( ; l; l = list_next( l ) ) + + for ( ; l; l = list_next( l ) ) file_dirscan( l->string, builtin_glob_back, &globbing ); if ( globbing.case_insensitive ) - { list_free( globbing.patterns ); - } + return globbing.results; } -static int has_wildcards(const char* str) + +static int has_wildcards( char const * str ) { - size_t index = strcspn(str, "[]*?"); - if (str[index] == '\0') - return 0; - else - return 1; + size_t const index = strcspn( str, "[]*?" ); + return str[ index ] == '\0' ? 0 : 1; } -/** If 'file' exists, append 'file' to 'list'. - Returns 'list'. -*/ -static LIST* append_if_exists(LIST* list, char* file) + +/* + * If 'file' exists, append 'file' to 'list'. Returns 'list'. + */ + +static LIST * append_if_exists( LIST * list, char * file ) { time_t time; - timestamp(file, &time); - if (time > 0) - return list_new(list, newstr(file)); - else - return list; + timestamp( file, &time ); + return time > 0 + ? list_new( list, newstr( file ) ) + : list; } -LIST* glob1(char* dirname, char* pattern) + +LIST * glob1( char * dirname, char * pattern ) { - LIST* plist = list_new(L0, pattern); + LIST * plist = list_new( L0, pattern ); struct globbing globbing; globbing.results = L0; globbing.patterns = plist; - + globbing.case_insensitive # if defined( OS_NT ) || defined( OS_CYGWIN ) = plist; /* always case-insensitive if any files can be found */ -# else +# else = L0; # endif if ( globbing.case_insensitive ) - { globbing.patterns = downcase_list( plist ); - } - + file_dirscan( dirname, builtin_glob_back, &globbing ); if ( globbing.case_insensitive ) - { list_free( globbing.patterns ); - } - list_free(plist); + list_free( plist ); return globbing.results; } -LIST* glob_recursive(char* pattern) +LIST * glob_recursive( char * pattern ) { - LIST* result = L0; + LIST * result = L0; /* Check if there's metacharacters in pattern */ - if (!has_wildcards(pattern)) + if ( !has_wildcards( pattern ) ) { /* No metacharacters. Check if the path exists. */ result = append_if_exists(result, pattern); - } + } else { - /* Have metacharacters in the pattern. Split into dir/name */ - PATHNAME path[1]; - path_parse(pattern, path); - - if (path->f_dir.ptr) - { - LIST* dirs = L0; - string dirname[1]; - string basename[1]; - string_new(dirname); - string_new(basename); + /* Have metacharacters in the pattern. Split into dir/name. */ + PATHNAME path[ 1 ]; + path_parse( pattern, path ); - string_append_range(dirname, path->f_dir.ptr, - path->f_dir.ptr + path->f_dir.len); + if ( path->f_dir.ptr ) + { + LIST * dirs = L0; + string dirname[ 1 ]; + string basename[ 1 ]; + string_new( dirname ); + string_new( basename ); + + string_append_range( dirname, path->f_dir.ptr, + path->f_dir.ptr + path->f_dir.len ); path->f_grist.ptr = 0; path->f_grist.len = 0; path->f_dir.ptr = 0; path->f_dir.len = 0; - path_build(path, basename, 0); + path_build( path, basename, 0 ); - if (has_wildcards(dirname->value)) + dirs = has_wildcards( dirname->value ) + ? glob_recursive( dirname->value ) + : list_new( dirs, dirname->value ); + + if ( has_wildcards( basename->value ) ) { - dirs = glob_recursive(dirname->value); + for ( ; dirs; dirs = dirs->next ) + result = list_append( result, glob1( dirs->string, + basename->value ) ); } else { - dirs = list_new(dirs, dirname->value); - } - - if (has_wildcards(basename->value)) - { - for(; dirs; dirs = dirs->next) + string file_string[ 1 ]; + string_new( file_string ); + + /* No wildcard in basename. */ + for ( ; dirs; dirs = dirs->next ) { - result = list_append(result, - glob1(dirs->string, basename->value)); - } - } - else - { - string file_string[1]; - string_new(file_string); - - /** No wildcard in basename. */ - for(; dirs; dirs = dirs->next) - { path->f_dir.ptr = dirs->string; - path->f_dir.len = strlen(dirs->string); - path_build(path, file_string, 0); + path->f_dir.len = strlen( dirs->string ); + path_build( path, file_string, 0 ); - result = append_if_exists(result, file_string->value); + result = append_if_exists( result, file_string->value ); - string_truncate(file_string, 0); + string_truncate( file_string, 0 ); } - string_free(file_string); + string_free( file_string ); } - string_free(dirname); - string_free(basename); + string_free( dirname ); + string_free( basename ); } else { /** No directory, just a pattern. */ - result = list_append(result, glob1(".", pattern)); + result = list_append( result, glob1( ".", pattern ) ); } } return result; } -LIST * -builtin_glob_recursive( - PARSE *parse, - FRAME *frame ) + +LIST * builtin_glob_recursive( PARSE * parse, FRAME * frame ) { - LIST* result = L0; - LIST* l = lol_get( frame->args, 0 ); - - for(; l; l = l->next) - { - result = list_append(result, glob_recursive(l->string)); - } - + LIST * result = L0; + LIST * l = lol_get( frame->args, 0 ); + for ( ; l; l = l->next ) + result = list_append( result, glob_recursive( l->string ) ); return result; } + /* - * builtin_match() - MATCH rule, regexp matching + * builtin_match() - MATCH rule, regexp matching. */ -LIST * -builtin_match( - PARSE *parse, - FRAME *frame ) +LIST * builtin_match( PARSE * parse, FRAME * frame ) { - LIST *l, *r; - LIST *result = 0; - - string buf[1]; - string_new(buf); + LIST * l; + LIST * r; + LIST * result = 0; - /* For each pattern */ + string buf[ 1 ]; + string_new( buf ); - for( l = lol_get( frame->args, 0 ); l; l = l->next ) - { - /* Result is cached and intentionally never freed */ - regexp *re = regex_compile( l->string ); + /* For each pattern */ - /* For each string to match against */ - for( r = lol_get( frame->args, 1 ); r; r = r->next ) + for ( l = lol_get( frame->args, 0 ); l; l = l->next ) + { + /* Result is cached and intentionally never freed. */ + regexp * re = regex_compile( l->string ); + + /* For each string to match against. */ + for ( r = lol_get( frame->args, 1 ); r; r = r->next ) + { + if ( regexec( re, r->string ) ) { - if( regexec( re, r->string ) ) + int i; + int top; + + /* Find highest parameter */ + + for ( top = NSUBEXP; top-- > 1; ) + if ( re->startp[ top ] ) + break; + + /* And add all parameters up to highest onto list. */ + /* Must have parameters to have results! */ + for ( i = 1; i <= top; ++i ) { - int i, top; - - /* Find highest parameter */ - - for( top = NSUBEXP; top-- > 1; ) - if( re->startp[top] ) - break; - - /* And add all parameters up to highest onto list. */ - /* Must have parameters to have results! */ - - for( i = 1; i <= top; i++ ) - { - string_append_range( buf, re->startp[i], re->endp[i] ); - result = list_new( result, newstr( buf->value ) ); - string_truncate( buf, 0 ); - } + string_append_range( buf, re->startp[ i ], re->endp[ i ] ); + result = list_new( result, newstr( buf->value ) ); + string_truncate( buf, 0 ); } } } + } - string_free( buf ); - return result; + string_free( buf ); + return result; } -LIST * -builtin_hdrmacro( - PARSE *parse, - FRAME *frame ) -{ - LIST* l = lol_get( frame->args, 0 ); - - for ( ; l; l = list_next(l) ) - { - TARGET* t = bindtarget( l->string ); - /* scan file for header filename macro definitions */ +LIST * builtin_hdrmacro( PARSE * parse, FRAME * frame ) +{ + LIST * l = lol_get( frame->args, 0 ); + + for ( ; l; l = list_next( l ) ) + { + TARGET * t = bindtarget( l->string ); + + /* Scan file for header filename macro definitions. */ if ( DEBUG_HEADER ) - printf( "scanning '%s' for header file macro definitions\n", - l->string ); + printf( "scanning '%s' for header file macro definitions\n", + l->string ); macro_headers( t ); } - + return L0; } -/* builtin_rulenames() - RULENAMES ( MODULE ? ) + +/* + * builtin_rulenames() - RULENAMES ( MODULE ? ). * - * Returns a list of the non-local rule names in the given MODULE. If - * MODULE is not supplied, returns the list of rule names in the - * global module. + * Returns a list of the non-local rule names in the given MODULE. If MODULE is + * not supplied, returns the list of rule names in the global module. */ -/* helper function for builtin_rulenames(), below */ -static void add_rule_name( void* r_, void* result_ ) +static void add_rule_name( void * r_, void * result_ ) { - RULE* r = (RULE*)r_; - LIST** result = (LIST**)result_; - + RULE * r = (RULE *)r_; + LIST * * result = (LIST * *)result_; if ( r->exported ) *result = list_new( *result, copystr( r->name ) ); } -LIST * -builtin_rulenames( - PARSE *parse, - FRAME *frame ) + +LIST * builtin_rulenames( PARSE * parse, FRAME * frame ) { - LIST *arg0 = lol_get( frame->args, 0 ); - LIST *result = L0; - module_t* source_module = bindmodule( arg0 ? arg0->string : 0 ); + LIST * arg0 = lol_get( frame->args, 0 ); + LIST * result = L0; + module_t * source_module = bindmodule( arg0 ? arg0->string : 0 ); if ( source_module->rules ) hashenumerate( source_module->rules, add_rule_name, &result ); return result; } -/* builtin_varnames() - VARNAMES ( MODULE ? ) + +/* + * builtin_varnames() - VARNAMES ( MODULE ? ). * - * Returns a list of the variable names in the given MODULE. If - * MODULE is not supplied, returns the list of variable names in the - * global module. + * Returns a list of the variable names in the given MODULE. If MODULE is not + * supplied, returns the list of variable names in the global module. */ -/* helper function for builtin_varnames(), below. Used with - * hashenumerate, will prepend the key of each element to a list +/* helper function for builtin_varnames(), below. Used with hashenumerate, will + * prepend the key of each element to the list */ -static void add_hash_key( void* np, void* result_ ) +static void add_hash_key( void * np, void * result_ ) { - LIST** result = (LIST**)result_; - - *result = list_new( *result, copystr( *(char**)np ) ); + LIST * * result = (LIST * *)result_; + *result = list_new( *result, copystr( *(char * *)np ) ); } -static struct hash *get_running_module_vars() + +static struct hash * get_running_module_vars() { - struct hash *dummy, *vars = NULL; - /* Get the global variables pointer (that of the currently running module) */ - var_hash_swap(&vars); + struct hash * dummy; + struct hash * vars = NULL; + /* Get the global variables pointer (that of the currently running module). + */ + var_hash_swap( &vars ); dummy = vars; - /* Put the global variables pointer in its right place */ - var_hash_swap(&dummy); + /* Put the global variables pointer in its right place. */ + var_hash_swap( &dummy ); return vars; } -LIST * -builtin_varnames( - PARSE *parse, - FRAME *frame ) -{ - LIST *arg0 = lol_get( frame->args, 0 ); - LIST *result = L0; - module_t* source_module = bindmodule( arg0 ? arg0->string : 0 ); - /* The running module _always_ has its 'variables' member set to NULL - * due to the way enter_module and var_hash_swap work */ - struct hash *vars = - source_module == frame->module ? - get_running_module_vars() : source_module->variables; +LIST * builtin_varnames( PARSE * parse, FRAME * frame ) +{ + LIST * arg0 = lol_get( frame->args, 0 ); + LIST * result = L0; + module_t * source_module = bindmodule( arg0 ? arg0->string : 0 ); + + /* The running module _always_ has its 'variables' member set to NULL due to + * the way enter_module() and var_hash_swap() work. + */ + struct hash * vars = source_module == frame->module + ? get_running_module_vars() + : source_module->variables; if ( vars ) hashenumerate( vars, add_hash_key, &result ); return result; } + /* - * builtin_delete_module() - MODULE ? + * builtin_delete_module() - MODULE ?. * * Clears all rules and variables from the given module. */ -LIST * -builtin_delete_module( - PARSE *parse, - FRAME *frame ) -{ - LIST *arg0 = lol_get( frame->args, 0 ); - LIST *result = L0; - module_t* source_module = bindmodule( arg0 ? arg0->string : 0 ); +LIST * builtin_delete_module( PARSE * parse, FRAME * frame ) +{ + LIST * arg0 = lol_get( frame->args, 0 ); + LIST * result = L0; + module_t * source_module = bindmodule( arg0 ? arg0->string : 0 ); delete_module( source_module ); return result; } -static void unknown_rule( FRAME *frame, char* key, char *module_name, char *rule_name ) + +static void unknown_rule( FRAME * frame, char * key, char * module_name, char * rule_name ) { backtrace_line( frame->prev ); printf( "%s error: rule \"%s\" unknown in module \"%s\"\n", key, rule_name, module_name ); backtrace( frame->prev ); - exit(1); - + exit( 1 ); } + /* - * builtin_import() - IMPORT ( SOURCE_MODULE ? : SOURCE_RULES * : TARGET_MODULE ? : TARGET_RULES * : LOCALIZE ? ) + * builtin_import() - IMPORT + * ( + * SOURCE_MODULE ? : + * SOURCE_RULES * : + * TARGET_MODULE ? : + * TARGET_RULES * : + * LOCALIZE ? + * ) * - * The IMPORT rule imports rules from the SOURCE_MODULE into the - * TARGET_MODULE as local rules. If either SOURCE_MODULE or - * TARGET_MODULE is not supplied, it refers to the global - * module. SOURCE_RULES specifies which rules from the SOURCE_MODULE - * to import; TARGET_RULES specifies the names to give those rules in - * TARGET_MODULE. If SOURCE_RULES contains a name which doesn't - * correspond to a rule in SOURCE_MODULE, or if it contains a - * different number of items than TARGET_RULES, an error is issued. - * if LOCALIZE is specified, the rules will be executed in - * TARGET_MODULE, with corresponding access to its module local + * The IMPORT rule imports rules from the SOURCE_MODULE into the TARGET_MODULE + * as local rules. If either SOURCE_MODULE or TARGET_MODULE is not supplied, it + * refers to the global module. SOURCE_RULES specifies which rules from the + * SOURCE_MODULE to import; TARGET_RULES specifies the names to give those rules + * in TARGET_MODULE. If SOURCE_RULES contains a name which doesn't correspond to + * a rule in SOURCE_MODULE, or if it contains a different number of items than + * TARGET_RULES, an error is issued. If LOCALIZE is specified, the rules will be + * executed in TARGET_MODULE, with corresponding access to its module local * variables. */ -LIST * -builtin_import( - PARSE *parse, - FRAME *frame ) -{ - LIST *source_module_list = lol_get( frame->args, 0 ); - LIST *source_rules = lol_get( frame->args, 1 ); - LIST *target_module_list = lol_get( frame->args, 2 ); - LIST *target_rules = lol_get( frame->args, 3 ); - LIST *localize = lol_get( frame->args, 4 ); - module_t* target_module = bindmodule( target_module_list ? target_module_list->string : 0 ); - module_t* source_module = bindmodule( source_module_list ? source_module_list->string : 0 ); - - LIST *source_name, *target_name; - +LIST * builtin_import( PARSE * parse, FRAME * frame ) +{ + LIST * source_module_list = lol_get( frame->args, 0 ); + LIST * source_rules = lol_get( frame->args, 1 ); + LIST * target_module_list = lol_get( frame->args, 2 ); + LIST * target_rules = lol_get( frame->args, 3 ); + LIST * localize = lol_get( frame->args, 4 ); + + module_t * target_module = + bindmodule( target_module_list ? target_module_list->string : 0 ); + module_t * source_module = + bindmodule( source_module_list ? source_module_list->string : 0 ); + + LIST * source_name; + LIST * target_name; + for ( source_name = source_rules, target_name = target_rules; source_name && target_name; - source_name = list_next( source_name ) - , target_name = list_next( target_name ) ) + source_name = list_next( source_name ), + target_name = list_next( target_name ) ) { - RULE r_, *r = &r_, *imported; + RULE r_; + RULE * r = &r_; + RULE * imported; r_.name = source_name->string; - - if ( !source_module->rules - || !hashcheck( source_module->rules, (HASHDATA**)&r ) - ) - { + + if ( !source_module->rules || + !hashcheck( source_module->rules, (HASHDATA * *)&r ) ) unknown_rule( frame, "IMPORT", source_module->name, r_.name ); - } - + imported = import_rule( r, target_module, target_name->string ); if ( localize ) imported->module = target_module; - imported->exported = 0; /* this rule is really part of some other module; just refer to it here, but don't let it out */ + /* This rule is really part of some other module. Just refer to it here, + * but do not let it out. + */ + imported->exported = 0; } - + if ( source_name || target_name ) { backtrace_line( frame->prev ); @@ -1063,7 +1032,7 @@ builtin_import( list_print( target_rules ); printf( "\n" ); backtrace( frame->prev ); - exit(1); + exit( 1 ); } return L0; @@ -1071,45 +1040,45 @@ builtin_import( /* - * builtin_export() - EXPORT ( MODULE ? : RULES * ) + * builtin_export() - EXPORT ( MODULE ? : RULES * ). * - * The EXPORT rule marks RULES from the SOURCE_MODULE as non-local - * (and thus exportable). If an element of RULES does not name a rule - * in MODULE, an error is issued. + * The EXPORT rule marks RULES from the SOURCE_MODULE as non-local (and thus + * exportable). If an element of RULES does not name a rule in MODULE, an error + * is issued. */ -LIST * -builtin_export( - PARSE *parse, - FRAME *frame ) -{ - LIST *module_list = lol_get( frame->args, 0 ); - LIST *rules = lol_get( frame->args, 1 ); - module_t* m = bindmodule( module_list ? module_list->string : 0 ); - - +LIST * builtin_export( PARSE * parse, FRAME * frame ) +{ + LIST * module_list = lol_get( frame->args, 0 ); + LIST * rules = lol_get( frame->args, 1 ); + module_t * m = bindmodule( module_list ? module_list->string : 0 ); + for ( ; rules; rules = list_next( rules ) ) { - RULE r_, *r = &r_; + RULE r_; + RULE * r = &r_; r_.name = rules->string; - - if ( !m->rules || !hashcheck( m->rules, (HASHDATA**)&r ) ) + + if ( !m->rules || !hashcheck( m->rules, (HASHDATA * *)&r ) ) unknown_rule( frame, "EXPORT", m->name, r_.name ); - + r->exported = 1; } return L0; } -/* Retrieve the file and line number that should be indicated for a - * given procedure in debug output or an error backtrace + +/* + * get_source_line() - Retrieve the file and line number that should be + * indicated for a given procedure in debug output or an error backtrace. */ -static void get_source_line( PARSE* procedure, char** file, int* line ) + +static void get_source_line( PARSE * procedure, char * * file, int * line ) { if ( procedure ) { - char* f = procedure->file; - int l = procedure->line; + char * f = procedure->file; + int l = procedure->line; if ( !strcmp( f, "+" ) ) { f = "jambase.c"; @@ -1125,20 +1094,26 @@ static void get_source_line( PARSE* procedure, char** file, int* line ) } } -void print_source_line( PARSE* p ) + +void print_source_line( PARSE * p ) { - char* file; - int line; + char * file; + int line; get_source_line( p, &file, &line ); if ( line < 0 ) printf( "(builtin):" ); else - printf( "%s:%d:", file, line); + printf( "%s:%d:", file, line ); } -/* Print a single line of error backtrace for the given frame */ -void backtrace_line( FRAME *frame ) + +/* + * backtrace_line() - print a single line of error backtrace for the given + * frame. + */ + +void backtrace_line( FRAME * frame ) { if ( frame == 0 ) { @@ -1151,34 +1126,38 @@ void backtrace_line( FRAME *frame ) } } -/* Print the entire backtrace from the given frame to the Jambase - * which invoked it. + +/* + * backtrace() - Print the entire backtrace from the given frame to the Jambase + * which invoked it. */ -void backtrace( FRAME *frame ) + +void backtrace( FRAME * frame ) { - if ( !frame ) return; - while ( frame = frame->prev ) - { + if ( !frame ) return; + while ( ( frame = frame->prev ) ) backtrace_line( frame ); - } } -/* A Jam version of the backtrace function, taking no arguments and - * returning a list of quadruples: FILENAME LINE MODULE. RULENAME - * describing each frame. Note that the module-name is always - * followed by a period. - */ -LIST *builtin_backtrace( PARSE *parse, FRAME *frame ) -{ - LIST* levels_arg = lol_get( frame->args, 0 ); - int levels = levels_arg ? atoi( levels_arg->string ) : ((unsigned int)(-1) >> 1) ; - LIST* result = L0; - for(; (frame = frame->prev) && levels ; --levels ) +/* + * builtin_backtrace() - A Jam version of the backtrace function, taking no + * arguments and returning a list of quadruples: FILENAME LINE MODULE. RULENAME + * describing each frame. Note that the module-name is always followed by a + * period. + */ + +LIST * builtin_backtrace( PARSE * parse, FRAME * frame ) +{ + LIST * levels_arg = lol_get( frame->args, 0 ); + int levels = levels_arg ? atoi( levels_arg->string ) : ( (unsigned int)(-1) >> 1 ) ; + + LIST * result = L0; + for ( ; ( frame = frame->prev ) && levels ; --levels ) { - char* file; - int line; - char buf[32]; + char * file; + int line; + char buf[32]; get_source_line( frame->procedure, &file, &line ); sprintf( buf, "%d", line ); result = list_new( result, newstr( file ) ); @@ -1189,405 +1168,420 @@ LIST *builtin_backtrace( PARSE *parse, FRAME *frame ) return result; } + /* * builtin_caller_module() - CALLER_MODULE ( levels ? ) * * If levels is not supplied, returns the name of the module of the rule which * called the one calling this one. If levels is supplied, it is interpreted as * an integer specifying a number of additional levels of call stack to traverse - * in order to locate the module in question. If no such module exists, - * returns the empty list. Also returns the empty list when the module in - * question is the global module. This rule is needed for implementing module - * import behavior. + * in order to locate the module in question. If no such module exists, returns + * the empty list. Also returns the empty list when the module in question is + * the global module. This rule is needed for implementing module import + * behavior. */ -LIST *builtin_caller_module( PARSE *parse, FRAME *frame ) + +LIST * builtin_caller_module( PARSE * parse, FRAME * frame ) { - LIST* levels_arg = lol_get( frame->args, 0 ); + LIST * levels_arg = lol_get( frame->args, 0 ); int levels = levels_arg ? atoi( levels_arg->string ) : 0 ; int i; - for (i = 0; i < levels + 2 && frame->prev; ++i) + for ( i = 0; ( i < levels + 2 ) && frame->prev; ++i ) frame = frame->prev; if ( frame->module == root_module() ) - { return L0; - } - else + { - LIST* result; - + LIST * result; string name; string_copy( &name, frame->module->name ); string_pop_back( &name ); - result = list_new( L0, newstr(name.value) ); - string_free( &name ); - return result; } } + /* * Return the current working directory. * * Usage: pwd = [ PWD ] ; */ -LIST* -builtin_pwd( PARSE *parse, FRAME *frame ) + +LIST * builtin_pwd( PARSE * parse, FRAME * frame ) { return pwd(); } + /* * Adds targets to the list of target that jam will attempt to update. */ -LIST* -builtin_update( PARSE *parse, FRAME *frame) + +LIST * builtin_update( PARSE * parse, FRAME * frame ) { - LIST* result = list_copy( L0, targets_to_update() ); - LIST* arg1 = lol_get( frame->args, 0 ); + LIST * result = list_copy( L0, targets_to_update() ); + LIST * arg1 = lol_get( frame->args, 0 ); clear_targets_to_update(); for ( ; arg1; arg1 = list_next( arg1 ) ) - mark_target_for_updating( newstr(arg1->string) ); + mark_target_for_updating( newstr( arg1->string ) ); return result; } -LIST* -builtin_search_for_target( PARSE *parse, FRAME *frame ) -{ - LIST* arg1 = lol_get( frame->args, 0 ); - LIST* arg2 = lol_get( frame->args, 1 ); - TARGET* t = search_for_target( arg1->string, arg2 ); +LIST * builtin_search_for_target( PARSE * parse, FRAME * frame ) +{ + LIST * arg1 = lol_get( frame->args, 0 ); + LIST * arg2 = lol_get( frame->args, 1 ); + TARGET * t = search_for_target( arg1->string, arg2 ); return list_new( L0, t->name ); } -LIST *builtin_import_module( PARSE *parse, FRAME *frame ) + +LIST * builtin_import_module( PARSE * parse, FRAME * frame ) { - LIST* arg1 = lol_get( frame->args, 0 ); - LIST* arg2 = lol_get( frame->args, 1 ); - - module_t* m = arg2 ? bindmodule(arg2->string) : root_module(); - - import_module(arg1, m); - + LIST * arg1 = lol_get( frame->args, 0 ); + LIST * arg2 = lol_get( frame->args, 1 ); + module_t * m = arg2 ? bindmodule( arg2->string ) : root_module(); + import_module( arg1, m ); return L0; } -LIST *builtin_imported_modules( PARSE *parse, FRAME *frame ) +LIST * builtin_imported_modules( PARSE * parse, FRAME * frame ) { - LIST *arg0 = lol_get( frame->args, 0 ); - module_t* source_module = bindmodule( arg0 ? arg0->string : 0 ); - - return imported_modules(source_module); + LIST * arg0 = lol_get( frame->args, 0 ); + return imported_modules( bindmodule( arg0 ? arg0->string : 0 ) ); } -LIST *builtin_instance( PARSE *parse, FRAME *frame ) -{ - LIST* arg1 = lol_get( frame->args, 0 ); - LIST* arg2 = lol_get( frame->args, 1 ); - module_t* instance = bindmodule( arg1->string ); - module_t* class_module = bindmodule( arg2->string ); +LIST * builtin_instance( PARSE * parse, FRAME * frame ) +{ + LIST * arg1 = lol_get( frame->args, 0 ); + LIST * arg2 = lol_get( frame->args, 1 ); + module_t * const instance = bindmodule( arg1->string ); + module_t * const class_module = bindmodule( arg2->string ); instance->class_module = class_module; - return L0; } -LIST* -builtin_sort( PARSE *parse, FRAME *frame ) -{ - LIST* arg1 = lol_get( frame->args, 0 ); - return list_sort(arg1); +LIST * builtin_sort( PARSE * parse, FRAME * frame ) +{ + LIST * arg1 = lol_get( frame->args, 0 ); + return list_sort( arg1 ); } -LIST *builtin_normalize_path( PARSE *parse, FRAME *frame ) + +LIST * builtin_normalize_path( PARSE * parse, FRAME * frame ) { - LIST* arg = lol_get( frame->args, 0 ); + LIST * arg = lol_get( frame->args, 0 ); - /* First, we iterate over all '/'-separated elements, starting from - the end of string. If we see '..', we remove previous path elements. - If we see '.', we remove it. - The removal is done by putting '\1' in the string. After all the string - is processed, we do a second pass, removing '\1' characters. - */ - - string in[1], out[1], tmp[1]; - char* end; /* Last character of the part of string still to be processed. */ - char* current; /* Working pointer. */ - int dotdots = 0; /* Number of '..' elements seen and not processed yet. */ - int rooted = arg->string[0] == '/'; - char* result; + /* First, we iterate over all '/'-separated elements, starting from the end + * of string. If we see a '..', we remove a previous path elements. If we + * see '.', we remove it. The removal is done by overwriting data using '\1' + * in the string. After the whole string has been processed, we do a second + * pass, removing all the entered '\1' characters. + */ - /* Make a copy of input: we should not change it. */ - string_new(in); - if (!rooted) - string_push_back(in, '/'); - while (arg) + string in[ 1 ]; + string out[ 1 ]; + /* Last character of the part of string still to be processed. */ + char * end; + /* Working pointer. */ + char * current; + /* Number of '..' elements seen and not processed yet. */ + int dotdots = 0; + int rooted = 0; + char * result = 0; + + /* Make a copy of input: we should not change it. Prepend a '/' before it as + * a guard for the algorithm later on and remember whether it was originally + * rooted or not. + */ + string_new( in ); + string_push_back( in, '/' ); + for ( ; arg; arg = list_next( arg ) ) { - string_append(in, arg->string); - arg = list_next(arg); - if (arg) - string_append(in, "/"); + if ( arg->string[ 0 ] != '\0' ) + { + if ( in->size == 1 ) + rooted = ( ( arg->string[ 0 ] == '/' ) || + ( arg->string[ 0 ] == '\\' ) ); + else + string_append( in, "/" ); + string_append( in, arg->string ); + } } - /* Convert \ into /. On windows, paths using / and \ are equivalent, - and we want this function to obtain canonic representation. */ - for (current = in->value, end = in->value + in->size; - current < end; ++current) - if (*current == '\\') + /* Convert \ into /. On Windows, paths using / and \ are equivalent, and we + * want this function to obtain a canonic representation. + */ + for ( current = in->value, end = in->value + in->size; + current < end; ++current ) + if ( *current == '\\' ) *current = '/'; - - end = in->value + in->size - 1; - current = end; - - for(;end >= in->value;) { + /* Now we remove any extra path elements by overwriting them with '\1' + * characters and cound how many more unused '..' path elements there are + * remaining. Note that each remaining path element with always starts with + * a '/' character. + */ + for ( end = in->value + in->size - 1; end >= in->value; ) + { /* Set 'current' to the next occurence of '/', which always exists. */ - for(current = end; *current != '/'; --current) - ; - - if (current == end && current != in->value) { - /* Found a trailing slash. Remove it. */ + for ( current = end; *current != '/'; --current ); + + if ( current == end ) + { + /* Found a trailing or duplicate '/'. Remove it. */ *current = '\1'; - } else if (current == end && *(current+1) == '/') { - /* Found duplicated slash. Remove it. */ + } + else if ( ( end - current == 1 ) && ( *(current + 1) == '.' ) ) + { + /* Found '/.'. Remove them all. */ *current = '\1'; - } else if (end - current == 1 && strncmp(current, "/.", 2) == 0) { - /* Found '/.'. Drop them all. */ + *(current + 1) = '\1'; + } + else if ( ( end - current == 2 ) && ( *(current + 1) == '.' ) && ( *(current + 2) == '.' ) ) + { + /* Found '/..'. Remove them all. */ *current = '\1'; - *(current+1) = '\1'; - } else if (end - current == 2 && strncmp(current, "/..", 3) == 0) { - /* Found '/..' */ - *current = '\1'; - *(current+1) = '\1'; - *(current+2) = '\1'; + *(current + 1) = '\1'; + *(current + 2) = '\1'; ++dotdots; - } else if (dotdots) { - char* p = current; - memset(current, '\1', end-current+1); + } + else if ( dotdots ) + { + memset( current, '\1', end - current + 1 ); --dotdots; - } - end = current-1; + } + end = current - 1; } + string_new( out ); - string_new(tmp); - while(dotdots--) - string_append(tmp, "/.."); - string_append(tmp, in->value); - string_copy(in, tmp->value); - string_free(tmp); - - - string_new(out); - /* The resulting path is either empty or has '/' as the first significant - element. If the original path was not rooted, we need to drop first '/'. - If the original path was rooted, and we've got empty path, need to add '/' - */ - if (!rooted) { - current = strchr(in->value, '/'); - if (current) - *current = '\1'; - } - - for (current = in->value; *current; ++current) - if (*current != '\1') - string_push_back(out, *current); + /* Now we know that we need to add exactly dotdots '..' path elements to the + * front and that our string is either empty or has a '/' as its first + * significant character. If we have any dotdots remaining then the passed + * path must not have been rooted or else it is invalid we return an empty + * list. + */ + if ( dotdots ) + { + if ( rooted ) return L0; + do + string_append( out, "/.." ); + while ( --dotdots ); + } - - result = newstr(out->size ? out->value : (rooted ? "/" : ".")); - string_free(in); - string_free(out); + /* Now we actually remove all the path characters marked for removal. */ + for ( current = in->value; *current; ++current ) + if ( *current != '\1' ) + string_push_back( out, *current ); - return list_new(0, result); + /* Here we know that our string contains no '\1' characters and is either + * empty or has a '/' as its initial character. If the original path was not + * rooted and we have a non-empty path we need to drop the initial '/'. If + * the original path was rooted and we have an empty path we need to add + * back the '/'. + */ + result = newstr( out->size ? out->value + !rooted : ( rooted ? "/" : "." ) ); + string_free( out ); + string_free( in ); + + return list_new( 0, result ); } -LIST *builtin_native_rule( PARSE *parse, FRAME *frame ) + +LIST * builtin_native_rule( PARSE * parse, FRAME * frame ) { - LIST* module_name = lol_get( frame->args, 0 ); - LIST* rule_name = lol_get( frame->args, 1 ); + LIST * module_name = lol_get( frame->args, 0 ); + LIST * rule_name = lol_get( frame->args, 1 ); - module_t* module = bindmodule(module_name->string); + module_t * module = bindmodule( module_name->string ); - native_rule_t n, *np = &n; + native_rule_t n; + native_rule_t * np = &n; n.name = rule_name->string; - if (module->native_rules && hashcheck(module->native_rules, (HASHDATA**)&np)) + if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) ) { - new_rule_body(module, np->name, np->arguments, np->procedure, 1); + new_rule_body( module, np->name, np->arguments, np->procedure, 1 ); } else { backtrace_line( frame->prev ); - printf( "error: no native rule \"%s\" defined in module \"%s\"\n", - n.name, module->name); + printf( "error: no native rule \"%s\" defined in module \"%s\"\n", + n.name, module->name ); backtrace( frame->prev ); - exit(1); + exit( 1 ); } - return L0; + return L0; } -LIST *builtin_has_native_rule( PARSE *parse, FRAME *frame ) + +LIST * builtin_has_native_rule( PARSE * parse, FRAME * frame ) { - LIST* module_name = lol_get( frame->args, 0 ); - LIST* rule_name = lol_get( frame->args, 1 ); - LIST* version = lol_get( frame->args, 2 ); + LIST * module_name = lol_get( frame->args, 0 ); + LIST * rule_name = lol_get( frame->args, 1 ); + LIST * version = lol_get( frame->args, 2 ); - module_t* module = bindmodule(module_name->string); + module_t * module = bindmodule( module_name->string ); - native_rule_t n, *np = &n; + native_rule_t n; + native_rule_t * np = &n; n.name = rule_name->string; - if (module->native_rules && hashcheck(module->native_rules, (HASHDATA**)&np)) + if ( module->native_rules && hashcheck( module->native_rules, (HASHDATA * *)&np ) ) { - int expected_version = atoi(version->string); - if (np->version == expected_version) - return list_new(0, newstr("true")); + int expected_version = atoi( version->string ); + if ( np->version == expected_version ) + return list_new( 0, newstr( "true" ) ); } - return L0; + return L0; } -LIST *builtin_user_module( PARSE *parse, FRAME *frame ) +LIST * builtin_user_module( PARSE * parse, FRAME * frame ) { - LIST* module_name = lol_get( frame->args, 0 ); - for(; module_name; module_name = module_name->next) + LIST * module_name = lol_get( frame->args, 0 ); + for ( ; module_name; module_name = module_name->next ) { - module_t* m = bindmodule( module_name->string); + module_t * m = bindmodule( module_name->string ); m->user_module = 1; } return L0; } -LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame ) -{ - LIST* result = 0; - FRAME* nearest_user_frame = - frame->module->user_module ? frame : frame->prev_user; - if (nearest_user_frame) +LIST * builtin_nearest_user_location( PARSE * parse, FRAME * frame ) +{ + FRAME * nearest_user_frame = + frame->module->user_module ? frame : frame->prev_user; + if ( !nearest_user_frame ) + return L0; + { - char* file; - int line; - char buf[32]; + LIST * result = 0; + char * file; + int line; + char buf[32]; + get_source_line( nearest_user_frame->procedure, &file, &line ); sprintf( buf, "%d", line ); result = list_new( result, newstr( file ) ); result = list_new( result, newstr( buf ) ); return result; } - else - { - return L0; - } } -LIST *builtin_check_if_file( PARSE *parse, FRAME *frame ) + +LIST * builtin_check_if_file( PARSE * parse, FRAME * frame ) { - LIST* name = lol_get( frame->args, 0 ); - if (file_is_file(name->string) == 1) { - return list_new(0, newstr("true")); - } else { - return L0; - } + LIST * name = lol_get( frame->args, 0 ); + return file_is_file( name->string ) == 1 + ? list_new( 0, newstr( "true" ) ) + : L0 ; } #ifdef HAVE_PYTHON -LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame ) +LIST * builtin_python_import_rule( PARSE * parse, FRAME * frame ) { static int first_time = 1; - char* python_module = lol_get( frame->args, 0 )->string; - char* python_function = lol_get( frame->args, 1 )->string; - char* jam_module = lol_get( frame->args, 2 )->string; - char* jam_rule = lol_get( frame->args, 3 )->string; + char * python_module = lol_get( frame->args, 0 )->string; + char * python_function = lol_get( frame->args, 1 )->string; + char * jam_module = lol_get( frame->args, 2 )->string; + char * jam_rule = lol_get( frame->args, 3 )->string; - PyObject *pName, *pModule, *pDict, *pFunc; + PyObject * pName; + PyObject * pModule; + PyObject * pDict; + PyObject * pFunc; - if (first_time) - { - /* At the first invocation, we add the value of the - global EXTRA_PYTHONPATH to the sys.path Python - variable. - */ - LIST* extra = 0; - module_t* outer_module = frame->module; + if ( first_time ) + { + /* At the first invocation, we add the value of the global + * EXTRA_PYTHONPATH to the sys.path Python variable. + */ + LIST * extra = 0; + module_t * outer_module = frame->module; - first_time = 0; + first_time = 0; - if ( outer_module != root_module()) - { - exit_module( outer_module ); - enter_module( root_module()); - } - - extra = var_get("EXTRA_PYTHONPATH"); - - if ( outer_module != root_module()) - { - exit_module( root_module()); - enter_module( outer_module ); - } + if ( outer_module != root_module() ) + { + exit_module( outer_module ); + enter_module( root_module() ); + } - for(; extra; extra = extra->next) - { - string buf[1]; - string_new(buf); - string_append(buf, "import sys\nsys.path.append(\""); - string_append(buf, extra->string); - string_append(buf, "\")\n"); - PyRun_SimpleString(buf->value); - string_free(buf); - } - } + extra = var_get( "EXTRA_PYTHONPATH" ); + if ( outer_module != root_module() ) + { + exit_module( root_module() ); + enter_module( outer_module ); + } - pName = PyString_FromString(python_module); - - pModule = PyImport_Import(pName); - Py_DECREF(pName); + for ( ; extra; extra = extra->next ) + { + string buf[ 1 ]; + string_new( buf ); + string_append( buf, "import sys\nsys.path.append(\"" ); + string_append( buf, extra->string ); + string_append( buf, "\")\n" ); + PyRun_SimpleString( buf->value ); + string_free( buf ); + } + } - if (pModule != NULL) { - pDict = PyModule_GetDict(pModule); - pFunc = PyDict_GetItemString(pDict, python_function); + pName = PyString_FromString( python_module ); + pModule = PyImport_Import( pName ); + Py_DECREF( pName ); - if (pFunc && PyCallable_Check(pFunc)) { + if ( pModule != NULL ) + { + pDict = PyModule_GetDict( pModule ); + pFunc = PyDict_GetItemString( pDict, python_function ); - module_t* m = bindmodule(jam_module); - RULE* r = bindrule( jam_rule, m ); + if ( pFunc && PyCallable_Check( pFunc ) ) + { + module_t * m = bindmodule( jam_module ); + RULE * r = bindrule( jam_rule, m ); - /* Make pFunc owned */ - Py_INCREF(pFunc); + /* Make pFunc owned. */ + Py_INCREF( pFunc ); r->python_function = pFunc; } - else { - if (PyErr_Occurred()) + else + { + if ( PyErr_Occurred() ) PyErr_Print(); - fprintf(stderr, "Cannot find function \"%s\"\n", python_function); + fprintf( stderr, "Cannot find function \"%s\"\n", python_function ); } - Py_DECREF(pModule); + Py_DECREF( pModule ); } - else { + else + { PyErr_Print(); - fprintf(stderr, "Failed to load \"%s\"\n", python_module); + fprintf( stderr, "Failed to load \"%s\"\n", python_module ); } - return L0; + return L0; } #endif -void lol_build( LOL* lol, char** elements ) +void lol_build( LOL * lol, char * * elements ) { - LIST* l = L0; + LIST * l = L0; lol_init( lol ); - + while ( elements && *elements ) { if ( !strcmp( *elements, ":" ) ) @@ -1601,67 +1595,69 @@ void lol_build( LOL* lol, char** elements ) } ++elements; } - + if ( l != L0 ) lol_add( lol, l ); } + #ifdef HAVE_PYTHON -/** Calls the bjam rule specified by name passed in 'args'. - The name is looked up in context of bjam's 'python_interface' - module. Returns the list of string retured by the rule. -*/ -PyObject* -bjam_call(PyObject* self, PyObject* args) -{ - FRAME inner[1]; - LIST *result; - PARSE *p; - char* rulename; - - /* Build up the list of arg lists */ +/* + * Calls the bjam rule specified by name passed in 'args'. The name is looked up + * in the context of bjam's 'python_interface' module. Returns the list of + * string retured by the rule. + */ +PyObject* bjam_call( PyObject * self, PyObject * args ) +{ + FRAME inner[ 1 ]; + LIST * result; + PARSE * p; + char * rulename; + + /* Build up the list of arg lists. */ frame_init( inner ); inner->prev = 0; inner->prev_user = 0; - inner->module = bindmodule("python_interface"); + inner->module = bindmodule( "python_interface" ); inner->procedure = 0; - /* Extract the rule name and arguments from 'args' */ + /* Extract the rule name and arguments from 'args'. */ - /* PyTuple_GetItem returns borrowed reference */ - rulename = PyString_AsString(PyTuple_GetItem(args, 0)); + /* PyTuple_GetItem returns borrowed reference. */ + rulename = PyString_AsString( PyTuple_GetItem( args, 0 ) ); { int i = 1; - int size = PyTuple_Size(args); - for( ; i < size; ++i) { - PyObject* a = PyTuple_GetItem(args, i); - if (PyString_Check(a)) + int size = PyTuple_Size( args ); + for ( ; i < size; ++i ) + { + PyObject * a = PyTuple_GetItem( args, i ); + if ( PyString_Check( a ) ) { - lol_add(inner->args, - list_new(0, newstr(PyString_AsString(a)))); + lol_add( inner->args, list_new( 0, newstr( + PyString_AsString( a ) ) ) ); } - else if (PySequence_Check(a)) + else if ( PySequence_Check( a ) ) { - LIST* l = 0; - int s = PySequence_Size(a); + LIST * l = 0; + int s = PySequence_Size( a ); int i = 0; - for(; i < s; ++i) + for ( ; i < s; ++i ) { /* PySequence_GetItem returns new reference. */ - PyObject* e = PySequence_GetItem(a, i); - char* s = PyString_AsString(e); - if (!s) + PyObject * e = PySequence_GetItem( a, i ); + char * s = PyString_AsString( e ); + if ( !s ) { - printf("Invalid parameter type passed from Python\n"); - exit(1); + printf( "Invalid parameter type passed from Python\n" ); + exit( 1 ); } - l = list_new(l, newstr(s)); - Py_DECREF(e); + l = list_new( l, newstr( s ) ); + Py_DECREF( e ); } - lol_add(inner->args, l); - } + lol_add( inner->args, l ); + } } } @@ -1669,170 +1665,260 @@ bjam_call(PyObject* self, PyObject* args) frame_free( inner ); - Py_INCREF(Py_None); - return Py_None; + /* Convert the bjam list into a Python list result. */ + { + PyObject * pyResult = PyList_New( list_length( result ) ); + int i = 0; + while ( result ) + { + PyList_SetItem( pyResult, i, PyString_FromString( result->string ) ); + result = list_next( result ); + i += 1; + } + list_free( result ); + return pyResult; + } } -/** Accepts three arguments: module name, rule name and Python callable. - Creates bjam rule with the specified name in the specified module, - which will invoke the Python callable. -*/ -PyObject* -bjam_import_rule(PyObject* self, PyObject* args) +/* + * Accepts three arguments: module name, rule name and Python callable. Creates + * a bjam rule with the specified name in the specified module, which will + * invoke the Python callable. + */ + +PyObject * bjam_import_rule( PyObject * self, PyObject * args ) { - char* module; - char* rule; - PyObject* func; - module_t* m; - RULE* r; + char * module; + char * rule; + PyObject * func; + module_t * m; + RULE * r; - if (!PyArg_ParseTuple(args, "ssO:import_rule", &module, &rule, &func)) + if ( !PyArg_ParseTuple( args, "ssO:import_rule", &module, &rule, &func ) ) return NULL; - - if (!PyCallable_Check(func)) + + if ( !PyCallable_Check( func ) ) { - PyErr_SetString(PyExc_RuntimeError, - "Non-callable object passed to bjam.import_rule"); + PyErr_SetString( PyExc_RuntimeError, + "Non-callable object passed to bjam.import_rule" ); return NULL; } - - m = bindmodule(module); - r = bindrule(rule, m); - /* Make pFunc owned */ - Py_INCREF(func); + m = bindmodule( *module ? module : 0 ); + r = bindrule( rule, m ); + + /* Make pFunc owned. */ + Py_INCREF( func ); r->python_function = func; - Py_INCREF(Py_None); + Py_INCREF( Py_None ); return Py_None; } -/* Accepts four arguments: - - an action name - - an action body - - a list of variable that will be bound inside the action - - integer flags. - Defines an action on bjam side. -*/ -PyObject* -bjam_define_action(PyObject* self, PyObject *args) -{ - char* name; - char* body; - module_t* m; - PyObject *bindlist_python; - int flags; - LIST *bindlist = L0; - int n; - int i; +/* + * Accepts four arguments: + * - an action name + * - an action body + * - a list of variable that will be bound inside the action + * - integer flags. + * Defines an action on bjam side. + */ - if (!PyArg_ParseTuple(args, "ssO!i:define_action", &name, &body, - &PyList_Type, &bindlist_python, &flags)) +PyObject * bjam_define_action( PyObject * self, PyObject * args ) +{ + char * name; + char * body; + module_t * m; + PyObject * bindlist_python; + int flags; + LIST * bindlist = L0; + int n; + int i; + + if ( !PyArg_ParseTuple( args, "ssO!i:define_action", &name, &body, + &PyList_Type, &bindlist_python, &flags ) ) return NULL; - - n = PyList_Size (bindlist_python); - for (i = 0; i < n; ++i) + + n = PyList_Size( bindlist_python ); + for ( i = 0; i < n; ++i ) { - PyObject *next = PyList_GetItem(bindlist_python, i); - if (!PyString_Check(next)) + PyObject * next = PyList_GetItem( bindlist_python, i ); + if ( !PyString_Check( next ) ) { - PyErr_SetString(PyExc_RuntimeError, - "bind list has non-string type"); + PyErr_SetString( PyExc_RuntimeError, + "bind list has non-string type" ); return NULL; } - bindlist = list_new(bindlist, PyString_AsString(next)); + bindlist = list_new( bindlist, PyString_AsString( next ) ); } - new_rule_actions(root_module(), name, newstr(body), bindlist, flags); + new_rule_actions( root_module(), name, newstr( body ), bindlist, flags ); - Py_INCREF(Py_None); - return Py_None; + Py_INCREF( Py_None ); + return Py_None; } -/* Returns the value of a variable in root Jam module. */ -PyObject* -bjam_variable(PyObject* self, PyObject* args) -{ - char *name; - LIST* value; - PyObject *result; - int i; - if (!PyArg_ParseTuple(args, "s", &name)) +/* + * Returns the value of a variable in root Jam module. + */ + +PyObject * bjam_variable( PyObject * self, PyObject * args ) +{ + char * name; + LIST * value; + PyObject * result; + int i; + + if ( !PyArg_ParseTuple( args, "s", &name ) ) return NULL; - enter_module(root_module()); - value = var_get(name); - exit_module(root_module()); + enter_module( root_module() ); + value = var_get( name ); + exit_module( root_module() ); - result = PyList_New(list_length(value)); - for (i = 0; value; value = list_next(value), ++i) - PyList_SetItem(result, i, PyString_FromString(value->string)); + result = PyList_New( list_length( value ) ); + for ( i = 0; value; value = list_next( value ), ++i ) + PyList_SetItem( result, i, PyString_FromString( value->string ) ); return result; } -PyObject* -bjam_backtrace(PyObject* self, PyObject *args) -{ - PyObject *result = PyList_New(0); - struct frame *f = frame_before_python_call; - for(; f = f->prev;) +PyObject * bjam_backtrace( PyObject * self, PyObject * args ) +{ + PyObject * result = PyList_New( 0 ); + struct frame * f = frame_before_python_call; + + for ( ; f = f->prev; ) { - PyObject *tuple = PyTuple_New(4); - char* file; - int line; - char buf[32]; + PyObject * tuple = PyTuple_New( 4 ); + char * file; + int line; + char buf[ 32 ]; + get_source_line( f->procedure, &file, &line ); sprintf( buf, "%d", line ); - - /* PyTuple_SetItem steals reference. */ - PyTuple_SetItem(tuple, 0, PyString_FromString(file)); - PyTuple_SetItem(tuple, 1, PyString_FromString(buf)); - PyTuple_SetItem(tuple, 2, PyString_FromString(f->module->name)); - PyTuple_SetItem(tuple, 3, PyString_FromString(f->rulename)); - PyList_Append(result, tuple); - Py_DECREF(tuple); + /* PyTuple_SetItem steals reference. */ + PyTuple_SetItem( tuple, 0, PyString_FromString( file ) ); + PyTuple_SetItem( tuple, 1, PyString_FromString( buf ) ); + PyTuple_SetItem( tuple, 2, PyString_FromString( f->module->name ) ); + PyTuple_SetItem( tuple, 3, PyString_FromString( f->rulename ) ); + + PyList_Append( result, tuple ); + Py_DECREF( tuple ); } return result; } -#endif +#endif /* #ifdef HAVE_PYTHON */ + #ifdef HAVE_POPEN + #if defined(_MSC_VER) || defined(__BORLANDC__) - #define popen _popen + #define popen windows_popen_wrapper #define pclose _pclose + + /* + * This wrapper is a workaround for a funny _popen() feature on Windows + * where it eats external quotes in some cases. The bug seems to be related + * to the quote stripping functionality used by the Windows cmd.exe + * interpreter when its /S is not specified. + * + * Cleaned up quote from the cmd.exe help screen as displayed on Windows XP + * SP3: + * + * 1. If all of the following conditions are met, then quote characters on + * the command line are preserved: + * + * - no /S switch + * - exactly two quote characters + * - no special characters between the two quote characters, where + * special is one of: &<>()@^| + * - there are one or more whitespace characters between the two quote + * characters + * - the string between the two quote characters is the name of an + * executable file. + * + * 2. Otherwise, old behavior is to see if the first character is a quote + * character and if so, strip the leading character and remove the last + * quote character on the command line, preserving any text after the + * last quote character. + * + * This causes some commands containing quotes not to be executed correctly. + * For example: + * + * "\Long folder name\aaa.exe" --name="Jurko" --no-surname + * + * would get its outermost quotes stripped and would be executed as: + * + * \Long folder name\aaa.exe" --name="Jurko --no-surname + * + * which would report an error about '\Long' not being a valid command. + * + * cmd.exe help seems to indicate it would be enough to add an extra space + * character in front of the command to avoid this but this does not work, + * most likely due to the shell first stripping all leading whitespace + * characters from the command. + * + * Solution implemented here is to quote the whole command in case it + * contains any quote characters. Note thought this will not work correctly + * should Windows ever 'fix' this feature. + * (03.06.2008.) (Jurko) + */ + static FILE * windows_popen_wrapper( char * command, char * mode ) + { + int extra_command_quotes_needed = ( strchr( command, '"' ) != 0 ); + string quoted_command; + FILE * result; + + if ( extra_command_quotes_needed ) + { + string_new( "ed_command ); + string_append( "ed_command, "\"" ); + string_append( "ed_command, command ); + string_append( "ed_command, "\"" ); + command = quoted_command.value; + } + + result = _popen( command, "r" ); + + if ( extra_command_quotes_needed ) + string_free( "ed_command ); + + return result; + } #endif -LIST *builtin_shell( PARSE *parse, FRAME *frame ) + +LIST * builtin_shell( PARSE * parse, FRAME * frame ) { - LIST* command = lol_get( frame->args, 0 ); - LIST* result = 0; - string s; - int ret; - char buffer[1024]; - FILE *p = NULL; - int exit_status = -1; - int exit_status_opt = 0; - int no_output_opt = 0; - + LIST * command = lol_get( frame->args, 0 ); + LIST * result = 0; + string s; + int ret; + char buffer[ 1024 ]; + FILE * p = NULL; + int exit_status = -1; + int exit_status_opt = 0; + int no_output_opt = 0; + /* Process the variable args options. */ { int a = 1; LIST * arg = lol_get( frame->args, a ); while ( arg ) { - if ( strcmp("exit-status", arg->string) == 0 ) + if ( strcmp( "exit-status", arg->string ) == 0 ) { exit_status_opt = 1; } - else if ( strcmp("no-output", arg->string) == 0 ) + else if ( strcmp( "no-output", arg->string ) == 0 ) { no_output_opt = 1; } @@ -1840,44 +1926,48 @@ LIST *builtin_shell( PARSE *parse, FRAME *frame ) } } - string_new( &s ); + /* The following fflush() call seems to be indicated as a workaround for a + * popen() bug on POSIX implementations related to synhronizing input + * stream positions for the called and the calling process. + */ + fflush( NULL ); - fflush(NULL); - - p = popen(command->string, "r"); + p = popen( command->string, "r" ); if ( p == NULL ) return L0; - while ( (ret = fread(buffer, sizeof(char), sizeof(buffer)-1, p)) > 0 ) + string_new( &s ); + + while ( ( ret = fread( buffer, sizeof( char ), sizeof( buffer ) - 1, p ) ) > 0 ) { buffer[ret] = 0; - if ( ! no_output_opt ) + if ( !no_output_opt ) { string_append( &s, buffer ); } } - exit_status = pclose(p); + exit_status = pclose( p ); /* The command output is returned first. */ - result = list_new( L0, newstr(s.value) ); - string_free(&s); - + result = list_new( L0, newstr( s.value ) ); + string_free( &s ); + /* The command exit result next. */ if ( exit_status_opt ) { - sprintf (buffer, "%d", exit_status); + sprintf( buffer, "%d", exit_status ); result = list_new( result, newstr( buffer ) ); } - + return result; } -#else +#else /* #ifdef HAVE_POPEN */ -LIST *builtin_shell( PARSE *parse, FRAME *frame ) +LIST * builtin_shell( PARSE * parse, FRAME * frame ) { return L0; } -#endif +#endif /* #ifdef HAVE_POPEN */ diff --git a/src/engine/class.c b/src/engine/class.c index fddb634ef..ff4ec5680 100644 --- a/src/engine/class.c +++ b/src/engine/class.c @@ -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; } diff --git a/src/engine/command.c b/src/engine/command.c index ef8830601..d2ea06814 100644 --- a/src/engine/command.c +++ b/src/engine/command.c @@ -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 +#include -# include "command.h" -# include -# include /* * 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 ); } diff --git a/src/engine/command.h b/src/engine/command.h index 6e4752ffe..ddd38e689 100644 --- a/src/engine/command.h +++ b/src/engine/command.h @@ -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 ) diff --git a/src/engine/compile.c b/src/engine/compile.c index 4d64bb987..6cc6970fa 100644 --- a/src/engine/compile.c +++ b/src/engine/compile.c @@ -38,20 +38,20 @@ * External routines: * * compile_append() - append list results of two statements - * compile_eval() - evaluate if to determine which leg to compile + * compile_eval() - evaluate if to determine which leg to compile * compile_foreach() - compile the "for x in y" statement * compile_if() - compile 'if' rule * compile_while() - compile 'while' rule * compile_include() - support for 'include' - call include() on file - * compile_list() - expand and return a list + * compile_list() - expand and return a list * compile_local() - declare (and set) local variables * compile_null() - do nothing -- a stub for parsing * compile_on() - run rule under influence of on-target variables * compile_rule() - compile a single user defined rule * compile_rules() - compile a chain of rules * compile_set() - compile the "set variable" statement - * compile_setcomp() - support for `rule` - save parse tree - * compile_setexec() - support for `actions` - save execution string + * compile_setcomp() - support for `rule` - save parse tree + * compile_setexec() - support for `actions` - save execution string * compile_settings() - compile the "on =" (set variable on exec) statement * compile_switch() - compile 'switch' rule * @@ -65,7 +65,7 @@ * builtin_exit() - EXIT rule * builtin_flags() - NOCARE, NOTFILE, TEMPORARY rule * - * 02/03/94 (seiwald) - Changed trace output to read "setting" instead of + * 02/03/94 (seiwald) - Changed trace output to read "setting" instead of * the awkward sounding "settings". * 04/12/94 (seiwald) - Combined build_depends() with build_includes(). * 04/12/94 (seiwald) - actionlist() now just appends a single action. @@ -93,8 +93,7 @@ void backtrace( FRAME *frame ); void backtrace_line( FRAME *frame ); void print_source_line( PARSE* p ); - -struct frame *frame_before_python_call; +struct frame * frame_before_python_call; void frame_init( FRAME* frame ) { @@ -106,11 +105,13 @@ void frame_init( FRAME* frame ) frame->procedure = 0; } + void frame_free( FRAME* frame ) { lol_free( frame->args ); } + /* * compile_append() - append list results of two statements * @@ -118,131 +119,112 @@ void frame_free( FRAME* frame ) * parse->right single rule */ -LIST * -compile_append( - PARSE *parse, - FRAME *frame ) +LIST * compile_append( PARSE * parse, FRAME * frame ) { /* Append right to left. */ - - return list_append( + return list_append( parse_evaluate( parse->left, frame ), parse_evaluate( parse->right, frame ) ); } + /* * compile_eval() - evaluate if to determine which leg to compile * * Returns: - * list if expression true - compile 'then' clause - * L0 if expression false - compile 'else' clause + * list if expression true - compile 'then' clause + * L0 if expression false - compile 'else' clause */ -static int -lcmp( LIST *t, LIST *s ) +static int lcmp( LIST * t, LIST * s ) { - int status = 0; + int status = 0; - while( !status && ( t || s ) ) - { - char *st = t ? t->string : ""; - char *ss = s ? s->string : ""; + while ( !status && ( t || s ) ) + { + char *st = t ? t->string : ""; + char *ss = s ? s->string : ""; - status = strcmp( st, ss ); + status = strcmp( st, ss ); - t = t ? list_next( t ) : t; - s = s ? list_next( s ) : s; - } + t = t ? list_next( t ) : t; + s = s ? list_next( s ) : s; + } - return status; + return status; } -LIST * -compile_eval( - PARSE *parse, - FRAME *frame ) +LIST * compile_eval( PARSE * parse, FRAME * frame ) { - LIST *ll, *lr, *s, *t; - int status = 0; + LIST * ll; + LIST * lr; + LIST * s; + LIST * t; + int status = 0; - /* Short circuit lr eval for &&, ||, and 'in' */ + /* Short circuit lr eval for &&, ||, and 'in'. */ - ll = parse_evaluate( parse->left, frame ); - lr = 0; + ll = parse_evaluate( parse->left, frame ); + lr = 0; - switch( parse->num ) - { - case EXPR_AND: - case EXPR_IN: if( ll ) goto eval; break; - case EXPR_OR: if( !ll ) goto eval; break; - default: eval: lr = parse_evaluate( parse->right, frame ); - } + switch ( parse->num ) + { + case EXPR_AND: + case EXPR_IN : if ( ll ) goto eval; break; + case EXPR_OR : if ( !ll ) goto eval; break; + default: eval: lr = parse_evaluate( parse->right, frame ); + } - /* Now eval */ + /* Now eval. */ + switch ( parse->num ) + { + case EXPR_NOT: if ( !ll ) status = 1; break; + case EXPR_AND: if ( ll && lr ) status = 1; break; + case EXPR_OR : if ( ll || lr ) status = 1; break; - switch( parse->num ) - { - case EXPR_NOT: - if( !ll ) status = 1; - break; + case EXPR_IN: + /* "a in b": make sure each of ll is equal to something in lr. */ + for ( t = ll; t; t = list_next( t ) ) + { + for ( s = lr; s; s = list_next( s ) ) + if ( !strcmp( t->string, s->string ) ) + break; + if ( !s ) break; + } + /* No more ll? Success. */ + if ( !t ) status = 1; + break; - case EXPR_AND: - if( ll && lr ) status = 1; - break; + case EXPR_EXISTS: if ( lcmp( ll, L0 ) != 0 ) status = 1; break; + case EXPR_EQUALS: if ( lcmp( ll, lr ) == 0 ) status = 1; break; + case EXPR_NOTEQ : if ( lcmp( ll, lr ) != 0 ) status = 1; break; + case EXPR_LESS : if ( lcmp( ll, lr ) < 0 ) status = 1; break; + case EXPR_LESSEQ: if ( lcmp( ll, lr ) <= 0 ) status = 1; break; + case EXPR_MORE : if ( lcmp( ll, lr ) > 0 ) status = 1; break; + case EXPR_MOREEQ: if ( lcmp( ll, lr ) >= 0 ) status = 1; break; + } - case EXPR_OR: - if( ll || lr ) status = 1; - break; + if ( DEBUG_IF ) + { + debug_compile( 0, "if", frame ); + list_print( ll ); + printf( "(%d) ", status ); + list_print( lr ); + printf( "\n" ); + } - case EXPR_IN: - /* "a in b": make sure each of */ - /* ll is equal to something in lr. */ + /* Find something to return. */ + /* In odd circumstances (like "" = "") */ + /* we'll have to return a new string. */ - for( t = ll; t; t = list_next( t ) ) - { - for( s = lr; s; s = list_next( s ) ) - if( !strcmp( t->string, s->string ) ) - break; - if( !s ) break; - } + if ( !status ) t = 0; + else if ( ll ) t = ll, ll = 0; + else if ( lr ) t = lr, lr = 0; + else t = list_new( L0, newstr( "1" ) ); - /* No more ll? Success */ - - if( !t ) status = 1; - - break; - - case EXPR_EXISTS: if( lcmp( ll, L0 ) != 0 ) status = 1; break; - case EXPR_EQUALS: if( lcmp( ll, lr ) == 0 ) status = 1; break; - case EXPR_NOTEQ: if( lcmp( ll, lr ) != 0 ) status = 1; break; - case EXPR_LESS: if( lcmp( ll, lr ) < 0 ) status = 1; break; - case EXPR_LESSEQ: if( lcmp( ll, lr ) <= 0 ) status = 1; break; - case EXPR_MORE: if( lcmp( ll, lr ) > 0 ) status = 1; break; - case EXPR_MOREEQ: if( lcmp( ll, lr ) >= 0 ) status = 1; break; - - } - - if( DEBUG_IF ) - { - debug_compile( 0, "if", frame ); - list_print( ll ); - printf( "(%d) ", status ); - list_print( lr ); - printf( "\n" ); - } - - /* Find something to return. */ - /* In odd circumstances (like "" = "") */ - /* we'll have to return a new string. */ - - if( !status ) t = 0; - else if( ll ) t = ll, ll = 0; - else if( lr ) t = lr, lr = 0; - else t = list_new( L0, newstr( "1" ) ); - - if( ll ) list_free( ll ); - if( lr ) list_free( lr ); - return t; + if ( ll ) list_free( ll ); + if ( lr ) list_free( lr ); + return t; } @@ -257,37 +239,32 @@ compile_eval( * parse->right rule to compile */ -LIST * -compile_foreach( - PARSE *parse, - FRAME *frame ) +LIST * compile_foreach( PARSE * parse, FRAME * frame ) { - LIST *nv = parse_evaluate( parse->left, frame ); - LIST *l; - SETTINGS *s = 0; - - if ( parse->num ) - { - s = addsettings( s, VAR_SET, parse->string, L0 ); - pushsettings( s ); - } + LIST * nv = parse_evaluate( parse->left, frame ); + LIST * l; + SETTINGS * s = 0; + + if ( parse->num ) + { + s = addsettings( s, VAR_SET, parse->string, L0 ); + pushsettings( s ); + } /* Call var_set to reset $(parse->string) for each val. */ - for( l = nv; l; l = list_next( l ) ) + for ( l = nv; l; l = list_next( l ) ) { - LIST *val = list_new( L0, copystr( l->string ) ); - + LIST * val = list_new( L0, copystr( l->string ) ); var_set( parse->string, val, VAR_SET ); - list_free( parse_evaluate( parse->right, frame ) ); } - if ( parse->num ) - { - popsettings( s ); - freesettings( s ); - } + if ( parse->num ) + { + popsettings( s ); + freesettings( s ); + } list_free( nv ); @@ -302,34 +279,26 @@ compile_foreach( * parse->third else tree */ -LIST * -compile_if( - PARSE *p, - FRAME *frame ) +LIST * compile_if( PARSE * p, FRAME * frame ) { - LIST *l = parse_evaluate( p->left, frame ); - if( l ) + LIST * l = parse_evaluate( p->left, frame ); + if ( l ) { list_free( l ); return parse_evaluate( p->right, frame ); } - else - { - return parse_evaluate( p->third, frame ); - } + return parse_evaluate( p->third, frame ); } -LIST * -compile_while( - PARSE *p, - FRAME *frame ) + +LIST * compile_while( PARSE * p, FRAME * frame ) { - LIST *r = 0; - LIST *l; - while ( l = parse_evaluate( p->left, frame ) ) + LIST * r = 0; + LIST * l; + while ( ( l = parse_evaluate( p->left, frame ) ) ) { list_free( l ); - if( r ) list_free( r ); + if ( r ) list_free( r ); r = parse_evaluate( p->right, frame ); } return r; @@ -342,38 +311,36 @@ compile_while( * parse->left list of files to include (can only do 1) */ -LIST * -compile_include( - PARSE *parse, - FRAME *frame ) +LIST * compile_include( PARSE * parse, FRAME * frame ) { - LIST *nt = parse_evaluate( parse->left, frame ); + LIST * nt = parse_evaluate( parse->left, frame ); - if( DEBUG_COMPILE ) + if ( DEBUG_COMPILE ) { debug_compile( 0, "include", frame); list_print( nt ); printf( "\n" ); } - if( nt ) + if ( nt ) { - TARGET *t = bindtarget( nt->string ); + TARGET * t = bindtarget( nt->string ); + + /* DWA 2001/10/22 - Perforce Jam cleared the arguments here, which + * prevents an included file from being treated as part of the body of a + * rule. I did not see any reason to do that, so I lifted the + * restriction. + */ - /* DWA 2001/10/22 - Perforce Jam clears the arguments here, which - * prevents an included file from being treated as part of the body - * of a rule. I didn't see any reason to do that, so I lifted the - * restriction. - */ - /* Bind the include file under the influence of */ /* "on-target" variables. Though they are targets, */ /* include files are not built with make(). */ pushsettings( t->settings ); /* We don't expect that file to be included is generated by some - action. Therefore, pass 0 as third argument. */ - t->boundname = search( t->name, &t->time, 0 ); + action. Therefore, pass 0 as third argument. + If the name resolves to directory, let it error out. */ + t->boundname = search( t->name, &t->time, 0, 0 ); popsettings( t->settings ); parse_file( t->boundname, frame ); @@ -396,9 +363,9 @@ static LIST* evaluate_in_module ( char* module_name, PARSE * p, FRAME* frame) exit_module( outer_module ); enter_module( frame->module ); } - + result = parse_evaluate( p, frame ); - + if ( outer_module != frame->module ) { exit_module( frame->module ); @@ -409,98 +376,87 @@ static LIST* evaluate_in_module ( char* module_name, PARSE * p, FRAME* frame) return result; } -LIST * -compile_module( - PARSE *p, - FRAME *frame ) + +LIST * compile_module( PARSE * p, FRAME * frame ) { - /* Here we are entering a module declaration block. - */ - LIST* module_name = parse_evaluate( p->left, frame ); - LIST* result = evaluate_in_module( module_name ? module_name->string : 0, + /* Here we are entering a module declaration block. */ + LIST * module_name = parse_evaluate( p->left, frame ); + LIST * result = evaluate_in_module( module_name ? module_name->string : 0, p->right, frame ); - list_free( module_name ); return result; } -LIST * -compile_class( - PARSE *p, - FRAME *frame ) + +LIST * compile_class( PARSE * p, FRAME * frame ) { /** Todo: check for empty class name. Check for class redeclaration. */ - char* class_module = 0; + char * class_module = 0; - LIST* name = parse_evaluate( p->left->right, frame ); - LIST* bases = 0; + LIST * name = parse_evaluate( p->left->right, frame ); + LIST * bases = 0; - if (p->left->left) + if ( p->left->left ) bases = parse_evaluate( p->left->left->right, frame ); - class_module = make_class_module(name, bases, frame); + class_module = make_class_module( name, bases, frame ); evaluate_in_module( class_module, p->right, frame ); - return L0; + return L0; } /* - * compile_list() - expand and return a list + * compile_list() - expand and return a list. * - * parse->string - character string to expand + * parse->string - character string to expand. */ -LIST * -compile_list( - PARSE *parse, - FRAME *frame ) +LIST * compile_list( PARSE * parse, FRAME * frame ) { - /* voodoo 1 means: s is a copyable string */ - char *s = parse->string; + /* s is a copyable string */ + char * s = parse->string; return var_expand( L0, s, s + strlen( s ), frame->args, 1 ); } + /* - * compile_local() - declare (and set) local variables + * compile_local() - declare (and set) local variables. * - * parse->left list of variables - * parse->right list of values - * parse->third rules to execute + * parse->left list of variables + * parse->right list of values + * parse->third rules to execute */ -LIST * -compile_local( - PARSE *parse, - FRAME *frame ) +LIST * compile_local( PARSE * parse, FRAME * frame ) { - LIST *l; - SETTINGS *s = 0; - LIST *nt = parse_evaluate( parse->left, frame ); - LIST *ns = parse_evaluate( parse->right, frame ); - LIST *result; + LIST * l; + SETTINGS * s = 0; + LIST * nt = parse_evaluate( parse->left, frame ); + LIST * ns = parse_evaluate( parse->right, frame ); + LIST * result; - if( DEBUG_COMPILE ) + if ( DEBUG_COMPILE ) { - debug_compile( 0, "local", frame); + debug_compile( 0, "local", frame ); list_print( nt ); printf( " = " ); list_print( ns ); printf( "\n" ); } - /* Initial value is ns */ - - for( l = nt; l; l = list_next( l ) ) - s = addsettings( s, VAR_SET, l->string, list_copy( (LIST*)0, ns ) ); + /* Initial value is ns. */ + for ( l = nt; l; l = list_next( l ) ) + s = addsettings( s, VAR_SET, l->string, list_copy( (LIST *)0, ns ) ); list_free( ns ); list_free( nt ); - /* Note that callees of the current context get this "local" */ - /* variable, making it not so much local as layered. */ + /* Note that callees of the current context get this "local" variable, + * making it not so much local as layered. + */ pushsettings( s ); result = parse_evaluate( parse->third, frame ); @@ -511,100 +467,86 @@ compile_local( return result; } + /* - * compile_null() - do nothing -- a stub for parsing + * compile_null() - do nothing -- a stub for parsing. */ -LIST * -compile_null( - PARSE *parse, - FRAME *frame ) +LIST * compile_null( PARSE * parse, FRAME * frame ) { return L0; } + /* * compile_on() - run rule under influence of on-target variables * - * parse->left list of files to include (can only do 1) - * parse->right rule to run + * parse->left list of files to include (can only do 1). + * parse->right rule to run. * * EXPERIMENTAL! */ -LIST * -compile_on( - PARSE *parse, - FRAME *frame ) +LIST * compile_on( PARSE * parse, FRAME * frame ) { - LIST *nt = parse_evaluate( parse->left, frame ); - LIST *result = 0; + LIST * nt = parse_evaluate( parse->left, frame ); + LIST * result = 0; - if( DEBUG_COMPILE ) - { - debug_compile( 0, "on", frame ); - list_print( nt ); - printf( "\n" ); - } + if ( DEBUG_COMPILE ) + { + debug_compile( 0, "on", frame ); + list_print( nt ); + printf( "\n" ); + } - if( nt ) - { - TARGET *t = bindtarget( nt->string ); - pushsettings( t->settings ); + if ( nt ) + { + TARGET * t = bindtarget( nt->string ); + pushsettings( t->settings ); + result = parse_evaluate( parse->right, frame ); + popsettings( t->settings ); + } - result = parse_evaluate( parse->right, frame ); - - popsettings( t->settings ); - } - - list_free( nt ); - - return result; -} - - -/* - * compile_rule() - compile a single user defined rule - * - * parse->string name of user defined rule - * parse->left parameters (list of lists) to rule, recursing left - * - * Wrapped around evaluate_rule() so that headers() can share it. - */ - -LIST * -compile_rule( - PARSE *parse, - FRAME *frame ) -{ - FRAME inner[1]; - LIST *result; - PARSE *p; - - - /* Build up the list of arg lists */ - - frame_init( inner ); - inner->prev = frame; - inner->prev_user = frame->module->user_module ? frame : frame->prev_user; - inner->module = frame->module; /* This gets fixed up in evaluate_rule(), below */ - inner->procedure = parse; - - for( p = parse->left; p; p = p->left ) - lol_add( inner->args, parse_evaluate( p->right, frame ) ); - - /* And invoke rule */ - - result = evaluate_rule( parse->string, inner ); - - frame_free( inner ); + list_free( nt ); return result; } -static void argument_error( char* message, RULE* rule, FRAME* frame, LIST* arg ) + +/* + * compile_rule() - compile a single user defined rule. + * + * parse->string name of user defined rule. + * parse->left parameters (list of lists) to rule, recursing left. + * + * Wrapped around evaluate_rule() so that headers() can share it. + */ + +LIST * compile_rule( PARSE * parse, FRAME * frame ) { - LOL* actual = frame->args; + FRAME inner[ 1 ]; + LIST * result; + PARSE * p; + + /* Build up the list of arg lists. */ + frame_init( inner ); + inner->prev = frame; + inner->prev_user = frame->module->user_module ? frame : frame->prev_user; + inner->module = frame->module; /* This gets fixed up in evaluate_rule(), below. */ + inner->procedure = parse; + for ( p = parse->left; p; p = p->left ) + lol_add( inner->args, parse_evaluate( p->right, frame ) ); + + /* And invoke the rule. */ + result = evaluate_rule( parse->string, inner ); + frame_free( inner ); + return result; +} + + +static void argument_error( char * message, RULE * rule, FRAME * frame, LIST* arg ) +{ + LOL * actual = frame->args; assert( frame->procedure != 0 ); backtrace_line( frame->prev ); printf( "*** argument error\n* rule %s ( ", frame->rulename ); @@ -615,77 +557,88 @@ static void argument_error( char* message, RULE* rule, FRAME* frame, LIST* arg ) print_source_line( rule->procedure ); printf( "see definition of rule '%s' being called\n", rule->name ); backtrace( frame->prev ); - exit(1); + exit( 1 ); } -/* define delimiters for type check elements in argument lists (and - * return type specifications, eventually) + +/* Define delimiters for type check elements in argument lists (and return type + * specifications, eventually). */ # define TYPE_OPEN_DELIM '[' # define TYPE_CLOSE_DELIM ']' -/* is_type_name - true iff the given string represents a type check - * specification +/* + * is_type_name() - true iff the given string represents a type check + * specification. */ -static int -is_type_name( char* s ) + +static int is_type_name( char * s ) { - return s[0] == TYPE_OPEN_DELIM - && s[strlen(s) - 1] == TYPE_CLOSE_DELIM; + return ( s[ 0 ] == TYPE_OPEN_DELIM ) && + ( s[ strlen( s ) - 1 ] == TYPE_CLOSE_DELIM ); } + /* - * arg_modifier - if the next element of formal is a single character, - * return that; return 0 otherwise. Used to extract "*+?" modifiers - * from argument lists. + * arg_modifier - if the next element of formal is a single character, return + * that; return 0 otherwise. Used to extract "*+?" modifiers * from argument + * lists. */ -static char -arg_modifier( LIST* formal ) + +static char arg_modifier( LIST * formal ) { if ( formal->next ) { - char *next = formal->next->string; - if ( next && next[0] != 0 && next[1] == 0 ) - return next[0]; + char * next = formal->next->string; + if ( next && ( next[ 0 ] != 0 ) && ( next[ 1 ] == 0 ) ) + return next[ 0 ]; } return 0; } + /* - * type_check - checks that each element of values satisfies the - * requirements of type_name. + * type_check() - checks that each element of values satisfies the requirements + * of type_name. * - * caller - the frame of the rule calling the rule whose - * arguments are being checked + * caller - the frame of the rule calling the rule whose arguments are + * being checked * * called - the rule being called * - * arg_name - a list element containing the name of the argument - * being checked + * arg_name - a list element containing the name of the argument being + * checked */ -static void -type_check( char* type_name, LIST *values, FRAME* caller, RULE* called, LIST* arg_name ) -{ - static module_t *typecheck = 0; - /* if nothing to check, bail now */ +static void type_check +( + char * type_name, + LIST * values, + FRAME * caller, + RULE * called, + LIST * arg_name +) +{ + static module_t * typecheck = 0; + + /* If nothing to check, bail now. */ if ( !values || !type_name ) return; if ( !typecheck ) - typecheck = bindmodule(".typecheck"); + typecheck = bindmodule( ".typecheck" ); - /* if the checking rule can't be found, also bail */ + /* If the checking rule can not be found, also bail. */ { RULE checker_, *checker = &checker_; checker->name = type_name; - if ( !typecheck->rules || !hashcheck( typecheck->rules, (HASHDATA**)&checker ) ) + if ( !typecheck->rules || !hashcheck( typecheck->rules, (HASHDATA * *)&checker ) ) return; } - + exit_module( caller->module ); - + while ( values != 0 ) { LIST *error; @@ -699,14 +652,14 @@ type_check( char* type_name, LIST *values, FRAME* caller, RULE* called, LIST* ar /* Prepare the argument list */ lol_add( frame->args, list_new( L0, values->string ) ); error = evaluate_rule( type_name, frame ); - + exit_module( typecheck ); - + if ( error ) argument_error( error->string, called, caller, arg_name ); frame_free( frame ); - values = values->next; + values = values->next; } enter_module( caller->module ); @@ -719,21 +672,21 @@ static SETTINGS * collect_arguments( RULE* rule, FRAME* frame ) { SETTINGS *locals = 0; - - LOL* all_actual = frame->args; - LOL *all_formal = rule->arguments ? rule->arguments->data : 0; + + LOL * all_actual = frame->args; + LOL * all_formal = rule->arguments ? rule->arguments->data : 0; if ( all_formal ) /* Nothing to set; nothing to check */ { int max = all_formal->count > all_actual->count ? all_formal->count : all_actual->count; - + int n; for ( n = 0; n < max ; ++n ) { LIST *actual = lol_get( all_actual, n ); char *type_name = 0; - + LIST *formal; for ( formal = lol_get( all_formal, n ); formal; formal = formal->next ) { @@ -743,7 +696,7 @@ collect_arguments( RULE* rule, FRAME* frame ) { if ( type_name ) argument_error( "missing argument name before type name:", rule, frame, formal ); - + if ( !formal->next ) argument_error( "missing argument name after type name:", rule, frame, formal ); @@ -754,13 +707,13 @@ collect_arguments( RULE* rule, FRAME* frame ) LIST* value = 0; char modifier; LIST* arg_name = formal; /* hold the argument name for type checking */ - + /* Stop now if a variable number of arguments are specified */ if ( name[0] == '*' && name[1] == 0 ) return locals; modifier = arg_modifier( formal ); - + if ( !actual && modifier != '?' && modifier != '*' ) argument_error( "missing argument", rule, frame, formal ); @@ -771,11 +724,11 @@ collect_arguments( RULE* rule, FRAME* frame ) value = list_copy( 0, actual ); actual = 0; /* skip an extra element for the modifier */ - formal = formal->next; + formal = formal->next; break; case '?': /* skip an extra element for the modifier */ - formal = formal->next; + formal = formal->next; /* fall through */ default: if ( actual ) /* in case actual is missing */ @@ -784,13 +737,13 @@ collect_arguments( RULE* rule, FRAME* frame ) actual = actual->next; } } - + locals = addsettings( locals, VAR_SET, name, value ); type_check( type_name, value, frame, rule, arg_name ); type_name = 0; } } - + if ( actual ) { argument_error( "extra argument", rule, frame, actual ); @@ -800,65 +753,67 @@ collect_arguments( RULE* rule, FRAME* frame ) return locals; } -static int python_instance_number = 0; - RULE * enter_rule( char *rulename, module_t *target_module ); #ifdef HAVE_PYTHON + +static int python_instance_number = 0; + static LIST* call_python_function(RULE* r, FRAME* frame) { - LIST* result = 0; - PyObject* arguments = PyTuple_New(frame->args->count); + LIST * result = 0; + PyObject * arguments = PyTuple_New( frame->args->count ); int i ; - PyObject* py_result; + PyObject * py_result; - for(i = 0; i < frame->args->count; ++i) + for ( i = 0; i < frame->args->count; ++i ) { - PyObject* arg = PyList_New(0); + PyObject * arg = PyList_New(0); LIST* l = lol_get( frame->args, i); - for(; l; l = l->next) + for ( ; l; l = l->next ) { - PyObject* v = PyString_FromString(l->string); + PyObject * v = PyString_FromString(l->string); /* Steals reference to 'v' */ - PyList_Append(arg, v); + PyList_Append( arg, v ); } /* Steals reference to 'arg' */ - PyTuple_SetItem(arguments, i, arg); + PyTuple_SetItem( arguments, i, arg ); } frame_before_python_call = frame; - py_result = PyObject_CallObject(r->python_function, arguments); - Py_DECREF(arguments); - if (py_result != NULL) { - - if (PyList_Check(py_result)) { - int size = PyList_Size(py_result); + py_result = PyObject_CallObject( r->python_function, arguments ); + Py_DECREF( arguments ); + if ( py_result != NULL ) + { + if ( PyList_Check( py_result ) ) + { + int size = PyList_Size( py_result ); int i; - for(i = 0; i < size; ++i) + for ( i = 0; i < size; ++i ) { - PyObject* item = PyList_GetItem(py_result, i); - if (PyString_Check(item)) + PyObject * item = PyList_GetItem( py_result, i ); + if ( PyString_Check( item ) ) { - result = list_new(result, - newstr(PyString_AsString(item))); + result = list_new( result, + newstr( PyString_AsString( item ) ) ); } else { - fprintf(stderr, "Non-string object returned by Python call\n"); + fprintf( stderr, "Non-string object returned by Python call.\n" ); } } } - else if (PyInstance_Check(py_result)) + else if ( PyInstance_Check( py_result ) ) { static char instance_name[1000]; static char imported_method_name[1000]; - module_t* m; - PyObject* method; - PyObject* method_name = PyString_FromString("foo"); - RULE* r; + module_t * m; + PyObject * method; + PyObject * method_name = PyString_FromString("foo"); + RULE * r; fprintf(stderr, "Got instance!\n"); @@ -867,21 +822,21 @@ call_python_function(RULE* r, FRAME* frame) snprintf(imported_method_name, 1000, "pyinstance%d.foo", python_instance_number); ++python_instance_number; - + m = bindmodule(instance_name); /* This is expected to get bound method. */ method = PyObject_GetAttr(py_result, method_name); - + r = bindrule( imported_method_name, root_module() ); r->python_function = method; - result = list_new(0, newstr(instance_name)); + result = list_new(0, newstr(instance_name)); - Py_DECREF(method_name); + Py_DECREF( method_name ); } - else if (py_result == Py_None) + else if ( py_result == Py_None ) { result = L0; } @@ -890,19 +845,21 @@ call_python_function(RULE* r, FRAME* frame) fprintf(stderr, "Non-list object returned by Python call\n"); } - Py_DECREF(py_result); + Py_DECREF( py_result ); } - else { + else + { PyErr_Print(); fprintf(stderr,"Call failed\n"); } - + return result; } -module_t* python_module() + +module_t * python_module() { - static module_t* python = 0; + static module_t * python = 0; if ( !python ) python = bindmodule("__python__"); return python; @@ -910,28 +867,28 @@ module_t* python_module() #endif + /* - * evaluate_rule() - execute a rule invocation + * evaluate_rule() - execute a rule invocation. */ LIST * evaluate_rule( - char *rulename, - FRAME *frame ) + char * rulename, + FRAME * frame ) { - LIST *result = L0; - RULE *rule; - profile_frame prof[1]; - module_t *prev_module = frame->module; - - LIST *l; + LIST * result = L0; + RULE * rule; + profile_frame prof[1]; + module_t * prev_module = frame->module; + + LIST * l; { - LOL arg_context_, *arg_context = &arg_context_; + LOL arg_context_, * arg_context = &arg_context_; if ( !frame->prev ) lol_init(arg_context); else arg_context = frame->prev->args; - l = var_expand( L0, rulename, rulename+strlen(rulename), arg_context, 0 ); } @@ -947,38 +904,32 @@ evaluate_rule( rule = bindrule( l->string, frame->module ); #ifdef HAVE_PYTHON - if (rule->python_function) + if ( rule->python_function ) { - /* The below messing with modules is due to the - way modules are implemented in jam. - Suppose we're in module M1 now. The global - variable map actually holds 'M1' variables, - and M1->variables hold global variables. + /* The below messing with modules is due to the way modules are + * implemented in Jam. Suppose we are in module M1 now. The global + * variable map actually holds 'M1' variables, and M1->variables hold + * global variables. + * + * If we call Python right away, Python calls back Jam and then Jam + * does 'module M1 { }' then Jam will try to swap the current global + * variables with M1->variables. The result will be that global + * variables map will hold global variables, and any variable settings + * we do will go to the global module, not M1. + * + * By restoring basic state, where the global variable map holds global + * variable, we make sure any future 'module M1' entry will work OK. + */ - If we call Python right away, and then Python - call back Jam, and jam does: - - module M1 { } - - then jam will try to swap current global - variables with M1->variables. The result will - be that global variables map will hold - global variables, and any variables settings - we do will go to global module, not M1. - - By restoring basic state, where global - variable map hold global variable, we make - sure any fugure 'module M1' will work OK. */ - - LIST *result; - module_t *m = python_module(); + LIST * result; + module_t * m = python_module(); frame->module = m; - + exit_module( prev_module ); enter_module( m ); - result = call_python_function(rule, frame); + result = call_python_function( rule, frame ); exit_module( m ); enter_module ( prev_module ); @@ -987,117 +938,138 @@ evaluate_rule( } #endif - /* drop the rule name */ + /* Drop the rule name. */ l = list_pop_front( l ); - /* tack the rest of the expansion onto the front of the first argument */ + /* Tack the rest of the expansion onto the front of the first argument. */ frame->args->list[0] = list_append( l, lol_get( frame->args, 0 ) ); if ( DEBUG_COMPILE ) { - /* Try hard to indicate in which module the rule is going to execute */ + /* Try hard to indicate in which module the rule is going to execute. */ if ( rule->module != frame->module - && rule->procedure != 0 && strcmp(rulename, rule->procedure->rulename) ) + && rule->procedure != 0 && strcmp( rulename, rule->procedure->rulename ) ) { char buf[256] = ""; - strncat( buf, rule->module->name, sizeof(buf) - 1 ); - strncat( buf, rule->name, sizeof(buf) - 1 ); - debug_compile( 1, buf, frame); + strncat( buf, rule->module->name, sizeof( buf ) - 1 ); + strncat( buf, rule->name, sizeof( buf ) - 1 ); + debug_compile( 1, buf, frame ); } else { - debug_compile( 1, rulename, frame); + debug_compile( 1, rulename, frame ); } lol_print( frame->args ); printf( "\n" ); } - + if ( rule->procedure && rule->module != prev_module ) { - /* propagate current module to nested rule invocations */ + /* Propagate current module to nested rule invocations. */ frame->module = rule->module; - - /* swap variables */ + + /* Swap variables. */ exit_module( prev_module ); enter_module( rule->module ); } - - /* record current rule name in frame */ + + /* Record current rule name in frame. */ if ( rule->procedure ) { frame->rulename = rulename; - /* and enter record profile info */ + /* And enter record profile info. */ if ( DEBUG_PROFILE ) profile_enter( rule->procedure->rulename, prof ); } - /* Check traditional targets $(<) and sources $(>) */ - - if( !rule->actions && !rule->procedure ) + /* Check traditional targets $(<) and sources $(>). */ + if ( !rule->actions && !rule->procedure ) { backtrace_line( frame->prev ); printf( "rule %s unknown in module %s\n", rule->name, frame->module->name ); backtrace( frame->prev ); - exit(1); + exit( 1 ); } - /* If this rule will be executed for updating the targets */ - /* then construct the action for make(). */ - - if( rule->actions ) + /* If this rule will be executed for updating the targets then construct the + * action for make(). + */ + if ( rule->actions ) { - TARGETS *t; - ACTION *action; - - /* The action is associated with this instance of this rule */ + TARGETS * t; + ACTION * action; + /* The action is associated with this instance of this rule. */ action = (ACTION *)BJAM_MALLOC( sizeof( ACTION ) ); memset( (char *)action, '\0', sizeof( *action ) ); action->rule = rule; action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) ); action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) ); - - /* Make targets[1,N-1] depend on targets[0], to describe the multply - generated targets for the rule. Do it with includes, to reflect - non-build dependency. */ + + /* If we have a group of targets all being built using the same action + * then we must not allow any of them to be used as sources unless they + * had all already been built in the first place or their joined action + * has had a chance to finish its work and build all of them anew. + * + * Without this it might be possible, in case of a multi-process build, + * for their action, triggered by buiding one of the targets, to still + * be running when another target in the group reports as done in order + * to avoid triggering the same action again and gets used prematurely. + * + * As a quick-fix to achieve this effect we make all the targets list + * each other as 'included targets'. More precisely, we mark the first + * listed target as including all the other targets in the list and vice + * versa. This makes anyone depending on any of those targets implicitly + * depend on all of them, thus making sure none of those targets can be + * used as sources until all of them have been built. Note that direct + * dependencies could not have been used due to the 'circular + * dependency' issue. + * + * TODO: Although the current implementation solves the problem of one + * of the targets getting used before its action completes its work it + * also forces the action to run whenever any of the targets in the + * group is not up to date even though some of them might not actually + * be used by the targets being built. We should see how we can + * correctly recognize such cases and use that to avoid running the + * action if possible and not rebuild targets not actually depending on + * targets that are not up to date. + * + * TODO: Using the 'include' feature might have side-effects due to + * interaction with the actual 'inclusion scanning' system. This should + * be checked. + */ if ( action->targets ) { TARGET * t0 = action->targets->target; for ( t = action->targets->next; t; t = t->next ) { - TARGET * tn = t->target; - if ( !tn->includes ) - { - tn->includes = copytarget( tn ); - tn->includes->original_target = tn; - } - tn = tn->includes; - tn->depends = targetentry( tn->depends, t0 ); + target_include( t->target, t0 ); + target_include( t0, t->target ); } } - /* Append this action to the actions of each target */ - - for( t = action->targets; t; t = t->next ) + /* Append this action to the actions of each target. */ + for ( t = action->targets; t; t = t->next ) t->target->actions = actionlist( t->target->actions, action ); } - /* Now recursively compile any parse tree associated with this rule */ - /* refer/free to ensure rule not freed during use */ - - if( rule->procedure ) + /* Now recursively compile any parse tree associated with this rule. + * parse_refer()/parse_free() call pair added to ensure rule not freed + * during use. + */ + if ( rule->procedure ) { - SETTINGS *local_args = collect_arguments( rule, frame ); - PARSE *parse = rule->procedure; + SETTINGS * local_args = collect_arguments( rule, frame ); + PARSE * parse = rule->procedure; parse_refer( parse ); - + pushsettings( local_args ); result = parse_evaluate( parse, frame ); popsettings( local_args ); freesettings( local_args ); - + parse_free( parse ); } @@ -1110,88 +1082,87 @@ evaluate_rule( if ( DEBUG_PROFILE && rule->procedure ) profile_exit( prof ); - if( DEBUG_COMPILE ) + if ( DEBUG_COMPILE ) debug_compile( -1, 0, frame); return result; } + /* - * Call the given rule with the specified parameters. - * The parameters should be of LIST* and end with NULL pointer. - * This differs from the 'evaluate_rule' in that frame - * for called rule is prepared in 'call_rule'. + * Call the given rule with the specified parameters. The parameters should be + * of type LIST* and end with a NULL pointer. This differs from 'evaluate_rule' + * in that frame for the called rule is prepared inside 'call_rule'. * - * This function is usefull when builtin rule (in C) wants to - * call another rule, which might be implemented in Jam. + * This function is useful when a builtin rule (in C) wants to call another rule + * which might be implemented in Jam. */ -LIST *call_rule( char *rulename, FRAME* caller_frame, ...) + +LIST * call_rule( char * rulename, FRAME * caller_frame, ... ) { va_list va; - LIST *result; + LIST * result; FRAME inner[1]; frame_init( inner ); inner->prev = caller_frame; - inner->prev_user = caller_frame->module->user_module ? + inner->prev_user = caller_frame->module->user_module ? caller_frame : caller_frame->prev_user; - inner->module = caller_frame->module; + inner->module = caller_frame->module; inner->procedure = 0; - va_start(va, caller_frame); - for(;;) + va_start( va, caller_frame ); + for ( ; ; ) { - LIST* l = va_arg(va, LIST*); - if (!l) + LIST * l = va_arg( va, LIST* ); + if ( !l ) break; - lol_add(inner->args, l); + lol_add( inner->args, l ); } - va_end(va); - - result = evaluate_rule(rulename, inner); + va_end( va ); - frame_free(inner); + result = evaluate_rule( rulename, inner ); + + frame_free( inner ); return result; } + /* * compile_rules() - compile a chain of rules * - * parse->left single rule - * parse->right more compile_rules() by right-recursion + * parse->left single rule + * parse->right more compile_rules() by right-recursion */ -LIST * -compile_rules( - PARSE *parse, - FRAME *frame ) +LIST * compile_rules( PARSE * parse, FRAME * frame ) { /* Ignore result from first statement; return the 2nd. */ - /* Optimize recursion on the right by looping. */ - + /* Optimize recursion on the right by looping. */ do list_free( parse_evaluate( parse->left, frame ) ); - while( (parse = parse->right)->func == compile_rules ); - + while ( ( parse = parse->right )->func == compile_rules ); return parse_evaluate( parse, frame ); } + /* - * assign_var_mode() - convert ASSIGN_XXX compilation flag into - * corresponding VAR_XXX variable set flag. + * assign_var_mode() - convert ASSIGN_XXX compilation flag into corresponding + * VAR_XXX variable set flag. */ -static int assign_var_mode(int parsenum, const char **tracetext) + +static int assign_var_mode( int parsenum, char const * * tracetext ) { - const char *trace; - int setflag; - switch( parsenum ) + char const * trace; + int setflag; + switch ( parsenum ) { - case ASSIGN_SET: setflag = VAR_SET; trace = "="; break; - case ASSIGN_APPEND: setflag = VAR_APPEND; trace = "+="; break; + case ASSIGN_SET : setflag = VAR_SET ; trace = "=" ; break; + case ASSIGN_APPEND : setflag = VAR_APPEND ; trace = "+="; break; case ASSIGN_DEFAULT: setflag = VAR_DEFAULT; trace = "?="; break; - default: setflag = VAR_SET; trace = ""; break; + default: setflag = VAR_SET ; trace = "" ; break; } - if (tracetext) + if ( tracetext ) *tracetext = trace ; return setflag; } @@ -1200,117 +1171,102 @@ static int assign_var_mode(int parsenum, const char **tracetext) * compile_set() - compile the "set variable" statement * * parse->left variable names - * parse->right variable values + * parse->right variable values * parse->num ASSIGN_SET/APPEND/DEFAULT */ -LIST * -compile_set( - PARSE *parse, - FRAME *frame ) +LIST * compile_set( PARSE * parse, FRAME * frame ) { - LIST *nt = parse_evaluate( parse->left, frame ); - LIST *ns = parse_evaluate( parse->right, frame ); - LIST *l; - const char *trace; - int setflag = assign_var_mode( parse->num, &trace ); + LIST * nt = parse_evaluate( parse->left, frame ); + LIST * ns = parse_evaluate( parse->right, frame ); + LIST * l; + char const * trace; + int setflag = assign_var_mode( parse->num, &trace ); - if( DEBUG_COMPILE ) + if ( DEBUG_COMPILE ) { - debug_compile( 0, "set", frame); + debug_compile( 0, "set", frame ); list_print( nt ); printf( " %s ", trace ); list_print( ns ); printf( "\n" ); } - /* Call var_set to set variable */ - /* var_set keeps ns, so need to copy it */ - - for( l = nt; l; l = list_next( l ) ) + /* Call var_set to set variable. var_set keeps ns, so need to copy it. */ + for ( l = nt; l; l = list_next( l ) ) var_set( l->string, list_copy( L0, ns ), setflag ); - list_free( nt ); - return ns; } + /* - * compile_setcomp() - support for `rule` - save parse tree + * compile_setcomp() - support for `rule` - save parse tree. * - * parse->string rule name - * parse->left rules for rule - * parse->right optional list-of-lists describing arguments + * parse->string rule name + * parse->left rules for rule + * parse->right optional list-of-lists describing arguments */ -LIST * -compile_setcomp( - PARSE *parse, - FRAME *frame) +LIST * compile_setcomp( PARSE * parse, FRAME * frame ) { - argument_list* arg_list = 0; - - /* Create new LOL describing argument requirements if supplied */ + argument_list * arg_list = 0; + + /* Create new LOL describing argument requirements if supplied. */ if ( parse->right ) { - PARSE *p; + PARSE * p; arg_list = args_new(); - for( p = parse->right; p; p = p->left ) + for ( p = parse->right; p; p = p->left ) lol_add( arg_list->data, parse_evaluate( p->right, frame ) ); } - + new_rule_body( frame->module, parse->string, arg_list, parse->left, !parse->num ); return L0; } + /* - * compile_setexec() - support for `actions` - save execution string + * compile_setexec() - support for `actions` - save execution string. * * parse->string rule name * parse->string1 OS command string - * parse->num flags - * parse->left `bind` variables + * parse->num flags + * parse->left `bind` variables * - * Note that the parse flags (as defined in compile.h) are transfered - * directly to the rule flags (as defined in rules.h). + * Note that the parse flags (as defined in compile.h) are transferred directly + * to the rule flags (as defined in rules.h). */ -LIST * -compile_setexec( - PARSE *parse, - FRAME *frame ) +LIST * compile_setexec( PARSE * parse, FRAME * frame ) { - LIST* bindlist = parse_evaluate( parse->left, frame ); - + LIST * bindlist = parse_evaluate( parse->left, frame ); new_rule_actions( frame->module, parse->string, parse->string1, bindlist, parse->num ); - return L0; } + /* - * compile_settings() - compile the "on =" (set variable on exec) statement + * compile_settings() - compile the "on =" (set variable on exec) statement. * - * parse->left variable names - * parse->right target name - * parse->third variable value - * parse->num ASSIGN_SET/APPEND + * parse->left variable names + * parse->right target name + * parse->third variable value + * parse->num ASSIGN_SET/APPEND */ -LIST * -compile_settings( - PARSE *parse, - FRAME *frame ) +LIST * compile_settings( PARSE * parse, FRAME * frame ) { - LIST *nt = parse_evaluate( parse->left, frame ); - LIST *ns = parse_evaluate( parse->third, frame ); - LIST *targets = parse_evaluate( parse->right, frame ); - LIST *ts; - const char *trace; - int setflag = assign_var_mode( parse->num, &trace ); + LIST * nt = parse_evaluate( parse->left, frame ); + LIST * ns = parse_evaluate( parse->third, frame ); + LIST * targets = parse_evaluate( parse->right, frame ); + LIST * ts; + char const * trace; + int setflag = assign_var_mode( parse->num, &trace ); - if( DEBUG_COMPILE ) + if ( DEBUG_COMPILE ) { - debug_compile( 0, "set", frame); + debug_compile( 0, "set", frame ); list_print( nt ); printf( " on " ); list_print( targets ); @@ -1319,99 +1275,93 @@ compile_settings( printf( "\n" ); } - /* Call addsettings to save variable setting */ - /* addsettings keeps ns, so need to copy it */ - /* Pass append flag to addsettings() */ - - for( ts = targets; ts; ts = list_next( ts ) ) + /* Call addsettings() to save variable setting. addsettings() keeps ns, so + * need to copy it. Pass append flag to addsettings(). + */ + for ( ts = targets; ts; ts = list_next( ts ) ) { - TARGET *t = bindtarget( ts->string ); - LIST *l; + TARGET * t = bindtarget( ts->string ); + LIST * l; - for( l = nt; l; l = list_next( l ) ) - t->settings = addsettings( t->settings, setflag, - l->string, list_copy( (LIST*)0, ns ) ); + for ( l = nt; l; l = list_next( l ) ) + t->settings = addsettings( t->settings, setflag, l->string, + list_copy( (LIST *)0, ns ) ); } list_free( nt ); list_free( targets ); - return ns; } + /* - * compile_switch() - compile 'switch' rule + * compile_switch() - compile 'switch' rule. * - * parse->left switch value (only 1st used) - * parse->right cases + * parse->left switch value (only 1st used) + * parse->right cases * - * cases->left 1st case - * cases->right next cases + * cases->left 1st case + * cases->right next cases * - * case->string argument to match - * case->left parse tree to execute + * case->string argument to match + * case->left parse tree to execute */ -LIST * -compile_switch( - PARSE *parse, - FRAME *frame ) +LIST * compile_switch( PARSE * parse, FRAME * frame ) { - LIST *nt = parse_evaluate( parse->left, frame ); - LIST *result = 0; + LIST * nt = parse_evaluate( parse->left, frame ); + LIST * result = 0; - if( DEBUG_COMPILE ) + if ( DEBUG_COMPILE ) { - debug_compile( 0, "switch", frame); + debug_compile( 0, "switch", frame ); list_print( nt ); printf( "\n" ); } - /* Step through cases */ - - for( parse = parse->right; parse; parse = parse->right ) + /* Step through cases. */ + for ( parse = parse->right; parse; parse = parse->right ) { - if( !glob( parse->left->string, nt ? nt->string : "" ) ) + if ( !glob( parse->left->string, nt ? nt->string : "" ) ) { - /* Get & exec parse tree for this case */ - parse = parse->left->left; - result = parse_evaluate( parse, frame ); - break; + /* Get & exec parse tree for this case. */ + parse = parse->left->left; + result = parse_evaluate( parse, frame ); + break; } } list_free( nt ); - return result; } + /* * debug_compile() - printf with indent to show rule expansion. */ -static void -debug_compile( int which, char *s, FRAME* frame ) +static void debug_compile( int which, char * s, FRAME * frame ) { static int level = 0; static char indent[36] = ">>>>|>>>>|>>>>|>>>>|>>>>|>>>>|>>>>|"; if ( which >= 0 ) { - int i; - - print_source_line( frame->procedure ); - - i = (level+1)*2; - while ( i > 35 ) - { - printf( indent ); - i -= 35; - } + int i; - printf( "%*.*s ", i, i, indent ); + print_source_line( frame->procedure ); + + i = ( level + 1 ) * 2; + while ( i > 35 ) + { + fputs( indent, stdout ); + i -= 35; + } + + printf( "%*.*s ", i, i, indent ); } - if( s ) + if ( s ) printf( "%s ", s ); level += which; diff --git a/src/engine/compile.h b/src/engine/compile.h index f44e51ef4..7d5191f0e 100644 --- a/src/engine/compile.h +++ b/src/engine/compile.h @@ -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 diff --git a/src/engine/debug.c b/src/engine/debug.c index df8f4b6c5..7290555a7 100644 --- a/src/engine/debug.c +++ b/src/engine/debug.c @@ -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 -# include +#include +#include -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 ); } } diff --git a/src/engine/debug.h b/src/engine/debug.h index b417c1618..115a88735 100644 --- a/src/engine/debug.h +++ b/src/engine/debug.h @@ -6,8 +6,9 @@ #ifndef BJAM_DEBUG_H #define BJAM_DEBUG_H -# include "jam.h" -# include +#include "jam.h" +#include + 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 diff --git a/src/engine/execcmd.h b/src/engine/execcmd.h index c39341c30..67f2b839c 100644 --- a/src/engine/execcmd.h +++ b/src/engine/execcmd.h @@ -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 diff --git a/src/engine/execmac.c b/src/engine/execmac.c index 6fec44ae4..2ddddedd1 100644 --- a/src/engine/execmac.c +++ b/src/engine/execmac.c @@ -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 +#include "jam.h" +#include "lists.h" +#include "execcmd.h" +#include -# 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 */ diff --git a/src/engine/execnt.c b/src/engine/execnt.c index 41dd1dab4..764204518 100644 --- a/src/engine/execnt.c +++ b/src/engine/execnt.c @@ -11,24 +11,24 @@ * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) */ -# include "jam.h" -# include "lists.h" -# include "execcmd.h" -# include "pathsys.h" -# include "string.h" -# include "output.h" -# include -# include -# include -# include -# include +#include "jam.h" +#include "lists.h" +#include "execcmd.h" +#include "pathsys.h" +#include "string.h" +#include "output.h" +#include +#include +#include +#include +#include -# ifdef USE_EXECNT +#ifdef USE_EXECNT -# define WIN32_LEAN_AND_MEAN -# include -# include -# include +#define WIN32_LEAN_AND_MEAN +#include +#include +#include /* * execnt.c - execute a shell command on Windows NT @@ -41,7 +41,7 @@ * * 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. @@ -49,11 +49,11 @@ * Don't just set JAMSHELL to /bin/sh or cmd.exe - it won't work! * * External routines: - * execcmd() - launch an async command execution - * execwait() - wait and drive at most one execution completion + * 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 @@ -96,7 +96,7 @@ static void read_output(); static int try_kill_one(); /* */ static double creation_time(HANDLE); -/* Recursive check if first process is parent (directly or indirectly) of +/* Recursive check if first process is parent (directly or indirectly) of the second one. */ static int is_parent_child(DWORD, DWORD); /* */ @@ -108,45 +108,54 @@ static void close_alerts(); static int intr = 0; static int cmdsrunning = 0; -static void (*istat)( int ); +static void (* istat)( int ); -/* the list of commands we run */ + +/* The list of commands we run. */ static struct { - /* buffer to hold action */ - string action; - /* buffer to hold target */ - string target; - /* buffer to hold command being invoked */ - string command; - /* the temporary batch file of the action, when needed */ - char *tempfile_bat; - /* the pipes for the child process, parent reads from (0), - child writes to (1) */ - HANDLE pipe_out[2]; - HANDLE pipe_err[2]; - /* buffers to hold stdout and stderr, if any */ - string buffer_out; - string buffer_err; - /* running process info */ - PROCESS_INFORMATION pi; - /* when comand completes, the result value */ - DWORD exitcode; - /* function called when the command completes */ - void (*func)( void *closure, int status, timing_info*, char *, char * ); - void *closure; - /* when command completes, the reason it completed */ - int exit_reason; -} cmdtab[ MAXJOBS ] = {{0}}; + string action; /* buffer to hold action */ + string target; /* buffer to hold target */ + string command; /* buffer to hold command being invoked */ + + /* Temporary batch file used to execute the action when needed. */ + char * tempfile_bat; + + /* Pipes for communicating with the child process. Parent reads from (0), + * child writes to (1). + */ + HANDLE pipe_out[ 2 ]; + HANDLE pipe_err[ 2 ]; + + string buffer_out; /* buffer to hold stdout, if any */ + string buffer_err; /* buffer to hold stderr, if any */ + + PROCESS_INFORMATION pi; /* running process information */ + DWORD exit_code; /* executed command's exit code */ + int exit_reason; /* reason why a command completed */ + + /* Function called when the command completes. */ + void (* func)( void * closure, int status, timing_info *, char *, char * ); + + /* Opaque data passed back to the 'func' callback called when the command + * completes. + */ + void * closure; +} +cmdtab[ MAXJOBS ] = { { 0 } }; + + +/* + * Execution unit tests. + */ -/* execution unit tests */ void execnt_unit_test() { -#if !defined(NDEBUG) - /* vc6 preprocessor is broken, so assert with these strings gets - * confused. Use a table instead. +#if !defined( NDEBUG ) + /* vc6 preprocessor is broken, so assert with these strings gets confused. + * Use a table instead. */ - typedef struct test { char* command; int result; } test; + typedef struct test { char * command; int result; } test; test tests[] = { { "x", 0 }, { "x\n ", 0 }, @@ -157,20 +166,17 @@ void execnt_unit_test() { "echo x \">\" foo.bar", 0 }, { "echo x \"<\" foo.bar", 0 }, { "echo x \\\">\\\" foo.bar", 1 }, - { "echo x \\\"<\\\" foo.bar", 1 } - }; + { "echo x \\\"<\\\" foo.bar", 1 } }; int i; - for ( i = 0; i < sizeof(tests)/sizeof(*tests); ++i) - { - assert( !can_spawn( tests[i].command ) == tests[i].result ); - } + for ( i = 0; i < sizeof( tests ) / sizeof( *tests ); ++i ) + assert( !can_spawn( tests[ i ].command ) == tests[ i ].result ); { - char* long_command = BJAM_MALLOC_ATOMIC(MAXLINE + 10); + char * long_command = BJAM_MALLOC_ATOMIC( MAXLINE + 10 ); assert( long_command != 0 ); memset( long_command, 'x', MAXLINE + 9 ); - long_command[MAXLINE + 9] = 0; - assert( can_spawn( long_command ) == MAXLINE + 9); + long_command[ MAXLINE + 9 ] = 0; + assert( can_spawn( long_command ) == MAXLINE + 9 ); BJAM_FREE( long_command ); } @@ -178,94 +184,101 @@ void execnt_unit_test() /* Work around vc6 bug; it doesn't like escaped string * literals inside assert */ - char** argv = string_to_args("\"g++\" -c -I\"Foobar\""); - char const expected[] = "-c -I\"Foobar\""; - - assert(!strcmp(argv[0], "g++")); - assert(!strcmp(argv[1], expected)); - free_argv(argv); + char * * argv = string_to_args(" \"g++\" -c -I\"Foobar\"" ); + char const expected[] = "-c -I\"Foobar\""; + + assert( !strcmp( argv[ 0 ], "g++" ) ); + assert( !strcmp( argv[ 1 ], expected ) ); + free_argv( argv ); } -#endif +#endif } -/* execcmd() - launch an async command execution */ -void execcmd( - char *command, - void (*func)( void *closure, int status, timing_info*, char *invoked_command, char *command_output), - void *closure, - LIST *shell, - char *action, - char *target ) + +/* + * exec_cmd() - launch an async command execution. + */ + +void exec_cmd +( + char * command, + void (* func)( void * closure, int status, timing_info *, char * invoked_command, char * command_output ), + void * closure, + LIST * shell, + char * action, + char * target +) { - int slot; - int raw_cmd = 0 ; - char *argv_static[ MAXARGC + 1 ]; /* +1 for NULL */ - char **argv = argv_static; - char *p; - char* command_orig = command; - - /* Check to see if we need to hack around the line-length limitation. */ - /* Look for a JAMSHELL setting of "%", indicating that the command - * should be invoked directly */ - if ( shell && !strcmp(shell->string,"%") && !list_next(shell) ) + int slot; + int raw_cmd = 0 ; + char * argv_static[ MAXARGC + 1 ]; /* +1 for NULL */ + char * * argv = argv_static; + char * p; + char * command_orig = command; + + /* Check to see if we need to hack around the line-length limitation. Look + * for a JAMSHELL setting of "%", indicating that the command should be + * invoked directly. + */ + if ( shell && !strcmp( shell->string, "%" ) && !list_next( shell ) ) { raw_cmd = 1; shell = 0; } /* Find a slot in the running commands table for this one. */ - for( slot = 0; slot < MAXJOBS; slot++ ) - if( !cmdtab[ slot ].pi.hProcess ) + for ( slot = 0; slot < MAXJOBS; ++slot ) + if ( !cmdtab[ slot ].pi.hProcess ) break; - if( slot == MAXJOBS ) + if ( slot == MAXJOBS ) { printf( "no slots for child!\n" ); exit( EXITBAD ); } - /* compute the name of a temp batch file, for possible use */ - if( !cmdtab[ slot ].tempfile_bat ) + /* Compute the name of a temp batch file, for possible use. */ + if ( !cmdtab[ slot ].tempfile_bat ) { - const char *tempdir = path_tmpdir(); + char const * tempdir = path_tmpdir(); DWORD procID = GetCurrentProcessId(); - - /* SVA - allocate 64 other just to be safe */ + + /* SVA - allocate 64 bytes extra just to be safe. */ cmdtab[ slot ].tempfile_bat = BJAM_MALLOC_ATOMIC( strlen( tempdir ) + 64 ); - - sprintf( - cmdtab[ slot ].tempfile_bat, "%s\\jam%d-%02d.bat", + + sprintf( cmdtab[ slot ].tempfile_bat, "%s\\jam%d-%02d.bat", tempdir, procID, slot ); } /* Trim leading, -ending- white space */ - while( *(command+1) && isspace( *command ) ) + while ( *( command + 1 ) && isspace( *command ) ) ++command; - /* Write to .BAT file unless the line would be too long and it - * meets the other spawnability criteria. + /* Write to .BAT file unless the line would be too long and it meets the + * other spawnability criteria. */ - if( raw_cmd && can_spawn( command ) >= MAXLINE ) + if ( raw_cmd && ( can_spawn( command ) >= MAXLINE ) ) { - if( DEBUG_EXECCMD ) - printf("Executing raw command directly\n"); + if ( DEBUG_EXECCMD ) + printf("Executing raw command directly\n"); } else { - FILE *f = 0; + FILE * f = 0; int tries = 0; raw_cmd = 0; - - /* Write command to bat file. For some reason this open can - fails intermitently. But doing some retries works. Most likely - this is due to a previously existing file of the same name that - happens to be opened by an active virus scanner. Pointed out, - and fix by Bronek Kozicki. */ - for (; !f && tries < 4; ++tries) + + /* Write command to bat file. For some reason this open can fail + * intermitently. But doing some retries works. Most likely this is due + * to a previously existing file of the same name that happens to be + * opened by an active virus scanner. Pointed out and fixed by Bronek + * Kozicki. + */ + for ( ; !f && ( tries < 4 ); ++tries ) { f = fopen( cmdtab[ slot ].tempfile_bat, "w" ); - if ( !f && tries < 4 ) Sleep( 250 ); + if ( !f && ( tries < 4 ) ) Sleep( 250 ); } - if (!f) + if ( !f ) { printf( "failed to write command file!\n" ); exit( EXITBAD ); @@ -274,126 +287,129 @@ void execcmd( fclose( f ); command = cmdtab[ slot ].tempfile_bat; - - if( DEBUG_EXECCMD ) + + if ( DEBUG_EXECCMD ) { - if (shell) - printf("using user-specified shell: %s", shell->string); + if ( shell ) + printf( "using user-specified shell: %s", shell->string ); else - printf("Executing through .bat file\n"); + printf( "Executing through .bat file\n" ); } } - /* Formulate argv; If shell was defined, be prepared for % and ! subs. */ - /* Otherwise, use stock cmd.exe. */ - if( shell ) + /* Formulate argv; If shell was defined, be prepared for % and ! subs. + * Otherwise, use stock cmd.exe. + */ + if ( shell ) { int i; - char jobno[4]; + char jobno[ 4 ]; int gotpercent = 0; sprintf( jobno, "%d", slot + 1 ); - for( i = 0; shell && i < MAXARGC; i++, shell = list_next( shell ) ) + for ( i = 0; shell && ( i < MAXARGC ); ++i, shell = list_next( shell ) ) { - switch( shell->string[0] ) + switch ( shell->string[ 0 ] ) { - case '%': argv[i] = command; gotpercent++; break; - case '!': argv[i] = jobno; break; - default: argv[i] = shell->string; + case '%': argv[ i ] = command; ++gotpercent; break; + case '!': argv[ i ] = jobno; break; + default : argv[ i ] = shell->string; } - if( DEBUG_EXECCMD ) - printf( "argv[%d] = '%s'\n", i, argv[i] ); + if ( DEBUG_EXECCMD ) + printf( "argv[%d] = '%s'\n", i, argv[ i ] ); } - if( !gotpercent ) - argv[i++] = command; + if ( !gotpercent ) + argv[ i++ ] = command; - argv[i] = 0; + argv[ i ] = 0; } - else if (raw_cmd) + else if ( raw_cmd ) { - argv = string_to_args(command); + argv = string_to_args( command ); } else { - argv[0] = "cmd.exe"; - argv[1] = "/Q/C"; /* anything more is non-portable */ - argv[2] = command; - argv[3] = 0; + argv[ 0 ] = "cmd.exe"; + argv[ 1 ] = "/Q/C"; /* anything more is non-portable */ + argv[ 2 ] = command; + argv[ 3 ] = 0; } /* Catch interrupts whenever commands are running. */ - - if( !cmdsrunning++ ) + if ( !cmdsrunning++ ) istat = signal( SIGINT, onintr ); - - /* Start the command */ + + /* Start the command. */ { SECURITY_ATTRIBUTES sa - = { sizeof(SECURITY_ATTRIBUTES), 0, 0 }; + = { sizeof( SECURITY_ATTRIBUTES ), 0, 0 }; SECURITY_DESCRIPTOR sd; STARTUPINFO si - = { sizeof(STARTUPINFO), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + = { sizeof( STARTUPINFO ), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; string cmd; - /* init the security data */ + /* Init the security data. */ InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION ); SetSecurityDescriptorDacl( &sd, TRUE, NULL, FALSE ); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = TRUE; - /* create the stdout, which is also the merged out+err, pipe */ - if ( ! CreatePipe( &cmdtab[ slot ].pipe_out[0], &cmdtab[ slot ].pipe_out[1], &sa, 0 ) ) + /* Create the stdout, which is also the merged out + err, pipe. */ + if ( !CreatePipe( &cmdtab[ slot ].pipe_out[ 0 ], + &cmdtab[ slot ].pipe_out[ 1 ], &sa, 0 ) ) { perror( "CreatePipe" ); exit( EXITBAD ); } - /* create the stdout, which is also the merged out+err, pipe */ + /* Create the stdout, which is also the merged out+err, pipe. */ if ( globs.pipe_action == 2 ) { - if ( ! CreatePipe( &cmdtab[ slot ].pipe_err[0], &cmdtab[ slot ].pipe_err[1], &sa, 0 ) ) + if ( !CreatePipe( &cmdtab[ slot ].pipe_err[ 0 ], + &cmdtab[ slot ].pipe_err[ 1 ], &sa, 0 ) ) { perror( "CreatePipe" ); exit( EXITBAD ); } } - /* set handle inheritance off for the pipe ends the parent reads from */ - SetHandleInformation( cmdtab[ slot ].pipe_out[0], HANDLE_FLAG_INHERIT, 0 ); + /* Set handle inheritance off for the pipe ends the parent reads from. */ + SetHandleInformation( cmdtab[ slot ].pipe_out[ 0 ], HANDLE_FLAG_INHERIT, 0 ); if ( globs.pipe_action == 2 ) - { - SetHandleInformation( cmdtab[ slot ].pipe_err[0], HANDLE_FLAG_INHERIT, 0 ); - } + SetHandleInformation( cmdtab[ slot ].pipe_err[ 0 ], HANDLE_FLAG_INHERIT, 0 ); - /* hide the child window, if any */ + /* Hide the child window, if any. */ si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; - /* set the child outputs to the pipes */ + /* Set the child outputs to the pipes. */ si.dwFlags |= STARTF_USESTDHANDLES; - si.hStdOutput = cmdtab[ slot ].pipe_out[1]; + si.hStdOutput = cmdtab[ slot ].pipe_out[ 1 ]; if ( globs.pipe_action == 2 ) { - /* pipe stderr to the action error output */ - si.hStdError = cmdtab[ slot ].pipe_err[1]; + /* Pipe stderr to the action error output. */ + si.hStdError = cmdtab[ slot ].pipe_err[ 1 ]; } else if ( globs.pipe_action == 1 ) { - /* pipe stderr to the console error output */ - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + /* Pipe stderr to the console error output. */ + si.hStdError = GetStdHandle( STD_ERROR_HANDLE ); } else { - /* pipe stderr to the action merged output */ - si.hStdError = cmdtab[ slot ].pipe_out[1]; + /* Pipe stderr to the action merged output. */ + si.hStdError = cmdtab[ slot ].pipe_out[ 1 ]; } - /* Save the operation for execwait() to find. */ + /* Let the child inherit stdin, as some commands assume it's available. */ + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + + /* Save the operation for exec_wait() to find. */ cmdtab[ slot ].func = func; cmdtab[ slot ].closure = closure; - if (action && target) + if ( action && target ) { string_copy( &cmdtab[ slot ].action, action ); string_copy( &cmdtab[ slot ].target, target ); @@ -401,380 +417,408 @@ void execcmd( else { string_free( &cmdtab[ slot ].action ); - string_new( &cmdtab[ slot ].action ); + string_new ( &cmdtab[ slot ].action ); string_free( &cmdtab[ slot ].target ); - string_new( &cmdtab[ slot ].target ); + string_new ( &cmdtab[ slot ].target ); } string_copy( &cmdtab[ slot ].command, command_orig ); - - /* put together the comman we run */ + + /* Put together the command we run. */ { - char ** argp = argv; - string_new(&cmd); - string_copy(&cmd,*(argp++)); - while( *argp != 0 ) + char * * argp = argv; + string_new( &cmd ); + string_copy( &cmd, *(argp++) ); + while ( *argp ) { - string_push_back(&cmd,' '); - string_append(&cmd,*(argp++)); + string_push_back( &cmd, ' ' ); + string_append( &cmd, *(argp++) ); } } - - /* create the output buffers */ + + /* Create output buffers. */ string_new( &cmdtab[ slot ].buffer_out ); string_new( &cmdtab[ slot ].buffer_err ); - /* run the command, by creating a sub-process for it */ + /* Run the command by creating a sub-process for it. */ if ( ! CreateProcess( - NULL, /* application name */ - cmd.value, /* command line */ - NULL, /* process attributes */ - NULL, /* thread attributes */ - TRUE, /* inherit handles */ - CREATE_NEW_PROCESS_GROUP, /* create flags */ - NULL, /* env vars, null inherits env */ - NULL, /* current dir, null is our current dir */ - &si, /* startup info */ - &cmdtab[ slot ].pi /* the child process info, if created */ + NULL , /* application name */ + cmd.value , /* command line */ + NULL , /* process attributes */ + NULL , /* thread attributes */ + TRUE , /* inherit handles */ + CREATE_NEW_PROCESS_GROUP, /* create flags */ + NULL , /* env vars, null inherits env */ + NULL , /* current dir, null is our */ + /* current dir */ + &si , /* startup info */ + &cmdtab[ slot ].pi /* child process info, if created */ ) ) { perror( "CreateProcess" ); exit( EXITBAD ); } - - /* clean up temporary stuff */ - string_free(&cmd); + + /* Clean up temporary stuff. */ + string_free( &cmd ); } - /* Wait until we're under the limit of concurrent commands. */ - /* Don't trust globs.jobs alone. */ - - while( cmdsrunning >= MAXJOBS || cmdsrunning >= globs.jobs ) - if( !execwait() ) + /* 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; - - if (argv != argv_static) - { - free_argv(argv); - } + + if ( argv != argv_static ) + free_argv( argv ); } +/* + * exec_wait() + * * wait and drive at most one execution completion. + * * waits for one command to complete, while processing the i/o for all + * ongoing commands. + * + * Returns 0 if called when there were no more commands being executed or 1 + * otherwise. + */ -/* execwait() - - wait and drive at most one execution completion - * waits for one command to complete, while processing the io - for all ongoing commands. -*/ -int execwait() +int exec_wait() { int i = -1; - /* Handle naive make1() which doesn't know if cmds are running. */ - - if( !cmdsrunning ) + /* Handle naive make1() which does not know if cmds are running. */ + if ( !cmdsrunning ) return 0; - - /* wait for a command to complete, while snarfing up any output */ + + /* Wait for a command to complete, while snarfing up any output. */ do { - /* read in the output of all running commands */ + /* Check for a complete command, briefly. */ + i = try_wait(500); + /* Read in the output of all running commands. */ read_output(); - /* close out pending debug style dialogs */ + /* Close out pending debug style dialogs. */ close_alerts(); - /* check for a complete command, briefly */ - if ( i < 0 ) i = try_wait(500); - /* check if a command ran out of time */ + /* Check if a command ran out of time. */ if ( i < 0 ) i = try_kill_one(); } while ( i < 0 ); - - /* we have a command... process it */ + + /* We have a command... process it. */ --cmdsrunning; { timing_info time; int rstat; - - /* the time data for the command */ - record_times(cmdtab[i].pi.hProcess, &time); - /* Clear the temp file */ - if ( cmdtab[i].tempfile_bat ) + /* The time data for the command. */ + record_times( cmdtab[ i ].pi.hProcess, &time ); + + /* Clear the temp file. */ + if ( cmdtab[ i ].tempfile_bat ) { unlink( cmdtab[ i ].tempfile_bat ); - BJAM_FREE(cmdtab[i].tempfile_bat); - cmdtab[i].tempfile_bat = NULL; + BJAM_FREE( cmdtab[ i ].tempfile_bat ); + cmdtab[ i ].tempfile_bat = NULL; } - /* the dispossition of the command */ - if( intr ) + /* Find out the process exit code. */ + GetExitCodeProcess( cmdtab[ i ].pi.hProcess, &cmdtab[ i ].exit_code ); + + /* The dispossition of the command. */ + if ( intr ) rstat = EXEC_CMD_INTR; - else if( cmdtab[i].exitcode != 0 ) + else if ( cmdtab[ i ].exit_code != 0 ) rstat = EXEC_CMD_FAIL; else rstat = EXEC_CMD_OK; - - /* output the action block */ - out_action( - cmdtab[i].action.size > 0 ? cmdtab[i].action.value : 0, - cmdtab[i].target.size > 0 ? cmdtab[i].target.value : 0, - cmdtab[i].command.size > 0 ? cmdtab[i].command.value : 0, - cmdtab[i].buffer_out.size > 0 ? cmdtab[i].buffer_out.value : 0, - cmdtab[i].buffer_err.size > 0 ? cmdtab[i].buffer_err.value : 0, - cmdtab[i].exit_reason); - /* call the callback, may call back to jam rule land. - assume -p0 in effect so only pass buffer containing - merged output */ + /* Output the action block. */ + out_action( + cmdtab[ i ].action.size > 0 ? cmdtab[ i ].action.value : 0, + cmdtab[ i ].target.size > 0 ? cmdtab[ i ].target.value : 0, + cmdtab[ i ].command.size > 0 ? cmdtab[ i ].command.value : 0, + cmdtab[ i ].buffer_out.size > 0 ? cmdtab[ i ].buffer_out.value : 0, + cmdtab[ i ].buffer_err.size > 0 ? cmdtab[ i ].buffer_err.value : 0, + cmdtab[ i ].exit_reason ); + + /* Call the callback, may call back to jam rule land. Assume -p0 in + * effect so only pass buffer containing merged output. + */ (*cmdtab[ i ].func)( cmdtab[ i ].closure, rstat, &time, - cmdtab[i].command.value, - cmdtab[i].buffer_out.value ); - - /* clean up the command data, process, etc. */ - string_free(&cmdtab[i].action); string_new(&cmdtab[i].action); - string_free(&cmdtab[i].target); string_new(&cmdtab[i].target); - string_free(&cmdtab[i].command); string_new(&cmdtab[i].command); - if (cmdtab[i].pi.hProcess) { CloseHandle(cmdtab[i].pi.hProcess); cmdtab[i].pi.hProcess = 0; } - if (cmdtab[i].pi.hThread) { CloseHandle(cmdtab[i].pi.hThread); cmdtab[i].pi.hThread = 0; } - if (cmdtab[i].pipe_out[0]) { CloseHandle(cmdtab[i].pipe_out[0]); cmdtab[i].pipe_out[0] = 0; } - if (cmdtab[i].pipe_out[1]) { CloseHandle(cmdtab[i].pipe_out[1]); cmdtab[i].pipe_out[1] = 0; } - if (cmdtab[i].pipe_err[0]) { CloseHandle(cmdtab[i].pipe_err[0]); cmdtab[i].pipe_err[0] = 0; } - if (cmdtab[i].pipe_err[1]) { CloseHandle(cmdtab[i].pipe_err[1]); cmdtab[i].pipe_err[1] = 0; } - string_free(&cmdtab[i].buffer_out); string_new(&cmdtab[i].buffer_out); - string_free(&cmdtab[i].buffer_err); string_new(&cmdtab[i].buffer_err); - cmdtab[i].exitcode = 0; - cmdtab[i].exit_reason = EXIT_OK; + cmdtab[ i ].command.value, + cmdtab[ i ].buffer_out.value ); + + /* Clean up the command data, process, etc. */ + string_free( &cmdtab[ i ].action ); string_new( &cmdtab[ i ].action ); + string_free( &cmdtab[ i ].target ); string_new( &cmdtab[ i ].target ); + string_free( &cmdtab[ i ].command ); string_new( &cmdtab[ i ].command ); + if ( cmdtab[ i ].pi.hProcess ) { CloseHandle( cmdtab[ i ].pi.hProcess ); cmdtab[ i ].pi.hProcess = 0; } + if ( cmdtab[ i ].pi.hThread ) { CloseHandle( cmdtab[ i ].pi.hThread ); cmdtab[ i ].pi.hThread = 0; } + if ( cmdtab[ i ].pipe_out[ 0 ] ) { CloseHandle( cmdtab[ i ].pipe_out[ 0 ] ); cmdtab[ i ].pipe_out[ 0 ] = 0; } + if ( cmdtab[ i ].pipe_out[ 1 ] ) { CloseHandle( cmdtab[ i ].pipe_out[ 1 ] ); cmdtab[ i ].pipe_out[ 1 ] = 0; } + if ( cmdtab[ i ].pipe_err[ 0 ] ) { CloseHandle( cmdtab[ i ].pipe_err[ 0 ] ); cmdtab[ i ].pipe_err[ 0 ] = 0; } + if ( cmdtab[ i ].pipe_err[ 1 ] ) { CloseHandle( cmdtab[ i ].pipe_err[ 1 ] ); cmdtab[ i ].pipe_err[ 1 ] = 0; } + string_free( &cmdtab[ i ].buffer_out ); string_new( &cmdtab[ i ].buffer_out ); + string_free( &cmdtab[ i ].buffer_err ); string_new( &cmdtab[ i ].buffer_err ); + cmdtab[ i ].exit_code = 0; + cmdtab[ i ].exit_reason = EXIT_OK; } return 1; } + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -static void free_argv( char** args ) +static void free_argv( char * * args ) { - BJAM_FREE( args[0] ); + BJAM_FREE( args[ 0 ] ); BJAM_FREE( args ); } + +/* + * For more details on Windows cmd.exe shell command-line length limitations see + * the following MSDN article: + * http://support.microsoft.com/default.aspx?scid=kb;en-us;830473 + */ + int maxline() { OSVERSIONINFO os_info; - os_info.dwOSVersionInfoSize = sizeof(os_info); - GetVersionEx(&os_info); - - return (os_info.dwMajorVersion == 3) - ? 996 /* NT 3.5.1 */ - : 2047 /* NT >= 4.x */ - ; + os_info.dwOSVersionInfoSize = sizeof( os_info ); + GetVersionEx( &os_info ); + + if ( os_info.dwMajorVersion >= 5 ) return 8191; /* XP > */ + if ( os_info.dwMajorVersion == 4 ) return 2047; /* NT 4.x */ + return 996; /* NT 3.5.1 */ } -/* Convert a command string into arguments for spawnvp. The original - * code, inherited from ftjam, tried to break up every argument on the - * command-line, dealing with quotes, but that's really a waste of - * time on Win32, at least. It turns out that all you need to do is - * get the raw path to the executable in the first argument to - * spawnvp, and you can pass all the rest of the command-line - * arguments to spawnvp in one, un-processed string. + +/* + * Convert a command string into arguments for spawnvp(). The original code, + * inherited from ftjam, tried to break up every argument on the command-line, + * dealing with quotes, but that is really a waste of time on Win32, at least. + * It turns out that all you need to do is get the raw path to the executable in + * the first argument to spawnvp(), and you can pass all the rest of the + * command-line arguments to spawnvp() in one, un-processed string. * * New strategy: break the string in at most one place. */ -static char** string_to_args( const char* string ) -{ - int src_len; - int in_quote; - char* line; - char const* src; - char* dst; - char** argv; - /* drop leading and trailing whitespace if any */ - while (isspace(*string)) +static char * * string_to_args( char const * string ) +{ + int src_len; + int in_quote; + char * line; + char const * src; + char * dst; + char * * argv; + + /* Drop leading and trailing whitespace if any. */ + while ( isspace( *string ) ) ++string; - + src_len = strlen( string ); - while ( src_len > 0 && isspace( string[src_len - 1] ) ) + while ( ( src_len > 0 ) && isspace( string[ src_len - 1 ] ) ) --src_len; - /* Copy the input string into a buffer we can modify - */ - line = (char*)BJAM_MALLOC_ATOMIC( src_len+1 ); - if (!line) + /* Copy the input string into a buffer we can modify. */ + line = (char *)BJAM_MALLOC_ATOMIC( src_len + 1 ); + if ( !line ) return 0; - /* allocate the argv array. + /* Allocate the argv array. * element 0: stores the path to the executable * element 1: stores the command-line arguments to the executable * element 2: NULL terminator */ - argv = (char**)BJAM_MALLOC( 3 * sizeof(char*) ); - if (!argv) + argv = (char * *)BJAM_MALLOC( 3 * sizeof( char * ) ); + if ( !argv ) { BJAM_FREE( line ); return 0; } - - /* Strip quotes from the first command-line argument and find - * where it ends. Quotes are illegal in Win32 pathnames, so we - * don't need to worry about preserving escaped quotes here. - * Spaces can't be escaped in Win32, only enclosed in quotes, so - * removing backslash escapes is also a non-issue. + + /* Strip quotes from the first command-line argument and find where it ends. + * Quotes are illegal in Win32 pathnames, so we do not need to worry about + * preserving escaped quotes here. Spaces can not be escaped in Win32, only + * enclosed in quotes, so removing backslash escapes is also a non-issue. */ in_quote = 0; - for ( src = string, dst = line ; *src; src++ ) + for ( src = string, dst = line ; *src; ++src ) { - if (*src == '"') + if ( *src == '"' ) in_quote = !in_quote; - else if (!in_quote && isspace(*src)) + else if ( !in_quote && isspace( *src ) ) break; else *dst++ = *src; } *dst++ = 0; - argv[0] = line; + argv[ 0 ] = line; - /* skip whitespace in src */ - while (isspace(*src)) + /* Skip whitespace in src. */ + while ( isspace( *src ) ) ++src; - argv[1] = dst; + argv[ 1 ] = dst; - /* Copy the rest of the arguments verbatim */ - + /* Copy the rest of the arguments verbatim. */ src_len -= src - string; - /* Use strncat because it appends a trailing nul */ + /* Use strncat() because it appends a trailing nul. */ *dst = 0; - strncat(dst, src, src_len); + strncat( dst, src, src_len ); + + argv[ 2 ] = 0; - argv[2] = 0; - return argv; } + static void onintr( int disp ) { - intr++; + ++intr; printf( "...interrupted\n" ); } + /* - * can_spawn() - If the command is suitable for execution via spawnvp, - * return a number >= the number of characters it would occupy on the - * command-line. Otherwise, return zero. + * can_spawn() - If the command is suitable for execution via spawnvp(), return + * a number >= the number of characters it would occupy on the command-line. + * Otherwise, return zero. */ -long can_spawn(char* command) + +long can_spawn( char * command ) { - char *p; - + char * p; char inquote = 0; - /* Move to the first non-whitespace */ + /* Move to the first non-whitespace. */ command += strspn( command, " \t" ); p = command; - - /* Look for newlines and unquoted i/o redirection */ + + /* Look for newlines and unquoted i/o redirection. */ do { p += strcspn( p, "'\n\"<>|" ); - switch (*p) + switch ( *p ) { case '\n': - /* skip over any following spaces */ - while( isspace( *p ) ) + /* Skip over any following spaces. */ + while ( isspace( *p ) ) ++p; - /* Must use a .bat file if there is anything significant - * following the newline + /* Must use a .bat file if there is anything significant following + * the newline. */ - if (*p) + if ( *p ) return 0; break; - + case '"': case '\'': - if (p > command && p[-1] != '\\') + if ( ( p > command ) && ( p[ -1 ] != '\\' ) ) { - if (inquote == *p) + if ( inquote == *p ) inquote = 0; - else if (inquote == 0) + else if ( inquote == 0 ) inquote = *p; } - ++p; break; - + case '<': case '>': case '|': - if (!inquote) + if ( !inquote ) return 0; ++p; break; } } - while (*p); + while ( *p ); - /* Return the number of characters the command will occupy - */ + /* Return the number of characters the command will occupy. */ return p - command; } -/* 64-bit arithmetic helpers */ -/* Compute the carry bit from the addition of two 32-bit unsigned numbers */ -#define add_carry_bit(a, b) ( (((a) | (b)) >> 31) & (~((a) + (b)) >> 31) & 0x1 ) +/* 64-bit arithmetic helpers. */ -/* Compute the high 32 bits of the addition of two 64-bit unsigned numbers, h1l1 and h2l2 */ -#define add_64_hi(h1, l1, h2, l2) ((h1) + (h2) + add_carry_bit(l1, l2)) +/* Compute the carry bit from the addition of two 32-bit unsigned numbers. */ +#define add_carry_bit( a, b ) ( (((a) | (b)) >> 31) & (~((a) + (b)) >> 31) & 0x1 ) -/* Add two 64-bit unsigned numbers, h1l1 and h2l2 */ -static FILETIME add_64( +/* Compute the high 32 bits of the addition of two 64-bit unsigned numbers, h1l1 and h2l2. */ +#define add_64_hi( h1, l1, h2, l2 ) ((h1) + (h2) + add_carry_bit(l1, l2)) + + +/* + * Add two 64-bit unsigned numbers, h1l1 and h2l2. + */ + +static FILETIME add_64 +( unsigned long h1, unsigned long l1, - unsigned long h2, unsigned long l2) + unsigned long h2, unsigned long l2 +) { FILETIME result; result.dwLowDateTime = l1 + l2; - result.dwHighDateTime = add_64_hi(h1, l1, h2, l2); - + result.dwHighDateTime = add_64_hi( h1, l1, h2, l2 ); return result; } -static FILETIME add_FILETIME(FILETIME t1, FILETIME t2) + +static FILETIME add_FILETIME( FILETIME t1, FILETIME t2 ) { - return add_64( - t1.dwHighDateTime, t1.dwLowDateTime - , t2.dwHighDateTime, t2.dwLowDateTime); + return add_64( t1.dwHighDateTime, t1.dwLowDateTime, t2.dwHighDateTime, + t2.dwLowDateTime ); } -static FILETIME negate_FILETIME(FILETIME t) + + +static FILETIME negate_FILETIME( FILETIME t ) { /* 2s complement negation */ - return add_64(~t.dwHighDateTime, ~t.dwLowDateTime, 0, 1); + return add_64( ~t.dwHighDateTime, ~t.dwLowDateTime, 0, 1 ); } -/* Convert a FILETIME to a number of seconds */ -static double filetime_seconds(FILETIME t) + +/* + * Convert a FILETIME to a number of seconds. + */ + +static double filetime_seconds( FILETIME t ) { - return t.dwHighDateTime * ((double)(1UL << 31) * 2.0 * 1.0e-7) + t.dwLowDateTime * 1.0e-7; + return t.dwHighDateTime * ( (double)( 1UL << 31 ) * 2.0 * 1.0e-7 ) + t.dwLowDateTime * 1.0e-7; } -/* What should be a simple conversion, turns out to be horribly - complicated by the defficiencies of MSVC and the Win32 API. */ -static time_t filetime_dt(FILETIME t_utc) + +/* + * What should be a simple conversion, turns out to be horribly complicated by + * the defficiencies of MSVC and the Win32 API. + */ + +static time_t filetime_dt( FILETIME t_utc ) { static int calc_time_diff = 1; static double time_diff; if ( calc_time_diff ) { struct tm t0_; - FILETIME f0_local,f0_; + FILETIME f0_local; + FILETIME f0_; SYSTEMTIME s0_; - GetSystemTime(&s0_); + GetSystemTime( &s0_ ); t0_.tm_year = s0_.wYear-1900; t0_.tm_mon = s0_.wMonth-1; t0_.tm_wday = s0_.wDayOfWeek; @@ -783,85 +827,84 @@ static time_t filetime_dt(FILETIME t_utc) t0_.tm_min = s0_.wMinute; t0_.tm_sec = s0_.wSecond; t0_.tm_isdst = 0; - SystemTimeToFileTime(&s0_,&f0_local); - LocalFileTimeToFileTime(&f0_local,&f0_); - time_diff = filetime_seconds(f0_)-((double)mktime(&t0_)); + SystemTimeToFileTime( &s0_, &f0_local ); + LocalFileTimeToFileTime( &f0_local, &f0_ ); + time_diff = filetime_seconds( f0_ ) - (double)mktime( &t0_ ); calc_time_diff = 0; } - return ceil(filetime_seconds(t_utc)-time_diff); + return ceil( filetime_seconds( t_utc ) - time_diff ); } -static void record_times(HANDLE process, timing_info* time) + +static void record_times( HANDLE process, timing_info * time ) { - FILETIME creation, exit, kernel, user; - - if (GetProcessTimes(process, &creation, &exit, &kernel, &user)) + FILETIME creation; + FILETIME exit; + FILETIME kernel; + FILETIME user; + if ( GetProcessTimes( process, &creation, &exit, &kernel, &user ) ) { - time->system = filetime_seconds(kernel); - time->user = filetime_seconds(user); - time->start = filetime_dt(creation); - time->end = filetime_dt(exit); + time->system = filetime_seconds( kernel ); + time->user = filetime_seconds( user ); + time->start = filetime_dt ( creation ); + time->end = filetime_dt ( exit ); } } -#define IO_BUFFER_SIZE (16*1024) -static char ioBuffer[IO_BUFFER_SIZE+1]; +#define IO_BUFFER_SIZE ( 16 * 1024 ) -static void read_pipe( - HANDLE in, /* the pipe to read from */ +static char ioBuffer[ IO_BUFFER_SIZE + 1 ]; + + +static void read_pipe +( + HANDLE in, /* the pipe to read from */ string * out - ) +) { DWORD bytesInBuffer = 0; DWORD bytesAvailable = 0; - + do { /* check if we have any data to read */ - if ( ! PeekNamedPipe( in, ioBuffer, IO_BUFFER_SIZE, &bytesInBuffer, &bytesAvailable, NULL ) ) - { + if ( !PeekNamedPipe( in, ioBuffer, IO_BUFFER_SIZE, &bytesInBuffer, &bytesAvailable, NULL ) ) bytesAvailable = 0; - } - + /* read in the available data */ if ( bytesAvailable > 0 ) { /* we only read in the available bytes, to avoid blocking */ - if ( - ReadFile( in, ioBuffer, - bytesAvailable <= IO_BUFFER_SIZE ? bytesAvailable : IO_BUFFER_SIZE, - &bytesInBuffer, NULL ) - ) + if ( ReadFile( in, ioBuffer, + bytesAvailable <= IO_BUFFER_SIZE ? bytesAvailable : IO_BUFFER_SIZE, + &bytesInBuffer, NULL ) ) { if ( bytesInBuffer > 0 ) { - /* clean up non-ascii chars */ + /* Clean up some illegal chars. */ int i; for ( i = 0; i < bytesInBuffer; ++i ) { - if ((unsigned char)ioBuffer[i] < 1 || - (unsigned char)ioBuffer[i] > 127 ) - { - ioBuffer[i] = '?'; - } + if ( ( (unsigned char)ioBuffer[ i ] < 1 ) ) + ioBuffer[ i ] = '?'; } - /* null, terminate */ - ioBuffer[bytesInBuffer] = '\0'; - /* append to the output */ - string_append(out,ioBuffer); - /* subtract what we read in */ + /* Null, terminate. */ + ioBuffer[ bytesInBuffer ] = '\0'; + /* Append to the output. */ + string_append( out, ioBuffer ); + /* Subtract what we read in. */ bytesAvailable -= bytesInBuffer; } else { - /* likely read a error, bail out. */ + /* Likely read a error, bail out. */ bytesAvailable = 0; } } else { - /* definitely read a error, bail out. */ + /* Definitely read a error, bail out. */ bytesAvailable = 0; } } @@ -869,82 +912,81 @@ static void read_pipe( while ( bytesAvailable > 0 ); } + static void read_output() { int i; - for ( i = 0; i < globs.jobs && i < MAXJOBS; ++i ) { - /* read stdout data */ - if (cmdtab[i].pipe_out[0]) - read_pipe( cmdtab[i].pipe_out[0], & cmdtab[i].buffer_out ); - /* read stderr data */ - if (cmdtab[i].pipe_err[0]) - read_pipe( cmdtab[i].pipe_err[0], & cmdtab[i].buffer_err ); + /* Read stdout data. */ + if ( cmdtab[ i ].pipe_out[ 0 ] ) + read_pipe( cmdtab[ i ].pipe_out[ 0 ], & cmdtab[ i ].buffer_out ); + /* Read stderr data. */ + if ( cmdtab[ i ].pipe_err[ 0 ] ) + read_pipe( cmdtab[ i ].pipe_err[ 0 ], & cmdtab[ i ].buffer_err ); } } -/* waits for a single child process command to complete, or the - timeout, whichever is first. returns the index of the completed - command, or -1. */ -static int try_wait(int timeoutMillis) -{ - int i, num_active, waiting; - HANDLE active_handles[MAXJOBS]; - int active_procs[MAXJOBS]; - for ( waiting = 1; waiting; ) +/* + * Waits for a single child process command to complete, or the timeout, + * whichever comes first. Returns the index of the completed command in the + * cmdtab array, or -1. + */ + +static int try_wait( int timeoutMillis ) +{ + int i; + int num_active; + int wait_api_result; + HANDLE active_handles[ MAXJOBS ]; + int active_procs[ MAXJOBS ]; + + /* Prepare a list of all active processes to wait for. */ + for ( num_active = 0, i = 0; i < globs.jobs; ++i ) { - /* find the first completed child process */ - for ( num_active = 0, i = 0; i < globs.jobs; ++i ) + if ( cmdtab[ i ].pi.hProcess ) { - /* if we have an already dead process, return it. */ - cmdtab[i].exitcode = 0; - if ( GetExitCodeProcess( cmdtab[i].pi.hProcess, &cmdtab[i].exitcode ) ) - { - if ( STILL_ACTIVE != cmdtab[i].exitcode ) - { - return i; - } - } - /* it's running, add it to the list to watch for */ - active_handles[num_active] = cmdtab[i].pi.hProcess; - active_procs[num_active] = i; - num_active += 1; - } - - /* wait for a child to complete, or for our timeout window to expire */ - if ( waiting ) - { - WaitForMultipleObjects( num_active, active_handles, FALSE, timeoutMillis ); - waiting = 0; + active_handles[ num_active ] = cmdtab[ i ].pi.hProcess; + active_procs[ num_active ] = i; + ++num_active; } } - + + /* Wait for a child to complete, or for our timeout window to expire. */ + wait_api_result = WaitForMultipleObjects( num_active, active_handles, + FALSE, timeoutMillis ); + if ( ( WAIT_OBJECT_0 <= wait_api_result ) && + ( wait_api_result < WAIT_OBJECT_0 + num_active ) ) + { + /* Rerminated process detected - return its index. */ + return active_procs[ wait_api_result - WAIT_OBJECT_0 ]; + } + + /* Timeout. */ return -1; } + static int try_kill_one() { - /* only need to check if a timeout was specified with the -l option. */ + /* Only need to check if a timeout was specified with the -l option. */ if ( globs.timeout > 0 ) { int i; - for ( i = 0; i < globs.jobs; ++i ) { - double t = running_time(cmdtab[i].pi.hProcess); + double t = running_time( cmdtab[ i ].pi.hProcess ); if ( t > (double)globs.timeout ) { - /* the job may have left an alert dialog around, - try and get rid of it before killing */ - close_alert(cmdtab[i].pi.hProcess); - /* we have a "runaway" job, kill it */ - kill_process_tree(0,cmdtab[i].pi.hProcess); - /* and return it as complete, with the failure code */ - GetExitCodeProcess( cmdtab[i].pi.hProcess, &cmdtab[i].exitcode ); - /* mark it as a timeout */ - cmdtab[i].exit_reason = EXIT_TIMEOUT; + /* The job may have left an alert dialog around, try and get rid + * of it before killing + */ + close_alert( cmdtab[ i ].pi.hProcess ); + /* We have a "runaway" job, kill it. */ + kill_process_tree( 0, cmdtab[ i ].pi.hProcess ); + /* And return it marked as a timeout. */ + cmdtab[ i ].exit_reason = EXIT_TIMEOUT; return i; } } @@ -952,49 +994,54 @@ static int try_kill_one() return -1; } + static void close_alerts() { - /* we only attempt this every 5 seconds, or so, because it's - not a cheap operation, and we'll catch the alerts eventually. - this check uses floats as some compilers define CLOCKS_PER_SEC - as a float or double. */ - if ( ((float)clock() / (float)(CLOCKS_PER_SEC*5)) < (1.0/5.0) ) + /* We only attempt this every 5 seconds, or so, because it is not a cheap + * operation, and we will catch the alerts eventually. This check uses + * floats as some compilers define CLOCKS_PER_SEC as a float or double. + */ + if ( ( (float)clock() / (float)( CLOCKS_PER_SEC * 5 ) ) < ( 1.0 / 5.0 ) ) { int i; for ( i = 0; i < globs.jobs; ++i ) - { - close_alert(cmdtab[i].pi.hProcess); - } + close_alert( cmdtab[ i ].pi.hProcess ); } } -/* calc the current running time of an *active* process */ -static double running_time(HANDLE process) + +/* + * Calc the current running time of an *active* process. + */ + +static double running_time( HANDLE process ) { - FILETIME creation, exit, kernel, user, current; - if (GetProcessTimes(process, &creation, &exit, &kernel, &user)) + FILETIME creation; + FILETIME exit; + FILETIME kernel; + FILETIME user; + FILETIME current; + if ( GetProcessTimes( process, &creation, &exit, &kernel, &user ) ) { - /* Compute the elapsed time */ - GetSystemTimeAsFileTime(¤t); - { - double delta = filetime_seconds( - add_FILETIME( current, negate_FILETIME(creation) ) - ); - return delta; - } + /* Compute the elapsed time. */ + GetSystemTimeAsFileTime( ¤t ); + return filetime_seconds( add_FILETIME( current, + negate_FILETIME( creation ) ) ); } return 0.0; } -/* it's just stupidly silly that one has to do this! */ -typedef struct PROCESS_BASIC_INFORMATION__ { - LONG ExitStatus; + +/* It is just stupidly silly that one has to do this. */ +typedef struct PROCESS_BASIC_INFORMATION__ +{ + LONG ExitStatus; PVOID PebBaseAddress; ULONG AffinityMask; - LONG BasePriority; + LONG BasePriority; ULONG UniqueProcessId; ULONG InheritedFromUniqueProcessId; - } PROCESS_BASIC_INFORMATION_; +} PROCESS_BASIC_INFORMATION_; typedef LONG (__stdcall * NtQueryInformationProcess__)( HANDLE ProcessHandle, LONG ProcessInformationClass, @@ -1003,234 +1050,247 @@ typedef LONG (__stdcall * NtQueryInformationProcess__)( PULONG ReturnLength); static NtQueryInformationProcess__ NtQueryInformationProcess_ = NULL; static HMODULE NTDLL_ = NULL; -DWORD get_process_id(HANDLE process) +DWORD get_process_id( HANDLE process ) { PROCESS_BASIC_INFORMATION_ pinfo; - if ( ! NtQueryInformationProcess_ ) + if ( !NtQueryInformationProcess_ ) { if ( ! NTDLL_ ) - { - NTDLL_ = GetModuleHandleA("ntdll"); - } + NTDLL_ = GetModuleHandleA( "ntdll" ); if ( NTDLL_ ) - { NtQueryInformationProcess_ - = (NtQueryInformationProcess__)GetProcAddress( NTDLL_,"NtQueryInformationProcess" ); - } + = (NtQueryInformationProcess__)GetProcAddress( NTDLL_, "NtQueryInformationProcess" ); } if ( NtQueryInformationProcess_ ) { - LONG r = (*NtQueryInformationProcess_)( - process,/* ProcessBasicInformation == */ 0,&pinfo,sizeof(PROCESS_BASIC_INFORMATION_),NULL); + LONG r = (*NtQueryInformationProcess_)( process, + /* ProcessBasicInformation == */ 0, &pinfo, + sizeof( PROCESS_BASIC_INFORMATION_ ), NULL ); return pinfo.UniqueProcessId; } - else - { - return 0; - } + return 0; } -/* not really optimal, or efficient, but it's easier this way, and it's not -like we are going to be killing thousands, or even tens of processes. */ -static void kill_process_tree(DWORD pid, HANDLE process) + +/* + * Not really optimal, or efficient, but it is easier this way, and it is not + * like we are going to be killing thousands, or even tens of processes. + */ + +static void kill_process_tree( DWORD pid, HANDLE process ) { HANDLE process_snapshot_h = INVALID_HANDLE_VALUE; if ( !pid ) - { - pid = get_process_id(process); - } - process_snapshot_h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); - - if (INVALID_HANDLE_VALUE != process_snapshot_h) + pid = get_process_id( process ); + process_snapshot_h = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); + + if ( INVALID_HANDLE_VALUE != process_snapshot_h ) { BOOL ok = TRUE; PROCESSENTRY32 pinfo; - pinfo.dwSize = sizeof(PROCESSENTRY32); + pinfo.dwSize = sizeof( PROCESSENTRY32 ); for ( - ok = Process32First(process_snapshot_h,&pinfo); - TRUE == ok; - ok = Process32Next(process_snapshot_h,&pinfo) ) + ok = Process32First( process_snapshot_h, &pinfo ); + ok == TRUE; + ok = Process32Next( process_snapshot_h, &pinfo ) ) { - if (pinfo.th32ParentProcessID == pid) + if ( pinfo.th32ParentProcessID == pid ) { - /* found a child, recurse to kill it and anything else below it */ - HANDLE ph = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pinfo.th32ProcessID); - if (NULL != ph) + /* Found a child, recurse to kill it and anything else below it. + */ + HANDLE ph = OpenProcess( PROCESS_ALL_ACCESS, FALSE, + pinfo.th32ProcessID ); + if ( NULL != ph ) { - kill_process_tree(pinfo.th32ProcessID,ph); - CloseHandle(ph); + kill_process_tree( pinfo.th32ProcessID, ph ); + CloseHandle( ph ); } } } - CloseHandle(process_snapshot_h); + CloseHandle( process_snapshot_h ); } - /* now that the children are all dead, kill the root */ - TerminateProcess(process,-2); + /* Now that the children are all dead, kill the root. */ + TerminateProcess( process, -2 ); } -static double creation_time(HANDLE process) + +static double creation_time( HANDLE process ) { - FILETIME creation, exit, kernel, user, current; - if (GetProcessTimes(process, &creation, &exit, &kernel, &user)) - { - return filetime_seconds(creation); - } - return 0.0; + FILETIME creation; + FILETIME exit; + FILETIME kernel; + FILETIME user; + FILETIME current; + return GetProcessTimes( process, &creation, &exit, &kernel, &user ) + ? filetime_seconds( creation ) + : 0.0; } -/* Recursive check if first process is parent (directly or indirectly) of -the second one. Both processes are passed as process ids, not handles. -Special return value 2 means that the second process is smss.exe and its -parent process is System (first argument is ignored) */ -static int is_parent_child(DWORD parent, DWORD child) + +/* + * Recursive check if first process is parent (directly or indirectly) of the + * second one. Both processes are passed as process ids, not handles. Special + * return value 2 means that the second process is smss.exe and its parent + * process is System (first argument is ignored). + */ + +static int is_parent_child( DWORD parent, DWORD child ) { HANDLE process_snapshot_h = INVALID_HANDLE_VALUE; - if (!child) + if ( !child ) return 0; - if (parent == child) + if ( parent == child ) return 1; - process_snapshot_h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); - if (INVALID_HANDLE_VALUE != process_snapshot_h) + process_snapshot_h = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); + if ( INVALID_HANDLE_VALUE != process_snapshot_h ) { BOOL ok = TRUE; PROCESSENTRY32 pinfo; - pinfo.dwSize = sizeof(PROCESSENTRY32); + pinfo.dwSize = sizeof( PROCESSENTRY32 ); for ( - ok = Process32First(process_snapshot_h, &pinfo); - ok == TRUE; - ok = Process32Next(process_snapshot_h, &pinfo) ) + ok = Process32First( process_snapshot_h, &pinfo ); + ok == TRUE; + ok = Process32Next( process_snapshot_h, &pinfo ) ) { - if (pinfo.th32ProcessID == child) + if ( pinfo.th32ProcessID == child ) { - /* - Unfortunately, process ids are not really unique. There might - be spurious "parent and child" relationship match between - two non-related processes if real parent process of a given - process has exited (while child process kept running as an - "orphan") and the process id of such parent process has been - reused by internals of the operating system when creating - another process. Thus additional check is needed - process - creation time. This check may fail (ie. return 0) for system - processes due to insufficient privileges, and that's OK. */ + /* Unfortunately, process ids are not really unique. There might + * be spurious "parent and child" relationship match between two + * non-related processes if real parent process of a given + * process has exited (while child process kept running as an + * "orphan") and the process id of such parent process has been + * reused by internals of the operating system when creating + * another process. + * + * Thus additional check is needed - process creation time. This + * check may fail (i.e. return 0) for system processes due to + * insufficient privileges, and that is OK. + */ double tchild = 0.0; double tparent = 0.0; - HANDLE hchild = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pinfo.th32ProcessID); - - CloseHandle(process_snapshot_h); + HANDLE hchild = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pinfo.th32ProcessID ); + CloseHandle( process_snapshot_h ); /* csrss.exe may display message box like following: - xyz.exe - Unable To Locate Component - This application has failed to start because - boost_foo-bar.dll was not found. Re-installing the - application may fix the problem - This actually happens when starting test process that depends - on a dynamic library which failed to build. We want to - automatically close these message boxes even though csrss.exe - is not our child process. We may depend on the fact that (in - all current versions of Windows) csrss.exe is directly - child of smss.exe process, which in turn is directly child of - System process, which always has process id == 4 . - This check must be performed before comparison of process - creation time */ - if (stricmp(pinfo.szExeFile, "csrss.exe") == 0 - && is_parent_child(parent, pinfo.th32ParentProcessID) == 2) - { + * xyz.exe - Unable To Locate Component + * This application has failed to start because + * boost_foo-bar.dll was not found. Re-installing the + * application may fix the problem + * This actually happens when starting test process that depends + * on a dynamic library which failed to build. We want to + * automatically close these message boxes even though csrss.exe + * is not our child process. We may depend on the fact that (in + * all current versions of Windows) csrss.exe is directly child + * of the smss.exe process, which in turn is directly child of + * the System process, which always has process id == 4. This + * check must be performed before comparison of process creation + * times. + */ + if ( !stricmp( pinfo.szExeFile, "csrss.exe" ) && + ( is_parent_child( parent, pinfo.th32ParentProcessID ) == 2 ) ) return 1; - } - else if (stricmp(pinfo.szExeFile, "smss.exe") == 0 - && pinfo.th32ParentProcessID == 4) - { + if ( !stricmp( pinfo.szExeFile, "smss.exe" ) && + ( pinfo.th32ParentProcessID == 4 ) ) return 2; - } - if (hchild != 0) + if ( hchild ) { - HANDLE hparent = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pinfo.th32ParentProcessID); - if (hparent != 0) + HANDLE hparent = OpenProcess( PROCESS_QUERY_INFORMATION, + FALSE, pinfo.th32ParentProcessID ); + if ( hparent ) { - tchild = creation_time(hchild); - tparent = creation_time(hparent); - - CloseHandle(hparent); + tchild = creation_time( hchild ); + tparent = creation_time( hparent ); + CloseHandle( hparent ); } - CloseHandle(hchild); + CloseHandle( hchild ); } - /* return 0 if one of the following is true: - 1. we failed to read process creation time - 2. child was created before alleged parent */ - if (tchild == 0.0 || tparent == 0.0 || tchild < tparent) + /* Return 0 if one of the following is true: + * 1. we failed to read process creation time + * 2. child was created before alleged parent + */ + if ( ( tchild == 0.0 ) || ( tparent == 0.0 ) || + ( tchild < tparent ) ) return 0; - return is_parent_child(parent, pinfo.th32ParentProcessID) & 1; + return is_parent_child( parent, pinfo.th32ParentProcessID ) & 1; } } - CloseHandle(process_snapshot_h); + CloseHandle( process_snapshot_h ); } return 0; } -typedef struct PROCESS_HANDLE_ID {HANDLE h; DWORD pid;} PROCESS_HANDLE_ID; +typedef struct PROCESS_HANDLE_ID { HANDLE h; DWORD pid; } PROCESS_HANDLE_ID; -/* This function is called by the operating system for each topmost window. */ -BOOL CALLBACK close_alert_window_enum(HWND hwnd, LPARAM lParam) + +/* + * This function is called by the operating system for each topmost window. + */ + +BOOL CALLBACK close_alert_window_enum( HWND hwnd, LPARAM lParam ) { - char buf[7] = {0}; - PROCESS_HANDLE_ID p = *((PROCESS_HANDLE_ID*) (lParam)); + char buf[ 7 ] = { 0 }; + PROCESS_HANDLE_ID p = *( (PROCESS_HANDLE_ID *)lParam ); DWORD pid = 0; DWORD tid = 0; - /* we want to find and close any window that: - 1. is visible and - 2. is a dialog and - 3. is displayed by any of our child processes */ - if (!IsWindowVisible(hwnd)) + /* We want to find and close any window that: + * 1. is visible and + * 2. is a dialog and + * 3. is displayed by any of our child processes + */ + if ( !IsWindowVisible( hwnd ) ) return TRUE; - if (!GetClassNameA(hwnd, buf, sizeof(buf))) - return TRUE; /* failed to read class name; presume it's not a dialog */ - - if (strcmp(buf, "#32770") != 0) - return TRUE; /* not a dialog */ + if ( !GetClassNameA( hwnd, buf, sizeof( buf ) ) ) + return TRUE; /* Failed to read class name; presume it is not a dialog. */ - /* GetWindowThreadProcessId returns 0 on error, otherwise thread id - of window message pump thread */ - tid = GetWindowThreadProcessId(hwnd, &pid); - - if (tid && is_parent_child(p.pid, pid)) + if ( strcmp( buf, "#32770" ) ) + return TRUE; /* Not a dialog */ + + /* GetWindowThreadProcessId() returns 0 on error, otherwise thread id of + * window message pump thread. + */ + tid = GetWindowThreadProcessId( hwnd, &pid ); + + if ( tid && is_parent_child( p.pid, pid ) ) { - /* ask really nice */ - PostMessageA(hwnd, WM_CLOSE, 0, 0); - /* now wait and see if it worked. If not, insist */ - if (WaitForSingleObject(p.h, 200) == WAIT_TIMEOUT) + /* Ask really nice. */ + PostMessageA( hwnd, WM_CLOSE, 0, 0 ); + /* Now wait and see if it worked. If not, insist. */ + if ( WaitForSingleObject( p.h, 200 ) == WAIT_TIMEOUT ) { - PostThreadMessageA(tid, WM_QUIT, 0, 0); - WaitForSingleObject(p.h, 300); + PostThreadMessageA( tid, WM_QUIT, 0, 0 ); + WaitForSingleObject( p.h, 300 ); } - - /* done, we do not want to check any other window now */ + + /* Done, we do not want to check any other window now. */ return FALSE; } return TRUE; } -static void close_alert(HANDLE process) + +static void close_alert( HANDLE process ) { - DWORD pid = get_process_id(process); - /* If process already exited or we just cannot get its process id, do not - go any further */ - if (pid) + DWORD pid = get_process_id( process ); + /* If process already exited or we just can not get its process id, do not + * go any further. + */ + if ( pid ) { PROCESS_HANDLE_ID p; p.h = process; - p.pid = pid; - EnumWindows(&close_alert_window_enum, (LPARAM) &p); + p.pid = pid; + EnumWindows( &close_alert_window_enum, (LPARAM)&p ); } } -# endif /* USE_EXECNT */ +#endif /* USE_EXECNT */ diff --git a/src/engine/execunix.c b/src/engine/execunix.c index 15711896e..87da9b816 100644 --- a/src/engine/execunix.c +++ b/src/engine/execunix.c @@ -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 -# include -# include -# include -# include /* needed for vfork(), _exit() prototypes */ -# include -# include -# include +#include "jam.h" +#include "lists.h" +#include "execcmd.h" +#include "output.h" +#include +#include +#include +#include +#include /* needed for vfork(), _exit() prototypes */ +#include +#include +#include #if defined(sun) || defined(__sun) || defined(linux) -#include + #include #endif -# ifdef USE_EXECUNIX -# include +#ifdef USE_EXECUNIX + +#include + +#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 #include @@ -20,150 +20,142 @@ #include /* - * 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 */ diff --git a/src/engine/expand.c b/src/engine/expand.c index 8e5b8794f..890610626 100644 --- a/src/engine/expand.c +++ b/src/engine/expand.c @@ -24,154 +24,149 @@ * * External routines: * - * var_expand() - variable-expand input string into list of strings + * var_expand() - variable-expand input string into list of strings * * Internal routines: * - * var_edit_parse() - parse : modifiers into PATHNAME structure - * var_edit_file() - copy input target name to output, modifying filename - * var_edit_shift() - do upshift/downshift mods + * var_edit_parse() - parse : modifiers into PATHNAME structure. + * var_edit_file() - copy input target name to output, modifying filename. + * var_edit_shift() - do upshift/downshift mods. * * 01/25/94 (seiwald) - $(X)$(UNDEF) was expanding like plain $(X) * 04/13/94 (seiwald) - added shorthand L0 for null list pointer * 01/11/01 (seiwald) - added support for :E=emptyvalue, :J=joinval */ -typedef struct { - PATHNAME f; /* :GDBSMR -- pieces */ - char parent; /* :P -- go to parent directory */ - char filemods; /* one of the above applied */ - char downshift; /* :L -- downshift result */ - char upshift; /* :U -- upshift result */ - char to_slashes; /* :T -- convert "\" to "/" */ - char to_windows; /* :W -- convert cygwin to native paths */ - PATHPART empty; /* :E -- default for empties */ - PATHPART join; /* :J -- join list with char */ +typedef struct +{ + PATHNAME f; /* :GDBSMR -- pieces */ + char parent; /* :P -- go to parent directory */ + char filemods; /* one of the above applied */ + char downshift; /* :L -- downshift result */ + char upshift; /* :U -- upshift result */ + char to_slashes; /* :T -- convert "\" to "/" */ + char to_windows; /* :W -- convert cygwin to native paths */ + PATHPART empty; /* :E -- default for empties */ + PATHPART join; /* :J -- join list with char */ } VAR_EDITS ; -static void var_edit_parse( char *mods, VAR_EDITS *edits ); -static void var_edit_file( char *in, string *out, VAR_EDITS *edits ); -static void var_edit_shift( string *out, VAR_EDITS *edits ); +static void var_edit_parse( char * mods, VAR_EDITS * edits ); +static void var_edit_file ( char * in, string * out, VAR_EDITS * edits ); +static void var_edit_shift( string * out, VAR_EDITS * edits ); + +#define MAGIC_COLON '\001' +#define MAGIC_LEFT '\002' +#define MAGIC_RIGHT '\003' -# define MAGIC_COLON '\001' -# define MAGIC_LEFT '\002' -# define MAGIC_RIGHT '\003' /* - * var_expand() - variable-expand input string into list of strings + * var_expand() - variable-expand input string into list of strings. * - * Would just copy input to output, performing variable expansion, - * except that since variables can contain multiple values the result - * of variable expansion may contain multiple values (a list). Properly - * performs "product" operations that occur in "$(var1)xxx$(var2)" or - * even "$($(var2))". + * Would just copy input to output, performing variable expansion, except that + * since variables can contain multiple values the result of variable expansion + * may contain multiple values (a list). Properly performs "product" operations + * that occur in "$(var1)xxx$(var2)" or even "$($(var2))". * * Returns a newly created list. */ -LIST * -var_expand( - LIST *l, - char *in, - char *end, - LOL *lol, - int cancopyin ) +LIST * var_expand( LIST * l, char * in, char * end, LOL * lol, int cancopyin ) { char out_buf[ MAXSYM ]; - string buf[1]; - string out1[1]; /* Temporary buffer */ + string buf[ 1 ]; + string out1[ 1 ]; /* temporary buffer */ size_t prefix_length; - char *out; - char *inp = in; - char *ov; /* for temp copy of variable in outbuf */ + char * out; + char * inp = in; + char * ov; /* for temp copy of variable in outbuf */ int depth; - if( DEBUG_VAREXP ) + if ( DEBUG_VAREXP ) printf( "expand '%.*s'\n", end - in, in ); - /* This gets alot of cases: $(<) and $(>) */ - - if( in[0] == '$' && in[1] == '(' && in[3] == ')' && in[4] == '\0' ) + /* This gets a lot of cases: $(<) and $(>). */ + if + ( + ( in[ 0 ] == '$' ) && + ( in[ 1 ] == '(' ) && + ( in[ 3 ] == ')' ) && + ( in[ 4 ] == '\0' ) + ) { - switch( in[2] ) + switch ( in[ 2 ] ) { - case '<': - return list_copy( l, lol_get( lol, 0 ) ); + case '<': return list_copy( l, lol_get( lol, 0 ) ); + case '>': return list_copy( l, lol_get( lol, 1 ) ); - case '>': - return list_copy( l, lol_get( lol, 1 ) ); - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return list_copy( l, lol_get( lol, in[2]-'1' ) ); + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return list_copy( l, lol_get( lol, in[ 2 ] - '1' ) ); } } - + /* Expand @() files, to single item plus accompanying file. */ - - if ( in[0] == '@' && in[1] == '(' && *(end-1) == ')' ) + if ( ( in[ 0 ] == '@' ) && ( in[ 1 ] == '(' ) && ( *( end - 1 ) == ')' ) ) { - /* We try the expansion until it fits within the propspective output buffer. */ + /* We try the expansion until it fits within the propective output + * buffer. + */ char * at_buf = 0; int at_size = MAXJPATH; int at_len = 0; do { - BJAM_FREE(at_buf); - at_buf = (char*)BJAM_MALLOC_ATOMIC(at_size + 1); + BJAM_FREE( at_buf ); + at_buf = (char *)BJAM_MALLOC_ATOMIC( at_size + 1 ); at_len = var_string( in, at_buf, at_size, lol ); at_size *= 2; - } while ( at_len < 0 && at_size < INT_MAX / 2 ); + } + while ( ( at_len < 0 ) && ( at_size < INT_MAX / 2 ) ); /* Return the result as a single item list. */ if ( at_len > 0 ) { LIST * r; string_copy( buf, at_buf ); - r = list_new( l, newstr( buf->value) ); + r = list_new( l, newstr( buf->value ) ); string_free( buf ); - BJAM_FREE(at_buf); + BJAM_FREE( at_buf ); return r; } - BJAM_FREE(at_buf); + BJAM_FREE( at_buf ); } /* Just try simple copy of in to out. */ - - while( in < end ) - if( *in++ == '$' && *in == '(' ) + while ( in < end ) + if ( ( *in++ == '$' ) && ( *in == '(' ) ) goto expand; /* No variables expanded - just add copy of input string to list. */ - /* Cancopyin is an optimization: if the input was already a list */ - /* item, we can use the copystr() to put it on the new list. */ - /* Otherwise, we use the slower newstr(). */ - - if( cancopyin ) - { + /* 'cancopyin' is an optimization: if the input was already a list item, we + * can use copystr() to put it on the new list. Otherwise, we use the slower + * newstr(). + */ + if ( cancopyin ) return list_new( l, copystr( inp ) ); - } - else + { - LIST* r; + LIST * r; string_new( buf ); string_append_range( buf, inp, end ); - - r = list_new( l, newstr( buf->value) ); + r = list_new( l, newstr( buf->value ) ); string_free( buf ); return r; } expand: string_new( buf ); - string_append_range( buf, inp, in - 1); /* copy the part before '$'. */ + string_append_range( buf, inp, in - 1 ); /* Copy the part before '$'. */ /* * Input so far (ignore blanks): * @@ -185,23 +180,22 @@ expand: * out_buf out * * - * We just copied the $ of $(...), so back up one on the output. - * We now find the matching close paren, copying the variable and - * modifiers between the $( and ) temporarily into out_buf, so that - * we can replace :'s with MAGIC_COLON. This is necessary to avoid - * being confused by modifier values that are variables containing - * :'s. Ugly. + * We just copied the $ of $(...), so back up one on the output. We now find + * the matching close paren, copying the variable and modifiers between the + * $( and ) temporarily into out_buf, so that we can replace :'s with + * MAGIC_COLON. This is necessary to avoid being confused by modifier values + * that are variables containing :'s. Ugly. */ depth = 1; - inp = ++in; /* skip over the '(' */ + inp = ++in; /* Skip over the '('. */ - while( in < end && depth ) + while ( ( in < end ) && depth ) { - switch( *in++ ) + switch ( *in++ ) { - case '(': depth++; break; - case ')': depth--; break; + case '(': ++depth; break; + case ')': --depth; break; } } @@ -218,11 +212,11 @@ expand: out = buf->value + prefix_length; for ( ov = out; ov < buf->value + buf->size; ++ov ) { - switch( *ov ) + switch ( *ov ) { - case ':': *ov = MAGIC_COLON; break; - case '[': *ov = MAGIC_LEFT; break; - case ']': *ov = MAGIC_RIGHT; break; + case ':': *ov = MAGIC_COLON; break; + case '[': *ov = MAGIC_LEFT ; break; + case ']': *ov = MAGIC_RIGHT; break; } } @@ -238,79 +232,72 @@ expand: * ^ ^ ^ * out_buf out ov * - * Later we will overwrite 'variable' in out_buf, but we'll be - * done with it by then. 'variable' may be a multi-element list, - * so may each value for '$(variable element)', and so may 'remainder'. - * Thus we produce a product of three lists. + * Later we will overwrite 'variable' in out_buf, but we will be done with + * it by then. 'variable' may be a multi-element list, so may each value for + * '$(variable element)', and so may 'remainder'. Thus we produce a product + * of three lists. */ - { - LIST *variables = 0; - LIST *remainder = 0; - LIST *vars; + LIST * variables = 0; + LIST * remainder = 0; + LIST * vars; - /* Recursively expand variable name & rest of input */ + /* Recursively expand variable name & rest of input. */ + if ( out < ov ) variables = var_expand( L0, out, ov, lol, 0 ); + if ( in < end ) remainder = var_expand( L0, in, end, lol, 0 ); - if( out < ov ) - variables = var_expand( L0, out, ov, lol, 0 ); - if( in < end ) - remainder = var_expand( L0, in, end, lol, 0 ); + /* Now produce the result chain. */ - /* Now produce the result chain */ - - /* For each variable name */ - - for( vars = variables; vars; vars = list_next( vars ) ) + /* For each variable name. */ + for ( vars = variables; vars; vars = list_next( vars ) ) { - LIST *value, *evalue = 0; - char *colon; - char *bracket; + LIST * value = 0; + LIST * evalue = 0; + char * colon; + char * bracket; string variable[1]; - char *varname; - int sub1 = 0, sub2 = -1; + char * varname; + int sub1 = 0; + int sub2 = -1; VAR_EDITS edits; - /* Look for a : modifier in the variable name */ - /* Must copy into varname so we can modify it */ - + /* Look for a : modifier in the variable name. Must copy into + * varname so we can modify it. + */ string_copy( variable, vars->string ); varname = variable->value; - if( colon = strchr( varname, MAGIC_COLON ) ) + if ( ( colon = strchr( varname, MAGIC_COLON ) ) ) { string_truncate( variable, colon - varname ); var_edit_parse( colon + 1, &edits ); } - /* Look for [x-y] subscripting */ - /* sub1 and sub2 are x and y. */ - - if ( bracket = strchr( varname, MAGIC_LEFT ) ) + /* Look for [x-y] subscripting. sub1 and sub2 are x and y. */ + if ( ( bracket = strchr( varname, MAGIC_LEFT ) ) ) { - /* - ** Make all syntax errors in [] subscripting - ** result in the same behavior: silenty return an empty - ** expansion (by setting sub2 = 0). Brute force parsing; - ** May get moved into yacc someday. - */ + /* Make all syntax errors in [] subscripting result in the same + * behavior: silenty return an empty expansion (by setting sub2 + * = 0). Brute force parsing; May get moved into yacc someday. + */ - char *s = bracket + 1; + char * s = bracket + 1; string_truncate( variable, bracket - varname ); do /* so we can use "break" */ { /* Allow negative indexes. */ - if (! isdigit( *s ) && ! ( *s == '-') ) + if ( !isdigit( *s ) && ( *s != '-' ) ) { sub2 = 0; break; } - sub1 = atoi(s); + sub1 = atoi( s ); /* Skip over the first symbol, which is either a digit or dash. */ - s++; - while ( isdigit( *s ) ) s++; + ++s; + while ( isdigit( *s ) ) ++s; if ( *s == MAGIC_RIGHT ) { @@ -318,13 +305,13 @@ expand: break; } - if ( *s != '-') + if ( *s != '-' ) { sub2 = 0; break; } - s++; + ++s; if ( *s == MAGIC_RIGHT ) { @@ -332,119 +319,114 @@ expand: break; } - if (! isdigit( *s ) && ! ( *s == '-') ) + if ( !isdigit( *s ) && ( *s != '-' ) ) { sub2 = 0; break; } /* First, compute the index of the last element. */ - sub2 = atoi(s); - s++; - while ( isdigit( *s ) ) s++; + sub2 = atoi( s ); + while ( isdigit( *++s ) ); - if ( *s != MAGIC_RIGHT) + if ( *s != MAGIC_RIGHT ) sub2 = 0; - } while (0); + } while ( 0 ); - /* - ** Anything but the end of the string, or the colon - ** introducing a modifier is a syntax error. - */ - - s++; - if (*s && *s != MAGIC_COLON) + /* Anything but the end of the string, or the colon introducing + * a modifier is a syntax error. + */ + ++s; + if ( *s && ( *s != MAGIC_COLON ) ) sub2 = 0; *bracket = '\0'; } - /* Get variable value, specially handling $(<), $(>), $(n) */ - - if( varname[0] == '<' && !varname[1] ) - value = lol_get( lol, 0 ); - else if( varname[0] == '>' && !varname[1] ) - value = lol_get( lol, 1 ); - else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] ) - value = lol_get( lol, varname[0] - '1' ); - else + /* Get variable value, with special handling for $(<), $(>), $(n). + */ + if ( !varname[1] ) + { + if ( varname[0] == '<' ) + value = lol_get( lol, 0 ); + else if ( varname[0] == '>' ) + value = lol_get( lol, 1 ); + else if ( ( varname[0] >= '1' ) && ( varname[0] <= '9' ) ) + value = lol_get( lol, varname[0] - '1' ); + } + + if ( !value ) value = var_get( varname ); /* Handle negitive indexes: part two. */ { int length = list_length( value ); - if (sub1 < 0) + if ( sub1 < 0 ) sub1 = length + sub1; else sub1 -= 1; - if (sub2 < 0) + if ( sub2 < 0 ) sub2 = length + 1 + sub2 - sub1; else sub2 -= sub1; - /* - ** The "sub2 < 0" test handles the semantic error - ** of sub2 < sub1. - */ + /* The "sub2 < 0" test handles the semantic error of sub2 < + * sub1. + */ if ( sub2 < 0 ) sub2 = 0; } - - - /* The fast path: $(x) - just copy the variable value. */ - /* This is only an optimization */ - - if( out == out_buf && !bracket && !colon && in == end ) + /* The fast path: $(x) - just copy the variable value. This is only + * an optimization. + */ + if ( ( out == out_buf ) && !bracket && !colon && ( in == end ) ) { string_free( variable ); l = list_copy( l, value ); continue; } - /* Handle start subscript */ - - while( sub1 > 0 && value ) + /* Handle start subscript. */ + while ( ( sub1 > 0 ) && value ) --sub1, value = list_next( value ); - /* Empty w/ :E=default? */ - - if( !value && colon && edits.empty.ptr ) + /* Empty w/ :E=default?. */ + if ( !value && colon && edits.empty.ptr ) evalue = value = list_new( L0, newstr( edits.empty.ptr ) ); - /* For each variable value */ - + /* For each variable value. */ string_new( out1 ); - for( ; value; value = list_next( value ) ) + for ( ; value; value = list_next( value ) ) { - LIST *rem; + LIST * rem; size_t postfix_start; - /* Handle end subscript (length actually) */ + /* Handle end subscript (length actually). */ - if( sub2 >= 0 && --sub2 < 0 ) + if ( sub2 >= 0 && --sub2 < 0 ) break; string_truncate( buf, prefix_length ); /* Apply : mods, if present */ - if( colon && edits.filemods ) + if ( colon && edits.filemods ) var_edit_file( value->string, out1, &edits ); else string_append( out1, value->string ); - if( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) ) + if ( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) ) var_edit_shift( out1, &edits ); /* Handle :J=joinval */ - /* If we have more values for this var, just */ - /* keep appending them (with the join value) */ - /* rather than creating separate LIST elements. */ - - if( colon && edits.join.ptr && + /* If we have more values for this var, just keep appending them + * (using the join value) rather than creating separate LIST + * elements. + */ + if ( colon && edits.join.ptr && ( list_next( value ) || list_next( vars ) ) ) { string_append( out1, edits.join.ptr ); @@ -456,21 +438,18 @@ expand: string_new( out1 ); /* If no remainder, append result to output chain. */ - - if( in == end ) + if ( in == end ) { l = list_new( l, newstr( buf->value ) ); continue; } - /* For each remainder, append the complete string */ - /* to the output chain. */ - /* Remember the end of the variable expansion so */ - /* we can just tack on each instance of 'remainder' */ - + /* For each remainder, append the complete string to the output + * chain. Remember the end of the variable expansion so we can + * just tack on each instance of 'remainder'. + */ postfix_start = buf->size; - - for( rem = remainder; rem; rem = list_next( rem ) ) + for ( rem = remainder; rem; rem = list_next( rem ) ) { string_truncate( buf, postfix_start ); string_append( buf, rem->string ); @@ -479,23 +458,18 @@ expand: } string_free( out1 ); - /* Toss used empty */ - - if( evalue ) + /* Toss used empty. */ + if ( evalue ) list_free( evalue ); string_free( variable ); } - /* variables & remainder were gifts from var_expand */ - /* and must be freed */ + /* variables & remainder were gifts from var_expand and must be freed. */ + if ( variables ) list_free( variables ); + if ( remainder ) list_free( remainder ); - if( variables ) - list_free( variables ); - if( remainder) - list_free( remainder ); - - if( DEBUG_VAREXP ) + if ( DEBUG_VAREXP ) { printf( "expanded to " ); list_print( l ); @@ -507,201 +481,169 @@ expand: } } + /* * var_edit_parse() - parse : modifiers into PATHNAME structure * - * The : modifiers in a $(varname:modifier) currently support replacing - * or omitting elements of a filename, and so they are parsed into a - * PATHNAME structure (which contains pointers into the original string). + * The : modifiers in a $(varname:modifier) currently support replacing or + * omitting elements of a filename, and so they are parsed into a PATHNAME + * structure (which contains pointers into the original string). * - * Modifiers of the form "X=value" replace the component X with - * the given value. Modifiers without the "=value" cause everything - * but the component X to be omitted. X is one of: + * Modifiers of the form "X=value" replace the component X with the given value. + * Modifiers without the "=value" cause everything but the component X to be + * omitted. X is one of: * - * G - * D directory name - * B base name - * S .suffix - * M (member) - * R root directory - prepended to whole path + * G + * D directory name + * B base name + * S .suffix + * M (member) + * R root directory - prepended to whole path * * This routine sets: * - * f->f_xxx.ptr = 0 - * f->f_xxx.len = 0 - * -> leave the original component xxx + * f->f_xxx.ptr = 0 + * f->f_xxx.len = 0 + * -> leave the original component xxx * - * f->f_xxx.ptr = string - * f->f_xxx.len = strlen( string ) - * -> replace component xxx with string + * f->f_xxx.ptr = string + * f->f_xxx.len = strlen( string ) + * -> replace component xxx with string * - * f->f_xxx.ptr = "" - * f->f_xxx.len = 0 - * -> omit component xxx + * f->f_xxx.ptr = "" + * f->f_xxx.len = 0 + * -> omit component xxx * * var_edit_file() below and path_build() obligingly follow this convention. */ -static void -var_edit_parse( - char *mods, - VAR_EDITS *edits ) +static void var_edit_parse( char * mods, VAR_EDITS * edits ) { - int havezeroed = 0; - memset( (char *)edits, 0, sizeof( *edits ) ); + int havezeroed = 0; + memset( (char *)edits, 0, sizeof( *edits ) ); - while( *mods ) - { - char *p; - PATHPART *fp; + while ( *mods ) + { + char * p; + PATHPART * fp; - switch( *mods++ ) - { - case 'L': edits->downshift = 1; continue; - case 'U': edits->upshift = 1; continue; - case 'P': edits->parent = edits->filemods = 1; continue; - case 'E': fp = &edits->empty; goto strval; - case 'J': fp = &edits->join; goto strval; - case 'G': fp = &edits->f.f_grist; goto fileval; - case 'R': fp = &edits->f.f_root; goto fileval; - case 'D': fp = &edits->f.f_dir; goto fileval; - case 'B': fp = &edits->f.f_base; goto fileval; - case 'S': fp = &edits->f.f_suffix; goto fileval; - case 'M': fp = &edits->f.f_member; goto fileval; + switch ( *mods++ ) + { + case 'L': edits->downshift = 1; continue; + case 'U': edits->upshift = 1; continue; + case 'P': edits->parent = edits->filemods = 1; continue; + case 'E': fp = &edits->empty; goto strval; + case 'J': fp = &edits->join; goto strval; + case 'G': fp = &edits->f.f_grist; goto fileval; + case 'R': fp = &edits->f.f_root; goto fileval; + case 'D': fp = &edits->f.f_dir; goto fileval; + case 'B': fp = &edits->f.f_base; goto fileval; + case 'S': fp = &edits->f.f_suffix; goto fileval; + case 'M': fp = &edits->f.f_member; goto fileval; case 'T': edits->to_slashes = 1; continue; case 'W': edits->to_windows = 1; continue; + default: + return; /* Should complain, but so what... */ + } - default: return; /* should complain, but so what... */ - } + fileval: + /* Handle :CHARS, where each char (without a following =) selects a + * particular file path element. On the first such char, we deselect all + * others (by setting ptr = "", len = 0) and for each char we select + * that element (by setting ptr = 0). + */ + edits->filemods = 1; - fileval: + if ( *mods != '=' ) + { + if ( !havezeroed++ ) + { + int i; + for ( i = 0; i < 6; ++i ) + { + edits->f.part[ i ].len = 0; + edits->f.part[ i ].ptr = ""; + } + } - /* Handle :CHARS, where each char (without a following =) */ - /* selects a particular file path element. On the first such */ - /* char, we deselect all others (by setting ptr = "", len = 0) */ - /* and for each char we select that element (by setting ptr = 0) */ + fp->ptr = 0; + continue; + } - edits->filemods = 1; - - if( *mods != '=' ) - { - int i; - - if( !havezeroed++ ) - for( i = 0; i < 6; i++ ) - { - edits->f.part[ i ].len = 0; - edits->f.part[ i ].ptr = ""; - } - - fp->ptr = 0; - continue; - } - - strval: - - /* Handle :X=value, or :X */ - - if( *mods != '=' ) - { - fp->ptr = ""; - fp->len = 0; - } - else if( p = strchr( mods, MAGIC_COLON ) ) - { - *p = 0; - fp->ptr = ++mods; - fp->len = p - mods; - mods = p + 1; - } - else - { - fp->ptr = ++mods; - fp->len = strlen( mods ); - mods += fp->len; - } - } + strval: + /* Handle :X=value, or :X */ + if ( *mods != '=' ) + { + fp->ptr = ""; + fp->len = 0; + } + else if ( ( p = strchr( mods, MAGIC_COLON ) ) ) + { + *p = 0; + fp->ptr = ++mods; + fp->len = p - mods; + mods = p + 1; + } + else + { + fp->ptr = ++mods; + fp->len = strlen( mods ); + mods += fp->len; + } + } } + /* - * var_edit_file() - copy input target name to output, modifying filename + * var_edit_file() - copy input target name to output, modifying filename. */ - -static void -var_edit_file( - char *in, - string *out, - VAR_EDITS *edits ) + +static void var_edit_file( char * in, string * out, VAR_EDITS * edits ) { - PATHNAME pathname; + PATHNAME pathname; - /* Parse apart original filename, putting parts into "pathname" */ + /* Parse apart original filename, putting parts into "pathname". */ + path_parse( in, &pathname ); - path_parse( in, &pathname ); + /* Replace any pathname with edits->f */ + if ( edits->f.f_grist .ptr ) pathname.f_grist = edits->f.f_grist; + if ( edits->f.f_root .ptr ) pathname.f_root = edits->f.f_root; + if ( edits->f.f_dir .ptr ) pathname.f_dir = edits->f.f_dir; + if ( edits->f.f_base .ptr ) pathname.f_base = edits->f.f_base; + if ( edits->f.f_suffix.ptr ) pathname.f_suffix = edits->f.f_suffix; + if ( edits->f.f_member.ptr ) pathname.f_member = edits->f.f_member; - /* Replace any pathname with edits->f */ - - if( edits->f.f_grist.ptr ) - pathname.f_grist = edits->f.f_grist; - - if( edits->f.f_root.ptr ) - pathname.f_root = edits->f.f_root; - - if( edits->f.f_dir.ptr ) - pathname.f_dir = edits->f.f_dir; - - if( edits->f.f_base.ptr ) - pathname.f_base = edits->f.f_base; - - if( edits->f.f_suffix.ptr ) - pathname.f_suffix = edits->f.f_suffix; - - if( edits->f.f_member.ptr ) - pathname.f_member = edits->f.f_member; - - /* If requested, modify pathname to point to parent */ - - if( edits->parent ) - path_parent( &pathname ); - - /* Put filename back together */ + /* If requested, modify pathname to point to parent. */ + if ( edits->parent ) + path_parent( &pathname ); + /* Put filename back together. */ path_build( &pathname, out, 0 ); } + /* - * var_edit_shift() - do upshift/downshift mods + * var_edit_shift() - do upshift/downshift mods. */ -static void -var_edit_shift( - string *out, - VAR_EDITS *edits ) +static void var_edit_shift( string * out, VAR_EDITS * edits ) { - /* Handle upshifting, downshifting and slash translation now */ - - char *p; + /* Handle upshifting, downshifting and slash translation now. */ + char * p; for ( p = out->value; *p; ++p) { - if (edits->upshift) - { + if ( edits->upshift ) *p = toupper( *p ); - } else if ( edits->downshift ) - { *p = tolower( *p ); - } - if ( edits->to_slashes ) - { - if ( *p == '\\') - *p = '/'; - } + if ( edits->to_slashes && ( *p == '\\' ) ) + *p = '/'; # ifdef OS_CYGWIN if ( edits->to_windows ) { - char result[MAX_PATH + 1]; - cygwin_conv_to_win32_path(out->value, result); - assert(strlen(result) <= MAX_PATH); + char result[ MAX_PATH + 1 ]; + cygwin_conv_to_win32_path( out->value, result ); + assert( strlen( result ) <= MAX_PATH ); string_free( out ); string_copy( out, result ); } @@ -710,59 +652,61 @@ var_edit_shift( out->size = p - out->value; } + #ifndef NDEBUG void var_expand_unit_test() { - LOL lol[1]; - LIST* l, *l2; - LIST *expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) ); - LIST *e2; + LOL lol[ 1 ]; + LIST * l; + LIST * l2; + LIST * expected = list_new( list_new( L0, newstr( "axb" ) ), newstr( "ayb" ) ); + LIST * e2; char axyb[] = "a$(xy)b"; char azb[] = "a$($(z))b"; char path[] = "$(p:W)"; - - # ifdef OS_CYGWIN - char cygpath[256]; - cygwin_conv_to_posix_path("c:\\foo\\bar", cygpath); - # else + +# ifdef OS_CYGWIN + char cygpath[ 256 ]; + cygwin_conv_to_posix_path( "c:\\foo\\bar", cygpath ); +# else char cygpath[] = "/cygdrive/c/foo/bar"; - # endif - +# endif + lol_init(lol); - var_set("xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET ); - var_set("z", list_new( L0, newstr( "xy" ) ), VAR_SET ); - var_set("p", list_new( L0, newstr( cygpath ) ), VAR_SET ); + var_set( "xy", list_new( list_new( L0, newstr( "x" ) ), newstr( "y" ) ), VAR_SET ); + var_set( "z", list_new( L0, newstr( "xy" ) ), VAR_SET ); + var_set( "p", list_new( L0, newstr( cygpath ) ), VAR_SET ); - l = var_expand( 0, axyb, axyb + sizeof(axyb) - 1, lol, 0 ); - for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) ) + l = var_expand( 0, axyb, axyb + sizeof( axyb ) - 1, lol, 0 ); + for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) ) assert( !strcmp( e2->string, l2->string ) ); - assert(l2 == 0 && e2 == 0); - list_free(l); - - l = var_expand( 0, azb, azb + sizeof(azb) - 1, lol, 0 ); - for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next(l2), e2 = list_next(e2) ) - assert( !strcmp( e2->string, l2->string ) ); - assert(l2 == 0 && e2 == 0); - list_free(l); + assert( l2 == 0 ); + assert( e2 == 0 ); + list_free( l ); - l = var_expand( 0, path, path + sizeof(path) - 1, lol, 0 ); - assert(l != 0); - assert(list_next(l) == 0); - # ifdef OS_CYGWIN - assert( !strcmp( l->string, "c:\\foo\\bar" ) ); - # else + l = var_expand( 0, azb, azb + sizeof( azb ) - 1, lol, 0 ); + for ( l2 = l, e2 = expected; l2 && e2; l2 = list_next( l2 ), e2 = list_next( e2 ) ) + assert( !strcmp( e2->string, l2->string ) ); + assert( l2 == 0 ); + assert( e2 == 0 ); + list_free( l ); + + l = var_expand( 0, path, path + sizeof( path ) - 1, lol, 0 ); + assert( l != 0 ); + assert( list_next( l ) == 0 ); +# ifdef OS_CYGWIN + /* On some installations of cygwin the drive letter is expanded to other + * case. This has been reported to be the case if cygwin has been installed + * to C:\ as opposed to C:\cygwin. Since case of the drive letter will not + * matter, we allow for both. + */ + assert( !strcmp( l->string, "c:\\foo\\bar" ) || + !strcmp( l->string, "C:\\foo\\bar" ) ); +# else assert( !strcmp( l->string, cygpath ) ); - # endif - list_free(l); - - list_free(expected); - - lol_free(lol); +# endif + list_free( l ); + list_free( expected ); + lol_free( lol ); } #endif - -/* - Local Variables: - tab-width: 8 - End: - */ diff --git a/src/engine/expand.h b/src/engine/expand.h index 351d39113..cc25d1909 100644 --- a/src/engine/expand.h +++ b/src/engine/expand.h @@ -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(); diff --git a/src/engine/filemac.c b/src/engine/filemac.c index 1eab3367d..06074417d 100644 --- a/src/engine/filemac.c +++ b/src/engine/filemac.c @@ -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 */ - diff --git a/src/engine/filent.c b/src/engine/filent.c index 7ec01c3ae..0bef792b9 100644 --- a/src/engine/filent.c +++ b/src/engine/filent.c @@ -25,7 +25,7 @@ # include # include # 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 "!\n" -#define SARMAG 8 +#define ARMAG "!\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 */ diff --git a/src/engine/fileos2.c b/src/engine/fileos2.c index 2821a4c2a..af2373ea8 100644 --- a/src/engine/fileos2.c +++ b/src/engine/fileos2.c @@ -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 ) { } diff --git a/src/engine/filesys.c b/src/engine/filesys.c index 3fbea962f..eb62ed406 100644 --- a/src/engine/filesys.c +++ b/src/engine/filesys.c @@ -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; } diff --git a/src/engine/filesys.h b/src/engine/filesys.h index a442d8268..9281c8674 100644 --- a/src/engine/filesys.h +++ b/src/engine/filesys.h @@ -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 diff --git a/src/engine/fileunix.c b/src/engine/fileunix.c index 313040dd3..51267a0ca 100644 --- a/src/engine/fileunix.c +++ b/src/engine/fileunix.c @@ -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 # include -# define STRUCT_DIRENT struct direct +# define STRUCT_DIRENT struct direct # else # include -# 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 "!\n" -#define SARMAG 8 -#define ARFMAG "`\n" +#define ARMAG "!\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 -# 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 ); } diff --git a/src/engine/filevms.c b/src/engine/filevms.c index ce2d9031c..d2ab2047f 100644 --- a/src/engine/filevms.c +++ b/src/engine/filevms.c @@ -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 */ - diff --git a/src/engine/frames.c b/src/engine/frames.c index 80b7197ed..84889f09e 100644 --- a/src/engine/frames.c +++ b/src/engine/frames.c @@ -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) diff --git a/src/engine/frames.h b/src/engine/frames.h index 535784141..693d77fa0 100644 --- a/src/engine/frames.h +++ b/src/engine/frames.h @@ -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 - diff --git a/src/engine/glob.c b/src/engine/glob.c index abb56eb1b..527d6c808 100644 --- a/src/engine/glob.c +++ b/src/engine/glob.c @@ -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; } diff --git a/src/engine/hash.c b/src/engine/hash.c index 318a2acef..8ca25cc5e 100644 --- a/src/engine/hash.c +++ b/src/engine/hash.c @@ -9,8 +9,8 @@ # include "compile.h" # include -/* - * 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 ); } diff --git a/src/engine/hash.h b/src/engine/hash.h index 11f0e7b3c..7195b4146 100644 --- a/src/engine/hash.h +++ b/src/engine/hash.h @@ -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 diff --git a/src/engine/hcache.c b/src/engine/hcache.c index 5d2f24140..e34aa9e94 100644 --- a/src/engine/hcache.c +++ b/src/engine/hcache.c @@ -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 : ""); - 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 : "" ); + 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); diff --git a/src/engine/hdrmacro.c b/src/engine/hdrmacro.c index 486039a1e..43031d48f 100644 --- a/src/engine/hdrmacro.c +++ b/src/engine/hdrmacro.c @@ -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) : ; + * $(HDRRULE) : ; * * 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; } - diff --git a/src/engine/headers.c b/src/engine/headers.c index d6bd9fa24..b9d8f6370 100644 --- a/src/engine/headers.c +++ b/src/engine/headers.c @@ -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) : ; + * + * $(HDRRULE) : ; * * 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 ); } diff --git a/src/engine/jam.c b/src/engine/jam.c index 3c0b40500..b68a9cb58 100644 --- a/src/engine/jam.c +++ b/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 -# endif - -/* And UNIX for this */ - -# ifdef unix -# include -# include -# 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 #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 + #include +#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; } diff --git a/src/engine/jam.h b/src/engine/jam.h index cfae431ff..38680c0fc 100644 --- a/src/engine/jam.h +++ b/src/engine/jam.h @@ -49,80 +49,81 @@ * VMS, OPENVMS */ -# ifdef VMS +#ifdef VMS -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -# 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 -# include -# include -# include -# include -# ifndef __MWERKS__ -# include +#include +#include +#include +#include +#include +#ifndef __MWERKS__ + #include #endif -# include -# include -# include +#include +#include +#include -# 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 -# include -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include +#include +#include -# 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 -# include -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include +#include +#include -# 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 -# include -# include -# include +#include +#include +#include +#include -# 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 -# include +#include +#include -# ifndef OS_MPEIX -# include -# endif +#ifndef OS_MPEIX + #include +#endif -# include -# include -# include -# include -# include -# include +#include +#include +#include +#include +#include +#include -# ifndef OS_QNX -# include -# endif +#ifndef OS_QNX + #include +#endif -# ifndef OS_ULTRIX -# include -# endif +#ifndef OS_ULTRIX + #include +#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 -# 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 +#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" diff --git a/src/engine/jambase.c b/src/engine/jambase.c index 772b685dd..dbcf263e3 100644 --- a/src/engine/jambase.c +++ b/src/engine/jambase.c @@ -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", diff --git a/src/engine/jambase.h b/src/engine/jambase.h index 75393f4cc..c05ec7922 100644 --- a/src/engine/jambase.h +++ b/src/engine/jambase.h @@ -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. */ diff --git a/src/engine/jamgram.c b/src/engine/jamgram.c index 26e0460b5..b1fa0835d 100644 --- a/src/engine/jamgram.c +++ b/src/engine/jamgram.c @@ -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; diff --git a/src/engine/jamgram.y b/src/engine/jamgram.y index 6ce30b245..c26b1e1b6 100644 --- a/src/engine/jamgram.y +++ b/src/engine/jamgram.y @@ -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; } ; - - diff --git a/src/engine/jamgram.yy b/src/engine/jamgram.yy index f3fbc71ad..152434871 100644 --- a/src/engine/jamgram.yy +++ b/src/engine/jamgram.yy @@ -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 ); } ; diff --git a/src/engine/lists.c b/src/engine/lists.c index 205c9777b..df0eff4d5 100644 --- a/src/engine/lists.c +++ b/src/engine/lists.c @@ -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 ] ); + } } diff --git a/src/engine/lists.h b/src/engine/lists.h index 590fefc95..50362a66f 100644 --- a/src/engine/lists.h +++ b/src/engine/lists.h @@ -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 diff --git a/src/engine/make.c b/src/engine/make.c index 5bb5dc34b..c871f0be2 100644 --- a/src/engine/make.c +++ b/src/engine/make.c @@ -11,847 +11,804 @@ */ /* - * make.c - bring a target up to date, once rules are in place + * make.c - bring a target up to date, once rules are in place. * - * This modules controls the execution of rules to bring a target and - * its dependencies up to date. It is invoked after the targets, rules, - * et. al. described in rules.h are created by the interpreting of the - * jam files. + * This modules controls the execution of rules to bring a target and its + * dependencies up to date. It is invoked after the targets, rules, et. al. + * described in rules.h are created by the interpreting jam files. * - * This file contains the main make() entry point and the first pass - * make0(). The second pass, make1(), which actually does the command - * execution, is in make1.c. + * This file contains the main make() entry point and the first pass make0(). + * The second pass, make1(), which actually does the command execution, is in + * make1.c. * * External routines: - * make() - make a target, given its name + * make() - make a target, given its name * * Internal routines: - * make0() - bind and scan everything to make a TARGET - * make0sort() - reorder TARGETS chain by their time (newest to oldest) + * make0() - bind and scan everything to make a TARGET + * make0sort() - reorder TARGETS chain by their time (newest to oldest) * - * 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>) - * 01/04/94 (seiwald) - print all targets, bounded, when tracing commands - * 04/08/94 (seiwald) - progress report now reflects only targets with actions + * 12/26/93 (seiwald) - allow NOTIME targets to be expanded via $(<), $(>). + * 01/04/94 (seiwald) - print all targets, bounded, when tracing commands. + * 04/08/94 (seiwald) - progress report now reflects only targets with actions. * 04/11/94 (seiwald) - Combined deps & headers into deps[2] in TARGET. * 12/20/94 (seiwald) - NOTIME renamed NOTFILE. - * 12/20/94 (seiwald) - make0() headers after determining fate of target, so - * that headers aren't seen as dependents on themselves. + * 12/20/94 (seiwald) - make0() headers after determining fate of target, so + * that headers are not seen as being dependent on + * themselves. * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets. * 02/02/95 (seiwald) - propagate leaf source time for new LEAVES rule. * 02/14/95 (seiwald) - NOUPDATE rule means don't update existing target. * 08/22/95 (seiwald) - NOUPDATE targets immune to anyhow (-a) flag. * 09/06/00 (seiwald) - NOCARE affects targets with sources/actions. * 03/02/01 (seiwald) - reverse NOCARE change. - * 03/14/02 (seiwald) - TEMPORARY targets no longer take on parents age - * 03/16/02 (seiwald) - support for -g (reorder builds by source time) + * 03/14/02 (seiwald) - TEMPORARY targets no longer take on parents age. + * 03/16/02 (seiwald) - support for -g (reorder builds by source time). */ -# 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" #ifdef OPT_HEADER_CACHE_EXT -# include "hcache.h" + #include "hcache.h" #endif -# include "search.h" -# include "newstr.h" -# include "make.h" -# include "headers.h" -# include "command.h" -# include +#include "search.h" +#include "newstr.h" +#include "make.h" +#include "headers.h" +#include "command.h" +#include -# ifndef max -# define max( a,b ) ((a)>(b)?(a):(b)) -# endif +#ifndef max + #define max( a,b ) ((a)>(b)?(a):(b)) +#endif -static TARGETS *make0sort( TARGETS *c ); +static TARGETS * make0sort( TARGETS * c ); #ifdef OPT_GRAPH_DEBUG_EXT -static void dependGraphOutput( TARGET *t, int depth ); + static void dependGraphOutput( TARGET * t, int depth ); #endif -static const char *target_fate[] = +static const char * target_fate[] = { - "init", /* T_FATE_INIT */ - "making", /* T_FATE_MAKING */ - "stable", /* T_FATE_STABLE */ - "newer", /* T_FATE_NEWER */ - "temp", /* T_FATE_ISTMP */ - "touched", /* T_FATE_TOUCHED */ - "rebuild", /* T_FATE_REBUILD */ - "missing", /* T_FATE_MISSING */ - "needtmp", /* T_FATE_NEEDTMP */ - "old", /* T_FATE_OUTDATED */ - "update", /* T_FATE_UPDATE */ - "nofind", /* T_FATE_CANTFIND */ - "nomake" /* T_FATE_CANTMAKE */ -} ; + "init", /* T_FATE_INIT */ + "making", /* T_FATE_MAKING */ + "stable", /* T_FATE_STABLE */ + "newer", /* T_FATE_NEWER */ + "temp", /* T_FATE_ISTMP */ + "touched", /* T_FATE_TOUCHED */ + "rebuild", /* T_FATE_REBUILD */ + "missing", /* T_FATE_MISSING */ + "needtmp", /* T_FATE_NEEDTMP */ + "old", /* T_FATE_OUTDATED */ + "update", /* T_FATE_UPDATE */ + "nofind", /* T_FATE_CANTFIND */ + "nomake" /* T_FATE_CANTMAKE */ +}; -static const char *target_bind[] = +static const char * target_bind[] = { - "unbound", - "missing", - "parents", - "exists", -} ; + "unbound", + "missing", + "parents", + "exists", +}; # define spaces(x) ( " " + ( x > 20 ? 0 : 20-x ) ) + /* - * make() - make a target, given its name + * make() - make a target, given its name. */ -int -make( - int n_targets, - const char **targets, - int anyhow ) +int make( int n_targets, char const * * targets, int anyhow ) { - int i; - COUNTS counts[1]; - int status = 0; /* 1 if anything fails */ + int i; + COUNTS counts[ 1 ]; + int status = 0; /* 1 if anything fails */ #ifdef OPT_HEADER_CACHE_EXT - hcache_init(); + hcache_init(); #endif - memset( (char *)counts, 0, sizeof( *counts ) ); + memset( (char *)counts, 0, sizeof( *counts ) ); - /* First bind all targets with LOCATE_TARGET setting. This is - needed to correctly handle dependencies to generated headers. - */ + /* First bind all targets with LOCATE_TARGET setting. This is needed to + * correctly handle dependencies to generated headers. + */ bind_explicitly_located_targets(); - { PROFILE_ENTER(MAKE_MAKE0); - for( i = 0; i < n_targets; i++ ) - { - TARGET *t = bindtarget( targets[i] ); + { + PROFILE_ENTER( MAKE_MAKE0 ); + for ( i = 0; i < n_targets; ++i ) + make0( bindtarget( targets[ i ] ), 0, 0, counts, anyhow ); + PROFILE_EXIT( MAKE_MAKE0 ); + } - make0( t, 0, 0, counts, anyhow ); - } - PROFILE_EXIT(MAKE_MAKE0); } - #ifdef OPT_GRAPH_DEBUG_EXT - if( DEBUG_GRAPH ) - { - for( i = 0; i < n_targets; i++ ) - { - TARGET *t = bindtarget( targets[i] ); - dependGraphOutput( t, 0 ); - } - } + if ( DEBUG_GRAPH ) + for ( i = 0; i < n_targets; ++i ) + dependGraphOutput( bindtarget( targets[ i ] ), 0 ); #endif - if( DEBUG_MAKE ) - { - if( counts->targets ) - printf( "...found %d target%s...\n", counts->targets, - counts->targets > 1 ? "s" : "" ); - if( counts->temp ) - printf( "...using %d temp target%s...\n", counts->temp, - counts->temp > 1 ? "s" : "" ); - if( counts->updating ) - printf( "...updating %d target%s...\n", counts->updating, - counts->updating > 1 ? "s" : "" ); - if( counts->cantfind ) - printf( "...can't find %d target%s...\n", counts->cantfind, - counts->cantfind > 1 ? "s" : "" ); - if( counts->cantmake ) - printf( "...can't make %d target%s...\n", counts->cantmake, - counts->cantmake > 1 ? "s" : "" ); - } + if ( DEBUG_MAKE ) + { + if ( counts->targets ) + printf( "...found %d target%s...\n", counts->targets, + counts->targets > 1 ? "s" : "" ); + if ( counts->temp ) + printf( "...using %d temp target%s...\n", counts->temp, + counts->temp > 1 ? "s" : "" ); + if ( counts->updating ) + printf( "...updating %d target%s...\n", counts->updating, + counts->updating > 1 ? "s" : "" ); + if ( counts->cantfind ) + printf( "...can't find %d target%s...\n", counts->cantfind, + counts->cantfind > 1 ? "s" : "" ); + if ( counts->cantmake ) + printf( "...can't make %d target%s...\n", counts->cantmake, + counts->cantmake > 1 ? "s" : "" ); + } #ifdef OPT_HEADER_CACHE_EXT - hcache_done(); + hcache_done(); #endif - status = counts->cantfind || counts->cantmake; + status = counts->cantfind || counts->cantmake; - { PROFILE_ENTER(MAKE_MAKE1); - for( i = 0; i < n_targets; i++ ) - status |= make1( bindtarget( targets[i] ) ); - PROFILE_EXIT(MAKE_MAKE1); } + { + PROFILE_ENTER( MAKE_MAKE1 ); + for ( i = 0; i < n_targets; ++i ) + status |= make1( bindtarget( targets[ i ] ) ); + PROFILE_EXIT( MAKE_MAKE1 ); + } - return status; + return status; } -/* Force any dependents of t that have already at least begun being - * visited by make0 to be updated. + +/* Force any dependants of t that have already at least begun being visited by + * make0() to be updated. */ -static void update_dependents(TARGET* t) + +static void update_dependants( TARGET * t ) { - TARGETS *q; - - for (q = t->dependents; q; q = q->next) + TARGETS * q; + + for ( q = t->dependants; q; q = q->next ) { - TARGET* p = q->target; + TARGET * p = q->target; char fate0 = p->fate; - /* If we've already at least begun visiting it and - * we're not already rebuilding it for other reasons + /* If we have already at least begun visiting it and we are not already + * rebuilding it for other reasons. */ - if (fate0 != T_FATE_INIT && fate0 < T_FATE_BUILD) + if ( ( fate0 != T_FATE_INIT ) && ( fate0 < T_FATE_BUILD ) ) { p->fate = T_FATE_UPDATE; - - if (DEBUG_FATE) + + if ( DEBUG_FATE ) { - printf( "fate change %s from %s to %s (as dependent of %s)\n", - p->name, target_fate[fate0], target_fate[p->fate], t->name); + printf( "fate change %s from %s to %s (as dependant of %s)\n", + p->name, target_fate[ (int) fate0 ], target_fate[ (int) p->fate ], t->name ); } - - /* If we're done visiting it, go back and make sure its - * dependents get rebuilt. + + /* If we are done visiting it, go back and make sure its dependants + * get rebuilt. */ - if (fate0 > T_FATE_MAKING) - update_dependents(p); + if ( fate0 > T_FATE_MAKING ) + update_dependants( p ); } } } -/* Make sure that all of t's rebuilds get rebuilt */ -static void force_rebuilds(TARGET* t) -{ - TARGETS* d; - for (d = t->rebuilds; d; d = d->next) - { - TARGET* r = d->target; - /* If it's not already being rebuilt for other reasons */ - if (r->fate < T_FATE_BUILD) - { - if (DEBUG_FATE) - printf( "fate change %s from %s to %s (by rebuild)\n", - r->name, target_fate[r->fate], target_fate[T_FATE_REBUILD]); - - /* Force rebuild it */ - r->fate = T_FATE_REBUILD; - - /* And make sure its dependents are updated too */ - update_dependents(r); - } - } -} /* - * make0() - bind and scan everything to make a TARGET - * - * Make0() recursively binds a target, searches for #included headers, - * calls itself on those headers, and calls itself on any dependents. + * Make sure that all of t's rebuilds get rebuilt. */ -void -make0( - TARGET *t, - TARGET *p, /* parent */ - int depth, /* for display purposes */ - COUNTS *counts, /* for reporting */ - int anyhow ) /* forcibly touch all (real) targets */ +static void force_rebuilds( TARGET * t ) { - TARGETS *c, *d, *incs; - TARGET *ptime = t; - time_t last, leaf, hlast; - int fate; - const char *flag = ""; - SETTINGS *s; + TARGETS * d; + for ( d = t->rebuilds; d; d = d->next ) + { + TARGET * r = d->target; + + /* If it is not already being rebuilt for other reasons. */ + if ( r->fate < T_FATE_BUILD ) + { + if ( DEBUG_FATE ) + printf( "fate change %s from %s to %s (by rebuild)\n", + r->name, target_fate[ (int) r->fate ], target_fate[ T_FATE_REBUILD ] ); + + /* Force rebuild it. */ + r->fate = T_FATE_REBUILD; + + /* And make sure its dependants are updated too. */ + update_dependants( r ); + } + } +} + + +/* + * make0() - bind and scan everything to make a TARGET. + * + * Recursively binds a target, searches for #included headers, calls itself on + * those headers and any dependencies. + */ + +void make0 +( + TARGET * t, + TARGET * p, /* parent */ + int depth, /* for display purposes */ + COUNTS * counts, /* for reporting */ + int anyhow +) /* forcibly touch all (real) targets */ +{ + TARGETS * c; + TARGET * ptime = t; + time_t last; + time_t leaf; + time_t hlast; + int fate; + char const * flag = ""; + SETTINGS * s; #ifdef OPT_GRAPH_DEBUG_EXT - int savedFate, oldTimeStamp; + int savedFate, oldTimeStamp; #endif - if( DEBUG_MAKEPROG ) - printf( "make\t--\t%s%s\n", spaces( depth ), t->name ); + if ( DEBUG_MAKEPROG ) + printf( "make\t--\t%s%s\n", spaces( depth ), t->name ); - /* - * Step 1: initialize - */ + /* + * Step 1: initialize + */ - if( DEBUG_MAKEPROG ) - printf( "make\t--\t%s%s\n", spaces( depth ), t->name ); + if ( DEBUG_MAKEPROG ) + printf( "make\t--\t%s%s\n", spaces( depth ), t->name ); - t->fate = T_FATE_MAKING; + t->fate = T_FATE_MAKING; - /* - * Step 2: under the influence of "on target" variables, - * bind the target and search for headers. - */ + /* + * Step 2: under the influence of "on target" variables, + * bind the target and search for headers. + */ - /* Step 2a: set "on target" variables. */ + /* Step 2a: set "on target" variables. */ + s = copysettings( t->settings ); + pushsettings( s ); - s = copysettings( t->settings ); - pushsettings( s ); - - /* Step 2b: find and timestamp the target file (if it's a file). */ - - if( t->binding == T_BIND_UNBOUND && !( t->flags & T_FLAG_NOTFILE ) ) - { - char* another_target; - t->boundname = search( t->name, &t->time, &another_target ); - /* If it was detected that this target refers to an already - existing and bound one, we add include dependency, so that - every target which depends on us will depend on that other - target. */ - if( another_target ) - { - TARGET* includes; - if (!t->includes) { - t->includes = copytarget(t); - t->includes->original_target = t; - } - includes = t->includes; - includes->depends = targetlist( includes->depends, - list_new( L0, another_target ) ); - } - - t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; - } - - /* INTERNAL, NOTFILE header nodes have the time of their parents */ - - if( p && t->flags & T_FLAG_INTERNAL ) - ptime = p; - - /* If temp file doesn't exist but parent does, use parent */ - if( p && t->flags & T_FLAG_TEMP && - t->binding == T_BIND_MISSING && - p->binding != T_BIND_MISSING ) + /* Step 2b: find and timestamp the target file (if it is a file). */ + if ( ( t->binding == T_BIND_UNBOUND ) && !( t->flags & T_FLAG_NOTFILE ) ) { - t->binding = T_BIND_PARENTS; - ptime = p; + char * another_target; + t->boundname = search( t->name, &t->time, &another_target, + t->flags & T_FLAG_ISFILE ); + /* If it was detected that this target refers to an already existing and + * bound one, we add an include dependency, so that every target + * depending on us will depend on that other target as well. + */ + if ( another_target ) + target_include( t, bindtarget( another_target ) ); + + t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; + } + + /* INTERNAL, NOTFILE header nodes have the time of their parents. */ + if ( p && ( t->flags & T_FLAG_INTERNAL ) ) + ptime = p; + + /* If temp file does not exist but parent does, use parent. */ + if ( p && ( t->flags & T_FLAG_TEMP ) && + ( t->binding == T_BIND_MISSING ) && + ( p->binding != T_BIND_MISSING ) ) + { + t->binding = T_BIND_PARENTS; + ptime = p; } #ifdef OPT_SEMAPHORE - { - LIST *var = var_get( "JAM_SEMAPHORE" ); - if( var ) - { - TARGET *semaphore = bindtarget( var->string ); - - semaphore->progress = T_MAKE_SEMAPHORE; - t->semaphore = semaphore; - } - } + { + LIST * var = var_get( "JAM_SEMAPHORE" ); + if ( var ) + { + TARGET * semaphore = bindtarget( var->string ); + semaphore->progress = T_MAKE_SEMAPHORE; + t->semaphore = semaphore; + } + } #endif - /* Step 2c: If its a file, search for headers. */ + /* Step 2c: If its a file, search for headers. */ + if ( t->binding == T_BIND_EXISTS ) + headers( t ); - if( t->binding == T_BIND_EXISTS ) - headers( t ); + /* Step 2d: reset "on target" variables. */ + popsettings( s ); + freesettings( s ); - /* Step 2d: reset "on target" variables */ - - popsettings( s ); - freesettings( s ); - - /* - * Pause for a little progress reporting - */ - - if( DEBUG_BIND ) - - { - if( strcmp( t->name, t->boundname ) ) - { - printf( "bind\t--\t%s%s: %s\n", - spaces( depth ), t->name, t->boundname ); - } - - switch( t->binding ) - { - case T_BIND_UNBOUND: - case T_BIND_MISSING: - case T_BIND_PARENTS: - printf( "time\t--\t%s%s: %s\n", - spaces( depth ), t->name, target_bind[ t->binding ] ); - break; - - case T_BIND_EXISTS: - printf( "time\t--\t%s%s: %s", - spaces( depth ), t->name, ctime( &t->time ) ); - break; - } - } - - /* - * Step 3: recursively make0() dependents & headers - */ - - /* Step 3a: recursively make0() dependents */ - - for( c = t->depends; c; c = c->next ) - { - int internal = t->flags & T_FLAG_INTERNAL; -/* Seems like it's not relevant for us.... - if( DEBUG_DEPENDS ) - printf( "%s \"%s\" : \"%s\" ;\n", - internal ? "Includes" : "Depends", - t->name, c->target->name ); -*/ - - /* Warn about circular deps, except for includes, */ - /* which include each other alot. */ - - if( c->target->fate == T_FATE_INIT ) - make0( c->target, ptime, depth + 1, counts, anyhow ); - else if( c->target->fate == T_FATE_MAKING && !internal ) - printf( "warning: %s depends on itself\n", c->target->name ); - } - - /* Step 3b: recursively make0() internal includes node */ - - if( t->includes ) - make0( t->includes, p, depth + 1, counts, anyhow ); - - /* Step 3c: add dependents' includes to our direct dependencies */ - - incs = 0; - - for( c = t->depends; c; c = c->next ) - if( c->target->includes ) - incs = targetentry( incs, c->target->includes ); - - t->depends = targetchain( t->depends, incs ); - - /* - * Step 4: compute time & fate - */ - - /* Step 4a: pick up dependents' time and fate */ - - - last = 0; - leaf = 0; - fate = T_FATE_STABLE; - - for( c = t->depends; c; c = c->next ) - { - /* If LEAVES has been applied, we only heed the timestamps of */ - /* the leaf source nodes. */ - - leaf = max( leaf, c->target->leaf ); - - if( t->flags & T_FLAG_LEAVES ) - { - last = leaf; - continue; - } - - last = max( last, c->target->time ); - fate = max( fate, c->target->fate ); - -#ifdef OPT_GRAPH_DEBUG_EXT - if( DEBUG_FATE ) - if( fate < c->target->fate ) - printf( "fate change %s from %s to %s by dependency %s\n", - t->name, - target_fate[fate], target_fate[c->target->fate], - c->target->name); -#endif - - } - - /* Step 4b: pick up included headers time */ - - /* - * If a header is newer than a temp source that includes it, - * the temp source will need building. - */ - - hlast = t->includes ? t->includes->time : 0; - - /* Step 4c: handle NOUPDATE oddity */ - - /* - * If a NOUPDATE file exists, make dependents eternally old. - * Don't inherit our fate from our dependents. Decide fate - * based only upon other flags and our binding (done later). - */ - - if( t->flags & T_FLAG_NOUPDATE ) - { -#ifdef OPT_GRAPH_DEBUG_EXT - if( DEBUG_FATE ) - if( fate != T_FATE_STABLE ) - printf( "fate change %s back to stable, NOUPDATE.\n", - t->name); -#endif - - last = 0; - t->time = 0; - - - /* - * Don't inherit our fate from our dependents. Decide fate - * based only upon other flags and our binding (done later). - */ - - fate = T_FATE_STABLE; - } - - /* Step 4d: determine fate: rebuild target or what? */ - - /* - In English: - If can't find or make child, can't make target. - If children changed, make target. - If target missing, make it. - If children newer, make target. - If temp's children newer than parent, make temp. - If temp's headers newer than parent, make temp. - If deliberately touched, make it. - If up-to-date temp file present, use it. - If target newer than non-notfile parent, mark target newer. - Otherwise, stable! - - Note this block runs from least to most stable: - as we make it further down the list, the target's - fate is getting stabler. - */ - -#ifdef OPT_GRAPH_DEBUG_EXT - savedFate = fate; - oldTimeStamp = 0; -#endif - - if( fate >= T_FATE_BROKEN ) - { - fate = T_FATE_CANTMAKE; - } - else if( fate >= T_FATE_SPOIL ) - { - fate = T_FATE_UPDATE; - } - else if( t->binding == T_BIND_MISSING ) - { - fate = T_FATE_MISSING; - } - else if( t->binding == T_BIND_EXISTS && last > t->time ) - { -#ifdef OPT_GRAPH_DEBUG_EXT - oldTimeStamp = 1; -#endif - fate = T_FATE_OUTDATED; - } - else if( t->binding == T_BIND_PARENTS && last > p->time ) - { -#ifdef OPT_GRAPH_DEBUG_EXT - oldTimeStamp = 1; -#endif - fate = T_FATE_NEEDTMP; - } - else if( t->binding == T_BIND_PARENTS && hlast > p->time ) - { - fate = T_FATE_NEEDTMP; - } - else if( t->flags & T_FLAG_TOUCHED ) - { - fate = T_FATE_TOUCHED; - } - else if( anyhow && !( t->flags & T_FLAG_NOUPDATE ) ) - { - fate = T_FATE_TOUCHED; - } - else if( t->binding == T_BIND_EXISTS && t->flags & T_FLAG_TEMP ) - { - fate = T_FATE_ISTMP; - } - else if( t->binding == T_BIND_EXISTS && p && - p->binding != T_BIND_UNBOUND && t->time > p->time ) - { -#ifdef OPT_GRAPH_DEBUG_EXT - oldTimeStamp = 1; -#endif - fate = T_FATE_NEWER; - } - else - { - fate = T_FATE_STABLE; - } -#ifdef OPT_GRAPH_DEBUG_EXT - if( DEBUG_FATE && fate != savedFate ) - if( savedFate == T_FATE_STABLE ) - printf( "fate change %s set to %s%s\n", - t->name, target_fate[fate], - oldTimeStamp ? " (by timestamp)" : "" ); - else - printf( "fate change %s from %s to %s%s\n", - t->name, target_fate[savedFate], target_fate[fate], - oldTimeStamp ? " (by timestamp)" : "" ); -#endif - - /* Step 4e: handle missing files */ - /* If it's missing and there are no actions to create it, boom. */ - /* If we can't make a target we don't care about, 'sokay */ - /* We could insist that there are updating actions for all missing */ - /* files, but if they have dependents we just pretend it's NOTFILE. */ - - if( fate == T_FATE_MISSING && !t->actions && !t->depends ) - { - if( t->flags & T_FLAG_NOCARE ) - { -#ifdef OPT_GRAPH_DEBUG_EXT - if( DEBUG_FATE ) - printf( "fate change %s to STABLE from %s, " - "no actions, no dependents and don't care\n", - t->name, target_fate[fate]); -#endif - fate = T_FATE_STABLE; - } - else - { - printf( "don't know how to make %s\n", t->name ); - - fate = T_FATE_CANTFIND; - } - } - - /* Step 4f: propagate dependents' time & fate. */ - /* Set leaf time to be our time only if this is a leaf. */ - - t->time = max( t->time, last ); - t->leaf = leaf ? leaf : t->time ; - /* This target's fate may have been updated by virtue of following - * some target's rebuilds list, so only allow it to be increased - * to the fate we've calculated. Otherwise, grab its new fate. + /* + * Pause for a little progress reporting . */ - if (fate > t->fate) + + if ( DEBUG_BIND ) + { + if ( strcmp( t->name, t->boundname ) ) + printf( "bind\t--\t%s%s: %s\n", + spaces( depth ), t->name, t->boundname ); + + switch ( t->binding ) + { + case T_BIND_UNBOUND: + case T_BIND_MISSING: + case T_BIND_PARENTS: + printf( "time\t--\t%s%s: %s\n", + spaces( depth ), t->name, target_bind[ (int) t->binding ] ); + break; + + case T_BIND_EXISTS: + printf( "time\t--\t%s%s: %s", + spaces( depth ), t->name, ctime( &t->time ) ); + break; + } + } + + /* + * Step 3: recursively make0() dependencies & headers. + */ + + /* Step 3a: recursively make0() dependencies. */ + for ( c = t->depends; c; c = c->next ) + { + int internal = t->flags & T_FLAG_INTERNAL; + + /* Warn about circular deps, except for includes, which include each + * other alot. + */ + if ( c->target->fate == T_FATE_INIT ) + make0( c->target, ptime, depth + 1, counts, anyhow ); + else if ( c->target->fate == T_FATE_MAKING && !internal ) + printf( "warning: %s depends on itself\n", c->target->name ); + } + + /* Step 3b: recursively make0() internal includes node. */ + if ( t->includes ) + make0( t->includes, p, depth + 1, counts, anyhow ); + + /* Step 3c: add dependencies' includes to our direct dependencies. */ + { + TARGETS * incs = 0; + for ( c = t->depends; c; c = c->next ) + if ( c->target->includes ) + incs = targetentry( incs, c->target->includes ); + t->depends = targetchain( t->depends, incs ); + } + + /* + * Step 4: compute time & fate + */ + + /* Step 4a: pick up dependencies' time and fate */ + last = 0; + leaf = 0; + fate = T_FATE_STABLE; + for ( c = t->depends; c; c = c->next ) + { + /* If LEAVES has been applied, we only heed the timestamps of the leaf + * source nodes. + */ + leaf = max( leaf, c->target->leaf ); + + if ( t->flags & T_FLAG_LEAVES ) + { + last = leaf; + continue; + } + + last = max( last, c->target->time ); + fate = max( fate, c->target->fate ); + +#ifdef OPT_GRAPH_DEBUG_EXT + if ( DEBUG_FATE ) + if ( fate < c->target->fate ) + printf( "fate change %s from %s to %s by dependency %s\n", + t->name, target_fate[(int) fate], target_fate[(int) c->target->fate], + c->target->name ); +#endif + } + + /* Step 4b: pick up included headers time */ + + /* + * If a header is newer than a temp source that includes it, + * the temp source will need building. + */ + + hlast = t->includes ? t->includes->time : 0; + + /* Step 4c: handle NOUPDATE oddity. + * + * If a NOUPDATE file exists, mark it as having eternally old dependencies. + * Do not inherit our fate from our dependencies. Decide fate based only on + * other flags and our binding (done later). + */ + if ( t->flags & T_FLAG_NOUPDATE ) + { +#ifdef OPT_GRAPH_DEBUG_EXT + if ( DEBUG_FATE ) + if ( fate != T_FATE_STABLE ) + printf( "fate change %s back to stable, NOUPDATE.\n", t->name + ); +#endif + + last = 0; + t->time = 0; + + /* Do not inherit our fate from our dependencies. Decide fate based only + * upon other flags and our binding (done later). + */ + fate = T_FATE_STABLE; + } + + /* Step 4d: determine fate: rebuild target or what? */ + + /* + In English: + If can not find or make child, can not make target. + If children changed, make target. + If target missing, make it. + If children newer, make target. + If temp's children newer than parent, make temp. + If temp's headers newer than parent, make temp. + If deliberately touched, make it. + If up-to-date temp file present, use it. + If target newer than non-notfile parent, mark target newer. + Otherwise, stable! + + Note this block runs from least to most stable: + as we make it further down the list, the target's + fate is getting stabler. + */ + +#ifdef OPT_GRAPH_DEBUG_EXT + savedFate = fate; + oldTimeStamp = 0; +#endif + + if ( fate >= T_FATE_BROKEN ) + { + fate = T_FATE_CANTMAKE; + } + else if ( fate >= T_FATE_SPOIL ) + { + fate = T_FATE_UPDATE; + } + else if ( t->binding == T_BIND_MISSING ) + { + fate = T_FATE_MISSING; + } + else if ( ( t->binding == T_BIND_EXISTS ) && ( last > t->time ) ) + { +#ifdef OPT_GRAPH_DEBUG_EXT + oldTimeStamp = 1; +#endif + fate = T_FATE_OUTDATED; + } + else if ( ( t->binding == T_BIND_PARENTS ) && ( last > p->time ) ) + { +#ifdef OPT_GRAPH_DEBUG_EXT + oldTimeStamp = 1; +#endif + fate = T_FATE_NEEDTMP; + } + else if ( ( t->binding == T_BIND_PARENTS ) && ( hlast > p->time ) ) + { + fate = T_FATE_NEEDTMP; + } + else if ( t->flags & T_FLAG_TOUCHED ) + { + fate = T_FATE_TOUCHED; + } + else if ( anyhow && !( t->flags & T_FLAG_NOUPDATE ) ) + { + fate = T_FATE_TOUCHED; + } + else if ( ( t->binding == T_BIND_EXISTS ) && ( t->flags & T_FLAG_TEMP ) ) + { + fate = T_FATE_ISTMP; + } + else if ( ( t->binding == T_BIND_EXISTS ) && p && + ( p->binding != T_BIND_UNBOUND ) && ( t->time > p->time ) ) + { +#ifdef OPT_GRAPH_DEBUG_EXT + oldTimeStamp = 1; +#endif + fate = T_FATE_NEWER; + } + else + { + fate = T_FATE_STABLE; + } +#ifdef OPT_GRAPH_DEBUG_EXT + if ( DEBUG_FATE && ( fate != savedFate ) ) + { + if ( savedFate == T_FATE_STABLE ) + printf( "fate change %s set to %s%s\n", t->name, + target_fate[ fate ], oldTimeStamp ? " (by timestamp)" : "" ); + else + printf( "fate change %s from %s to %s%s\n", t->name, + target_fate[ savedFate ], target_fate[ fate ], + oldTimeStamp ? " (by timestamp)" : "" ); + } +#endif + + /* Step 4e: handle missing files */ + /* If it is missing and there are no actions to create it, boom. */ + /* If we can not make a target we do not care about it, okay. */ + /* We could insist that there are updating actions for all missing */ + /* files, but if they have dependencies we just pretend it is a NOTFILE. */ + + if ( ( fate == T_FATE_MISSING ) && !t->actions && !t->depends ) + { + if ( t->flags & T_FLAG_NOCARE ) + { +#ifdef OPT_GRAPH_DEBUG_EXT + if ( DEBUG_FATE ) + printf( "fate change %s to STABLE from %s, " + "no actions, no dependencies and do not care\n", + t->name, target_fate[ fate ] ); +#endif + fate = T_FATE_STABLE; + } + else + { + printf( "don't know how to make %s\n", t->name ); + fate = T_FATE_CANTFIND; + } + } + + /* Step 4f: propagate dependencies' time & fate. */ + /* Set leaf time to be our time only if this is a leaf. */ + + t->time = max( t->time, last ); + t->leaf = leaf ? leaf : t->time ; + /* This target's fate may have been updated by virtue of following some + * target's rebuilds list, so only allow it to be increased to the fate we + * have calculated. Otherwise, grab its new fate. + */ + if ( fate > t->fate ) t->fate = fate; else fate = t->fate; - /* Step 4g: if this target needs to be built, force rebuild - * everything in this target's rebuilds list */ - if (fate >= T_FATE_BUILD && fate < T_FATE_BROKEN) - force_rebuilds(t); - /* - * Step 5: sort dependents by their update time. - */ + /* Step 4g: if this target needs to be built, force rebuild everything in + * this target's rebuilds list. + */ + if ( ( fate >= T_FATE_BUILD ) && ( fate < T_FATE_BROKEN ) ) + force_rebuilds( t ); - if( globs.newestfirst ) - t->depends = make0sort( t->depends ); + /* + * Step 5: sort dependencies by their update time. + */ - /* - * Step 6: a little harmless tabulating for tracing purposes - */ + if ( globs.newestfirst ) + t->depends = make0sort( t->depends ); - /* Don't count or report interal includes nodes. */ + /* + * Step 6: a little harmless tabulating for tracing purposes + */ - if( t->flags & T_FLAG_INTERNAL ) - return; + /* Do not count or report interal includes nodes. */ + if ( t->flags & T_FLAG_INTERNAL ) + return; - if (counts) { + if ( counts ) + { #ifdef OPT_IMPROVED_PATIENCE_EXT ++counts->targets; -#else - if( !( ++counts->targets % 1000 ) && DEBUG_MAKE ) +#else + if ( !( ++counts->targets % 1000 ) && DEBUG_MAKE ) printf( "...patience...\n" ); #endif - if( fate == T_FATE_ISTMP ) - counts->temp++; - else if( fate == T_FATE_CANTFIND ) - counts->cantfind++; - else if( fate == T_FATE_CANTMAKE && t->actions ) - counts->cantmake++; - else if( fate >= T_FATE_BUILD && fate < T_FATE_BROKEN && t->actions ) - counts->updating++; + if ( fate == T_FATE_ISTMP ) + ++counts->temp; + else if ( fate == T_FATE_CANTFIND ) + ++counts->cantfind; + else if ( ( fate == T_FATE_CANTMAKE ) && t->actions ) + ++counts->cantmake; + else if ( ( fate >= T_FATE_BUILD ) && ( fate < T_FATE_BROKEN ) && + t->actions ) + ++counts->updating; } - if( !( t->flags & T_FLAG_NOTFILE ) && fate >= T_FATE_SPOIL ) - flag = "+"; - else if( t->binding == T_BIND_EXISTS && p && t->time > p->time ) - flag = "*"; + if ( !( t->flags & T_FLAG_NOTFILE ) && ( fate >= T_FATE_SPOIL ) ) + flag = "+"; + else if ( ( t->binding == T_BIND_EXISTS ) && p && ( t->time > p->time ) ) + flag = "*"; - if( DEBUG_MAKEPROG ) - printf( "made%s\t%s\t%s%s\n", - flag, target_fate[ t->fate ], - spaces( depth ), t->name ); - -/* We don't have DEBUG_CAUSES. - if( DEBUG_CAUSES && - t->fate >= T_FATE_NEWER && - t->fate <= T_FATE_MISSING ) - printf( "%s %s\n", target_fate[ t->fate ], t->name ); -*/ + if ( DEBUG_MAKEPROG ) + printf( "made%s\t%s\t%s%s\n", flag, target_fate[ (int) t->fate ], + spaces( depth ), t->name ); } + #ifdef OPT_GRAPH_DEBUG_EXT -static const char* target_name( TARGET* t ) +static const char * target_name( TARGET * t ) { - static char buf[1000]; - if (t->flags & T_FLAG_INTERNAL) { - sprintf(buf, "%s (internal node)", t->name); + static char buf[ 1000 ]; + if ( t->flags & T_FLAG_INTERNAL ) + { + sprintf( buf, "%s (internal node)", t->name ); return buf; - } else { - return t->name; } + return t->name; } + /* - * dependGraphOutput() - output the DG after make0 has run + * dependGraphOutput() - output the DG after make0 has run. */ -static void -dependGraphOutput( TARGET *t, int depth ) +static void dependGraphOutput( TARGET * t, int depth ) { - TARGETS *c; + TARGETS * c; - if ( (t->flags & T_FLAG_VISITED) != 0 - || !t->name - || !t->boundname) - return; + if ( ( t->flags & T_FLAG_VISITED ) || !t->name || !t->boundname ) + return; t->flags |= T_FLAG_VISITED; - switch (t->fate) + switch ( t->fate ) { - case T_FATE_TOUCHED: - case T_FATE_MISSING: - case T_FATE_OUTDATED: - case T_FATE_UPDATE: - printf( "->%s%2d Name: %s\n", spaces(depth), depth, target_name(t) ); - break; - default: - printf( " %s%2d Name: %s\n", spaces(depth), depth, target_name(t) ); - break; + case T_FATE_TOUCHED: + case T_FATE_MISSING: + case T_FATE_OUTDATED: + case T_FATE_UPDATE: + printf( "->%s%2d Name: %s\n", spaces( depth ), depth, target_name( t ) ); + break; + default: + printf( " %s%2d Name: %s\n", spaces( depth ), depth, target_name( t ) ); + break; } - if( strcmp (t->name, t->boundname) ) + if ( strcmp( t->name, t->boundname ) ) + printf( " %s Loc: %s\n", spaces( depth ), t->boundname ); + + switch ( t->fate ) { - printf( " %s Loc: %s\n", spaces(depth), t->boundname ); + case T_FATE_STABLE: + printf( " %s : Stable\n", spaces( depth ) ); + break; + case T_FATE_NEWER: + printf( " %s : Newer\n", spaces( depth ) ); + break; + case T_FATE_ISTMP: + printf( " %s : Up to date temp file\n", spaces( depth ) ); + break; + case T_FATE_NEEDTMP: + printf( " %s : Temporary file, to be updated\n", spaces( depth ) ); + break; + case T_FATE_TOUCHED: + printf( " %s : Been touched, updating it\n", spaces( depth ) ); + break; + case T_FATE_MISSING: + printf( " %s : Missing, creating it\n", spaces( depth ) ); + break; + case T_FATE_OUTDATED: + printf( " %s : Outdated, updating it\n", spaces( depth ) ); + break; + case T_FATE_REBUILD: + printf( " %s : Rebuild, updating it\n", spaces( depth ) ); + break; + case T_FATE_UPDATE: + printf( " %s : Updating it\n", spaces( depth ) ); + break; + case T_FATE_CANTFIND: + printf( " %s : Can not find it\n", spaces( depth ) ); + break; + case T_FATE_CANTMAKE: + printf( " %s : Can make it\n", spaces( depth ) ); + break; } - switch( t->fate ) + if ( t->flags & ~T_FLAG_VISITED ) { - case T_FATE_STABLE: - printf( " %s : Stable\n", spaces(depth) ); - break; - case T_FATE_NEWER: - printf( " %s : Newer\n", spaces(depth) ); - break; - case T_FATE_ISTMP: - printf( " %s : Up to date temp file\n", spaces(depth) ); - case T_FATE_NEEDTMP: - printf( " %s : Temporary file, to be updated\n", spaces(depth) ); - break; - case T_FATE_TOUCHED: - printf( " %s : Been touched, updating it\n", spaces(depth) ); - break; - case T_FATE_MISSING: - printf( " %s : Missing, creating it\n", spaces(depth) ); - break; - case T_FATE_OUTDATED: - printf( " %s : Outdated, updating it\n", spaces(depth) ); - break; - case T_FATE_REBUILD: - printf( " %s : Rebuild, Updating it\n", spaces(depth) ); - break; - case T_FATE_UPDATE: - printf( " %s : Updating it\n", spaces(depth) ); - break; - case T_FATE_CANTFIND: - printf( " %s : Can't find it\n", spaces(depth) ); - break; - case T_FATE_CANTMAKE: - printf( " %s : Can't make it\n", spaces(depth) ); - break; + printf( " %s : ", spaces( depth ) ); + if ( t->flags & T_FLAG_TEMP ) printf( "TEMPORARY " ); + if ( t->flags & T_FLAG_NOCARE ) printf( "NOCARE " ); + if ( t->flags & T_FLAG_NOTFILE ) printf( "NOTFILE " ); + if ( t->flags & T_FLAG_TOUCHED ) printf( "TOUCHED " ); + if ( t->flags & T_FLAG_LEAVES ) printf( "LEAVES " ); + if ( t->flags & T_FLAG_NOUPDATE ) printf( "NOUPDATE " ); + printf( "\n" ); } - if( t->flags & ~T_FLAG_VISITED ) + for ( c = t->depends; c; c = c->next ) { - printf( " %s : ", spaces(depth) ); - if( t->flags & T_FLAG_TEMP ) printf ("TEMPORARY "); - if( t->flags & T_FLAG_NOCARE ) printf ("NOCARE "); - if( t->flags & T_FLAG_NOTFILE ) printf ("NOTFILE "); - if( t->flags & T_FLAG_TOUCHED ) printf ("TOUCHED "); - if( t->flags & T_FLAG_LEAVES ) printf ("LEAVES "); - if( t->flags & T_FLAG_NOUPDATE ) printf ("NOUPDATE "); - printf( "\n" ); + printf( " %s : Depends on %s (%s)", spaces( depth ), + target_name( c->target ), target_fate[ (int) c->target->fate ] ); + if ( c->target->time == t->time ) + printf( " (max time)"); + printf( "\n" ); } - for( c = t->depends; c; c = c->next ) - { - printf( " %s : Depends on %s (%s)", spaces(depth), - target_name(c->target), target_fate[ c->target->fate ] ); - if (c->target->time == t->time) - printf( " (max time)"); - printf("\n"); - - } - - - for( c = t->depends; c; c = c->next ) - { - - dependGraphOutput( c->target, depth + 1 ); - } + for ( c = t->depends; c; c = c->next ) + dependGraphOutput( c->target, depth + 1 ); } - #endif + + /* - * make0sort() - reorder TARGETS chain by their time (newest to oldest) + * make0sort() - reorder TARGETS chain by their time (newest to oldest). + * + * We walk chain, taking each item and inserting it on the sorted result, with + * newest items at the front. This involves updating each of the TARGETS' + * c->next and c->tail. Note that we make c->tail a valid prev pointer for every + * entry. Normally, it is only valid at the head, where prev == tail. Note also + * that while tail is a loop, next ends at the end of the chain. */ -static TARGETS * -make0sort( TARGETS *chain ) +static TARGETS * make0sort( TARGETS * chain ) { - PROFILE_ENTER(MAKE_MAKE0SORT); - TARGETS *result = 0; + PROFILE_ENTER( MAKE_MAKE0SORT ); - /* We walk chain, taking each item and inserting it on the */ - /* sorted result, with newest items at the front. This involves */ - /* updating each TARGETS' c->next and c->tail. Note that we */ - /* make c->tail a valid prev pointer for every entry. Normally, */ - /* it is only valid at the head, where prev == tail. Note also */ - /* that while tail is a loop, next ends at the end of the chain. */ + TARGETS * result = 0; - /* Walk current target list */ + /* Walk the current target list. */ + while ( chain ) + { + TARGETS * c = chain; + TARGETS * s = result; - while( chain ) - { - TARGETS *c = chain; - TARGETS *s = result; + chain = chain->next; - chain = chain->next; + /* Find point s in result for c. */ + while ( s && ( s->target->time > c->target->time ) ) + s = s->next; - /* Find point s in result for c */ + /* Insert c in front of s (might be 0). Do not even think of deciphering + * this. + */ + c->next = s; /* good even if s = 0 */ + if ( result == s ) result = c; /* new head of chain? */ + if ( !s ) s = result; /* wrap to ensure a next */ + if ( result != c ) s->tail->next = c; /* not head? be prev's next */ + c->tail = s->tail; /* take on next's prev */ + s->tail = c; /* make next's prev us */ + } - while( s && s->target->time > c->target->time ) - s = s->next; - - /* Insert c in front of s (might be 0). */ - /* Don't even think of deciphering this. */ - - c->next = s; /* good even if s = 0 */ - if( result == s ) result = c; /* new head of chain? */ - if( !s ) s = result; /* wrap to ensure a next */ - if( result != c ) s->tail->next = c; /* not head? be prev's next */ - c->tail = s->tail; /* take on next's prev */ - s->tail = c; /* make next's prev us */ - } - - PROFILE_EXIT(MAKE_MAKE0SORT); - return result; + PROFILE_EXIT( MAKE_MAKE0SORT ); + return result; } -static LIST *targets_to_update_ = 0; -void mark_target_for_updating(char *target) +static LIST * targets_to_update_ = 0; + + +void mark_target_for_updating( char * target ) { targets_to_update_ = list_new( targets_to_update_, target ); } -LIST *targets_to_update() + +LIST * targets_to_update() { return targets_to_update_; } + void clear_targets_to_update() { - list_free(targets_to_update_); + list_free( targets_to_update_ ); targets_to_update_ = 0; } diff --git a/src/engine/make.h b/src/engine/make.h index 2627446ad..b372263e1 100644 --- a/src/engine/make.h +++ b/src/engine/make.h @@ -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(); diff --git a/src/engine/make1.c b/src/engine/make1.c index 485a41caf..26ee5c41e 100644 --- a/src/engine/make1.c +++ b/src/engine/make1.c @@ -13,406 +13,412 @@ /* * make1.c - execute command to bring targets up to date * - * This module contains make1(), the entry point called by make() to + * This module contains make1(), the entry point called by make() to * recursively decend the dependency graph executing update actions as * marked by make0(). * * External routines: * - * make1() - execute commands to update a TARGET and all its dependents + * make1() - execute commands to update a TARGET and all of its dependencies. * * Internal routines, the recursive/asynchronous command executors: * - * make1a() - recursively traverse target tree, calling make1b() - * make1b() - dependents of target built, now build target with make1c() - * make1c() - launch target's next command, call make1b() when done - * make1d() - handle command execution completion and call back make1c() + * make1a() - recursively traverse dependency target tree, calling make1b(). + * make1atail() - started processing all dependencies so go on to make1b(). + * make1b() - when dependencies are up to date, build target with make1c(). + * make1c() - launch target's next command, call parents' make1b() if none. + * make1d() - handle command execution completion and call back make1c(). * * Internal support routines: * - * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc - * make1list() - turn a list of targets into a LIST, for $(<) and $(>) - * make1settings() - for vars that get bound values, build up replacement lists - * make1bind() - bind targets that weren't bound in dependency analysis + * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc. + * make1list() - turn a list of targets into a LIST, for $(<) and $(>). + * make1settings() - for vars that get bound values, build up replacement lists. + * make1bind() - bind targets that weren't bound in dependency analysis. * * 04/16/94 (seiwald) - Split from make.c. * 04/21/94 (seiwald) - Handle empty "updated" actions. - * 05/04/94 (seiwald) - async multiprocess (-j) support - * 06/01/94 (seiwald) - new 'actions existing' does existing sources + * 05/04/94 (seiwald) - async multiprocess (-j) support. + * 06/01/94 (seiwald) - new 'actions existing' does existing sources. * 12/20/94 (seiwald) - NOTIME renamed NOTFILE. * 01/19/95 (seiwald) - distinguish between CANTFIND/CANTMAKE targets. - * 01/22/94 (seiwald) - pass per-target JAMSHELL down to execcmd(). + * 01/22/94 (seiwald) - pass per-target JAMSHELL down to exec_cmd(). * 02/28/95 (seiwald) - Handle empty "existing" actions. * 03/10/95 (seiwald) - Fancy counts. */ -# include "jam.h" +#include "jam.h" -# include "lists.h" -# include "parse.h" -# include "assert.h" -# include "variable.h" -# include "rules.h" -# include "headers.h" +#include "lists.h" +#include "parse.h" +#include "assert.h" +#include "variable.h" +#include "rules.h" +#include "headers.h" -# include "search.h" -# include "newstr.h" -# include "make.h" -# include "command.h" -# include "execcmd.h" -# include "compile.h" -# include "output.h" +#include "search.h" +#include "newstr.h" +#include "make.h" +#include "command.h" +#include "execcmd.h" +#include "compile.h" +#include "output.h" -# include +#include -#if defined(sun) || defined(__sun) -#include /* for unlink */ +#if ! defined(NT) || defined(__GNUC__) + #include /* for unlink */ #endif -static CMD *make1cmds( TARGET *t ); -static LIST *make1list( LIST *l, TARGETS *targets, int flags ); -static SETTINGS *make1settings( LIST *vars ); -static void make1bind( TARGET *t ); +static CMD * make1cmds ( TARGET * ); +static LIST * make1list ( LIST *, TARGETS *, int flags ); +static SETTINGS * make1settings( LIST * vars ); +static void make1bind ( TARGET * ); -/* Ugly static - it's too hard to carry it through the callbacks. */ +/* Ugly static - it is too hard to carry it through the callbacks. */ -static struct { - int failed; - int skipped; - int total; - int made; -} counts[1] ; +static struct +{ + int failed; + int skipped; + int total; + int made; +} counts[ 1 ] ; -/* - * Target state - remove recursive calls by just keeping track of state target is in +/* Target state - remove recursive calls by just keeping track of state target + * is in. */ typedef struct _state { - struct _state *prev; /* previous state on stack */ - TARGET *t; /* current target */ - TARGET *parent; /* parent argument necessary for make1a() */ -#define T_STATE_MAKE1A 0 /* make1a() should be called */ -#define T_STATE_MAKE1ATAIL 1 /* make1atail() should be called */ -#define T_STATE_MAKE1B 2 /* make1b() should be called */ -#define T_STATE_MAKE1C 3 /* make1c() should be called */ -#define T_STATE_MAKE1D 4 /* make1d() should be called */ - int curstate; /* current state */ - int status; + struct _state * prev; /* previous state on stack */ + TARGET * t; /* current target */ + TARGET * parent; /* parent argument necessary for make1a() */ +#define T_STATE_MAKE1A 0 /* make1a() should be called */ +#define T_STATE_MAKE1ATAIL 1 /* make1atail() should be called */ +#define T_STATE_MAKE1B 2 /* make1b() should be called */ +#define T_STATE_MAKE1C 3 /* make1c() should be called */ +#define T_STATE_MAKE1D 4 /* make1d() should be called */ + int curstate; /* current state */ + int status; } state; -static void make1a( state *pState); -static void make1atail(state *pState); -static void make1b( state *pState ); -static void make1c( state *pState ); -static void make1d( state *pState ); -static void make_closure(void *closure, int status, timing_info*, char *, char *); +static void make1a ( state * ); +static void make1atail ( state * ); +static void make1b ( state * ); +static void make1c ( state * ); +static void make1d ( state * ); +static void make_closure( void * closure, int status, timing_info *, char *, char * ); typedef struct _stack { - state *stack; + state * stack; } stack; static stack state_stack = { NULL }; -static state *state_freelist = NULL; +static state * state_freelist = NULL; -static state *alloc_state() + +static state * alloc_state() { - if(state_freelist != NULL) - { - state *pState; + if ( state_freelist != NULL ) + { + state * pState = state_freelist; + state_freelist = pState->prev; + memset( pState, 0, sizeof( state ) ); + return pState; + } - pState = state_freelist; - state_freelist = pState->prev; - memset(pState, 0, sizeof(state)); - return pState; - } - else - { - return (state *)BJAM_MALLOC(sizeof(state)); - } + return (state *)BJAM_MALLOC( sizeof( state ) ); } -static void free_state(state *pState) + +static void free_state( state * pState ) { - pState->prev = state_freelist; - state_freelist = pState; + pState->prev = state_freelist; + state_freelist = pState; } + static void clear_state_freelist() { - while(state_freelist != NULL) - { - state *pState = state_freelist; - state_freelist = state_freelist->prev; - BJAM_FREE(pState); - } + while ( state_freelist != NULL ) + { + state * pState = state_freelist; + state_freelist = state_freelist->prev; + BJAM_FREE( pState ); + } } -static state *current_state(stack *pStack) + +static state * current_state( stack * pStack ) { - return pStack->stack; + return pStack->stack; } -static void pop_state(stack *pStack) + +static void pop_state( stack * pStack ) { - state *pState; - - if(pStack->stack != NULL) - { - pState = pStack->stack->prev; - free_state(pStack->stack); - pStack->stack = pState; - } + if ( pStack->stack != NULL ) + { + state * pState = pStack->stack->prev; + free_state( pStack->stack ); + pStack->stack = pState; + } } -static state *push_state(stack *pStack, TARGET *t, TARGET *parent, int curstate) + +static state * push_state( stack * pStack, TARGET * t, TARGET * parent, int curstate ) { - state *pState; + state * pState = alloc_state(); - pState = alloc_state(); + pState->t = t; + pState->parent = parent; + pState->prev = pStack->stack; + pState->curstate = curstate; - pState->t = t; - pState->parent = parent; - pState->prev = pStack->stack; - pState->curstate = curstate; + pStack->stack = pState; - pStack->stack = pState; - - return pStack->stack; + return pStack->stack; } -/* pushes a stack onto another stack, effectively reversing the order */ -static void push_stack_on_stack(stack *pDest, stack *pSrc) -{ - while(pSrc->stack != NULL) - { - state *pState; - - pState = pSrc->stack; - pSrc->stack = pSrc->stack->prev; - pState->prev = pDest->stack; - pDest->stack = pState; - } -} /* - * make1() - execute commands to update a TARGET and all its dependents + * Pushes a stack onto another stack, effectively reversing the order. + */ + +static void push_stack_on_stack( stack * pDest, stack * pSrc ) +{ + while ( pSrc->stack != NULL ) + { + state * pState = pSrc->stack; + pSrc->stack = pSrc->stack->prev; + pState->prev = pDest->stack; + pDest->stack = pState; + } +} + + +/* + * make1() - execute commands to update a TARGET and all of its dependencies. */ static int intr = 0; -int -make1( TARGET *t ) +int make1( TARGET * t ) { - state *pState; + state * pState; - memset( (char *)counts, 0, sizeof( *counts ) ); + memset( (char *)counts, 0, sizeof( *counts ) ); - /* Recursively make the target and its dependents */ - push_state(&state_stack, t, NULL, T_STATE_MAKE1A); + /* Recursively make the target and its dependencies. */ + push_state( &state_stack, t, NULL, T_STATE_MAKE1A ); - do - { - while((pState = current_state(&state_stack)) != NULL) - { - if (intr) - pop_state(&state_stack); + do + { + while ( ( pState = current_state( &state_stack ) ) != NULL ) + { + if ( intr ) + pop_state( &state_stack ); - switch(pState->curstate) - { - case T_STATE_MAKE1A: - make1a(pState); - break; - case T_STATE_MAKE1ATAIL: - make1atail(pState); - break; - case T_STATE_MAKE1B: - make1b(pState); - break; - case T_STATE_MAKE1C: - make1c(pState); - break; - case T_STATE_MAKE1D: - make1d(pState); - break; - default: - break; - } - } - - - /* Wait for any outstanding commands to finish running. */ - } while( execwait() ); - - clear_state_freelist(); - - /* Talk about it */ - if( counts->failed ) - printf( "...failed updating %d target%s...\n", counts->failed, - counts->failed > 1 ? "s" : "" ); - - if( DEBUG_MAKE && counts->skipped ) - printf( "...skipped %d target%s...\n", counts->skipped, - counts->skipped > 1 ? "s" : "" ); - - if( DEBUG_MAKE && counts->made ) - printf( "...updated %d target%s...\n", counts->made, - counts->made > 1 ? "s" : "" ); - - return counts->total != counts->made; -} - -/* - * make1a() - recursively traverse target tree, calling make1b() - */ - -static void -make1a( state *pState) -{ - TARGET* t = pState->t; - TARGETS *c; - TARGETS *inc; - - /* If the parent is the first to try to build this target */ - /* or this target is in the make1c() quagmire, arrange for the */ - /* parent to be notified when this target is built. */ - - if( pState->parent ) - switch( pState->t->progress ) - { - case T_MAKE_INIT: - case T_MAKE_ACTIVE: - case T_MAKE_RUNNING: - pState->t->parents = targetentry( pState->t->parents, pState->parent ); - pState->parent->asynccnt++; - } - - if( pState->t->progress != T_MAKE_INIT ) - { - pop_state(&state_stack); - return; - } - - /* Asynccnt counts the dependents preventing this target from */ - /* proceeding to make1b() for actual building. We start off with */ - /* a count of 1 to prevent anything from happening until we can */ - /* call all dependents. This 1 is accounted for when we call */ - /* make1b() ourselves, below. */ - - pState->t->asynccnt = 1; - - /* Add header node that was created during building process. */ - - inc = 0; - for (c = t->depends; c; c = c->next) { - if (c->target->rescanned && c->target->includes) - inc = targetentry(inc, c->target->includes); + switch ( pState->curstate ) + { + case T_STATE_MAKE1A : make1a ( pState ); break; + case T_STATE_MAKE1ATAIL: make1atail( pState ); break; + case T_STATE_MAKE1B : make1b ( pState ); break; + case T_STATE_MAKE1C : make1c ( pState ); break; + case T_STATE_MAKE1D : make1d ( pState ); break; + } + } } - t->depends = targetchain(t->depends, inc); + /* Wait for any outstanding commands to finish running. */ + while ( exec_wait() ); - /* against circular dependency. */ + clear_state_freelist(); - pState->t->progress = T_MAKE_ONSTACK; + /* Talk about it. */ + if ( counts->failed ) + printf( "...failed updating %d target%s...\n", counts->failed, + counts->failed > 1 ? "s" : "" ); + if ( DEBUG_MAKE && counts->skipped ) + printf( "...skipped %d target%s...\n", counts->skipped, + counts->skipped > 1 ? "s" : "" ); + if ( DEBUG_MAKE && counts->made ) + printf( "...updated %d target%s...\n", counts->made, + counts->made > 1 ? "s" : "" ); - { - stack temp_stack = { NULL }; - for( c = t->depends; c && !intr; c = c->next ) - push_state(&temp_stack, c->target, pState->t, T_STATE_MAKE1A); - - /* using stacks reverses the order of execution. Reverse it back */ - push_stack_on_stack(&state_stack, &temp_stack); - } - - pState->curstate = T_STATE_MAKE1ATAIL; + return counts->total != counts->made; } -static void make1atail(state *pState) -{ - pState->t->progress = T_MAKE_ACTIVE; - - /* Now that all dependents have bumped asynccnt, we now allow */ - /* decrement our reference to asynccnt. */ - pState->curstate = T_STATE_MAKE1B; -} /* - * make1b() - dependents of target built, now build target with make1c() + * make1a() - recursively traverse target tree, calling make1b(). + * + * Called to start processing a specified target. Does nothing if the target is + * already being processed or otherwise starts processing all of its + * dependencies. Once all of its dependencies have started being processed goes + * on and calls make1b() (actually does that indirectly via a helper + * make1atail() state). */ -static void -make1b( state *pState ) +static void make1a( state * pState ) { - TARGET *t = pState->t; - TARGETS *c; - TARGET *failed = 0; - char* failed_name = "dependencies"; + TARGET * t = pState->t; + TARGETS * c; - /* If any dependents are still outstanding, wait until they */ - /* call make1b() to signal their completion. */ + /* If the parent is the first to try to build this target or this target is + * in the make1c() quagmire, arrange for the parent to be notified when this + * target is built. + */ + if ( pState->parent ) + switch ( pState->t->progress ) + { + case T_MAKE_INIT: + case T_MAKE_ACTIVE: + case T_MAKE_RUNNING: + pState->t->parents = targetentry( pState->t->parents, + pState->parent ); + ++pState->parent->asynccnt; + } - if( --(pState->t->asynccnt) ) - { - pop_state(&state_stack); - return; - } - - /* Try to aquire a semaphore. If it's locked, wait until the target - that locked it is build and signals completition. */ + /* If this target is already being processed then do nothing. There is no + * need to start processing the same target all over again. + */ + if ( pState->t->progress != T_MAKE_INIT ) + { + pop_state( &state_stack ); + return; + } + + /* Asynccnt counts the dependencies preventing this target from proceeding + * to make1b() for actual building. We start off with a count of 1 to + * prevent anything from happening until we can notify all dependencies that + * they are needed. This 1 is accounted for when we call make1b() ourselves, + * below. Without this if a a dependency gets built before we finish + * processing all of our other dependencies our build might be triggerred + * prematurely. + */ + pState->t->asynccnt = 1; + + /* Add header nodes created during the building process. */ + { + TARGETS * inc = 0; + for ( c = t->depends; c; c = c->next ) + if ( c->target->rescanned && c->target->includes ) + inc = targetentry( inc, c->target->includes ); + t->depends = targetchain( t->depends, inc ); + } + + /* Guard against circular dependencies. */ + pState->t->progress = T_MAKE_ONSTACK; + + { + stack temp_stack = { NULL }; + for ( c = t->depends; c && !intr; c = c->next ) + push_state( &temp_stack, c->target, pState->t, T_STATE_MAKE1A ); + + /* Using stacks reverses the order of execution. Reverse it back. */ + push_stack_on_stack( &state_stack, &temp_stack ); + } + + pState->curstate = T_STATE_MAKE1ATAIL; +} + + +/* + * make1atail() - started processing all dependencies so go on to make1b(). + */ + +static void make1atail( state * pState ) +{ + pState->t->progress = T_MAKE_ACTIVE; + /* Now that all of our dependencies have bumped up our asynccnt we can + * remove our own internal bump added to prevent this target from being + * built before all of its dependencies start getting processed. + */ + pState->curstate = T_STATE_MAKE1B; +} + + +/* + * make1b() - when dependencies are up to date, build target with make1c(). + * + * Called after all dependencies have started being processed and after each of + * them finishes its processing. The target actually goes on to getting built in + * make1c() only after all of its dependencies have finished their processing. + */ + +static void make1b( state * pState ) +{ + TARGET * t = pState->t; + TARGETS * c; + TARGET * failed = 0; + char * failed_name = "dependencies"; + + /* If any dependencies are still outstanding, wait until they call make1b() + * to signal their completion. + */ + if ( --pState->t->asynccnt ) + { + pop_state( &state_stack ); + return; + } + + /* Try to aquire a semaphore. If it is locked, wait until the target that + * locked it is built and signal completition. + */ #ifdef OPT_SEMAPHORE - if( t->semaphore && t->semaphore->asynccnt ) - { + if ( t->semaphore && t->semaphore->asynccnt ) + { /* Append 't' to the list of targets waiting on semaphore. */ - t->semaphore->parents = targetentry( t->semaphore->parents, t ); - t->asynccnt++; + t->semaphore->parents = targetentry( t->semaphore->parents, t ); + t->asynccnt++; - if( DEBUG_EXECCMD ) - printf( "SEM: %s is busy, delaying launch of %s\n", - t->semaphore->name, t->name); - pop_state(&state_stack); - return; - } + if ( DEBUG_EXECCMD ) + printf( "SEM: %s is busy, delaying launch of %s\n", + t->semaphore->name, t->name ); + pop_state( &state_stack ); + return; + } #endif + /* Now ready to build target 't', if dependencies built OK. */ - /* Now ready to build target 't'... if dependents built ok. */ - - /* Collect status from dependents */ - - - for( c = t->depends; c; c = c->next ) - if( c->target->status > t->status && !( c->target->flags & T_FLAG_NOCARE )) + /* Collect status from dependencies. */ + for ( c = t->depends; c; c = c->next ) + if ( c->target->status > t->status && !( c->target->flags & T_FLAG_NOCARE ) ) { failed = c->target; pState->t->status = c->target->status; } - /* If a internal header node failed to build, we'd want to output the - target that it failed on. */ - if (failed && (failed->flags & T_FLAG_INTERNAL)) { - failed_name = failed->failed; - } else if (failed) { - failed_name = failed->name; + /* If an internal header node failed to build, we want to output the target + * that it failed on. + */ + if ( failed ) + { + failed_name = failed->flags & T_FLAG_INTERNAL + ? failed->failed + : failed->name; } t->failed = failed_name; - /* If actions on deps have failed, bail. */ - /* Otherwise, execute all actions to make target */ - - if( pState->t->status == EXEC_CMD_FAIL && pState->t->actions ) + /* If actions for building any of the dependencies have failed, bail. + * Otherwise, execute all actions to make the current target. + */ + if ( ( pState->t->status == EXEC_CMD_FAIL ) && pState->t->actions ) { ++counts->skipped; if ( ( pState->t->flags & ( T_FLAG_RMOLD | T_FLAG_NOTFILE ) ) == T_FLAG_RMOLD ) { - if( !unlink( pState->t->boundname ) ) + if ( !unlink( pState->t->boundname ) ) printf( "...removing outdated %s\n", pState->t->boundname ); } - else { + else printf( "...skipped %s for lack of %s...\n", pState->t->name, failed_name ); - } } - if( pState->t->status == EXEC_CMD_OK ) - switch( pState->t->fate ) + if ( pState->t->status == EXEC_CMD_OK ) + switch ( pState->t->fate ) { /* These are handled by the default case below now case T_FATE_INIT: @@ -429,7 +435,7 @@ make1b( state *pState ) break; case T_FATE_ISTMP: - if( DEBUG_MAKE ) + if ( DEBUG_MAKE ) printf( "...using %s...\n", pState->t->name ); break; @@ -439,290 +445,279 @@ make1b( state *pState ) case T_FATE_OUTDATED: case T_FATE_UPDATE: case T_FATE_REBUILD: - - /* Set "on target" vars, build actions, unset vars */ - /* Set "progress" so that make1c() counts this target among */ - /* the successes/failures. */ - - if( pState->t->actions ) + /* Prepare commands for executing actions scheduled for this target + * and then schedule transfer to make1c() state to proceed with + * executing the prepared commands. Commands have their embedded + * variables automatically expanded, including making use of any "on + * target" variables. + */ + if ( pState->t->actions ) { ++counts->total; - if( DEBUG_MAKE && !( counts->total % 100 ) ) + if ( DEBUG_MAKE && !( counts->total % 100 ) ) printf( "...on %dth target...\n", counts->total ); pState->t->cmds = (char *)make1cmds( pState->t ); + /* Set the target's "progress" so that make1c() counts it among + * its successes/failures. + */ pState->t->progress = T_MAKE_RUNNING; } - break; - - /* All possible fates should have been accounted for by now */ + + /* All possible fates should have been accounted for by now. */ default: - printf("ERROR: %s has bad fate %d", pState->t->name, pState->t->fate); + printf( "ERROR: %s has bad fate %d", pState->t->name, + pState->t->fate ); abort(); } - /* Call make1c() to begin the execution of the chain of commands */ - /* needed to build target. If we're not going to build target */ - /* (because of dependency failures or because no commands need to */ - /* be run) the chain will be empty and make1c() will directly */ - /* signal the completion of target. */ - - /* Recurse on our dependents, manipulating progress to guard */ + /* Call make1c() to begin the execution of the chain of commands needed to + * build the target. If we are not going to build the target (due of + * dependency failures or no commands needing to be run) the chain will be + * empty and make1c() will directly signal the target's completion. + */ #ifdef OPT_SEMAPHORE - /* If there is a semaphore, indicate that its in use */ - if( pState->t->semaphore ) - { - ++(pState->t->semaphore->asynccnt); - - if( DEBUG_EXECCMD ) - printf( "SEM: %s now used by %s\n", pState->t->semaphore->name, - pState->t->name ); - } + /* If there is a semaphore, indicate that it is in use. */ + if ( pState->t->semaphore ) + { + ++pState->t->semaphore->asynccnt; + if ( DEBUG_EXECCMD ) + printf( "SEM: %s now used by %s\n", pState->t->semaphore->name, + pState->t->name ); + } #endif - pState->curstate = T_STATE_MAKE1C; + pState->curstate = T_STATE_MAKE1C; } + /* - * make1c() - launch target's next command, call make1b() when done + * make1c() - launch target's next command, call parents' make1b() if none. + * + * If there are (more) commands to run to build this target (and we have not hit + * an error running earlier comands) we launch the command using exec_cmd(). If + * there are no more commands to run, we collect the status from all the actions + * and report our completion to all the parents. */ -static void -make1c( state *pState ) +static void make1c( state * pState ) { - CMD *cmd = (CMD *)pState->t->cmds; + CMD * cmd = (CMD *)pState->t->cmds; - /* If there are (more) commands to run to build this target */ - /* (and we haven't hit an error running earlier comands) we */ - /* launch the command with execcmd(). */ - - /* If there are no more commands to run, we collect the status */ - /* from all the actions then report our completion to all the */ - /* parents. */ + if ( cmd && ( pState->t->status == EXEC_CMD_OK ) ) + { + char * rule_name = 0; + char * target = 0; - if( cmd && pState->t->status == EXEC_CMD_OK ) - { - char *rule_name = 0; - char *target = 0; - if( DEBUG_MAKEQ || - ! ( cmd->rule->actions->flags & RULE_QUIETLY ) && DEBUG_MAKE) - { + if ( DEBUG_MAKEQ || + ( !( cmd->rule->actions->flags & RULE_QUIETLY ) && DEBUG_MAKE ) ) + { rule_name = cmd->rule->name; - target = lol_get(&cmd->args, 0)->string; + target = lol_get( &cmd->args, 0 )->string; if ( globs.noexec ) + out_action( rule_name, target, cmd->buf, "", "", EXIT_OK ); + } + + if ( globs.noexec ) + { + pState->curstate = T_STATE_MAKE1D; + pState->status = EXEC_CMD_OK; + } + else + { + /* Pop state first because exec_cmd() could push state. */ + pop_state( &state_stack ); + exec_cmd( cmd->buf, make_closure, pState->t, cmd->shell, rule_name, + target ); + } + } + else + { + TARGETS * c; + ACTIONS * actions; + + /* Collect status from actions, and distribute it as well. */ + for ( actions = pState->t->actions; actions; actions = actions->next ) + if ( actions->action->status > pState->t->status ) + pState->t->status = actions->action->status; + for ( actions = pState->t->actions; actions; actions = actions->next ) + if ( pState->t->status > actions->action->status ) + actions->action->status = pState->t->status; + + /* Tally success/failure for those we tried to update. */ + if ( pState->t->progress == T_MAKE_RUNNING ) + switch ( pState->t->status ) { - out_action(rule_name,target,cmd->buf,"","",EXIT_OK); + case EXEC_CMD_OK : ++counts->made ; break; + case EXEC_CMD_FAIL: ++counts->failed; break; } - } - if( globs.noexec ) - { - pState->curstate = T_STATE_MAKE1D; - pState->status = EXEC_CMD_OK; - } - else - { - TARGET *t = pState->t; + /* Tell parents their dependency has been built. */ + { + stack temp_stack = { NULL }; + TARGET * t = pState->t; + TARGET * additional_includes = NULL; - pop_state(&state_stack); /* pop state first because execcmd could push state */ - execcmd( cmd->buf, make_closure, t, cmd->shell, rule_name, target ); - } - } - else - { - TARGETS *c; - ACTIONS *actions; + t->progress = T_MAKE_DONE; - /* Collect status from actions, and distribute it as well */ - - for( actions = pState->t->actions; actions; actions = actions->next ) - if( actions->action->status > pState->t->status ) - pState->t->status = actions->action->status; - - for( actions = pState->t->actions; actions; actions = actions->next ) - if( pState->t->status > actions->action->status ) - actions->action->status = pState->t->status; - - /* Tally success/failure for those we tried to update. */ - - if( pState->t->progress == T_MAKE_RUNNING ) - switch( pState->t->status ) - { - case EXEC_CMD_OK: - ++counts->made; - break; - case EXEC_CMD_FAIL: - ++counts->failed; - break; - } - - /* Tell parents dependent has been built */ - { - stack temp_stack = { NULL }; - TARGET *t = pState->t; - TARGET* additional_includes = NULL; - - t->progress = T_MAKE_DONE; - - /* Target was updated. Rescan dependencies. */ - if (t->fate >= T_FATE_MISSING && - t->status == EXEC_CMD_OK && - !t->rescanned) { - - TARGET *target_to_rescan = t; - SETTINGS *s; + /* Target has been updated so rescan it for dependencies. */ + if ( ( t->fate >= T_FATE_MISSING ) && + ( t->status == EXEC_CMD_OK ) && + !t->rescanned ) + { + TARGET * target_to_rescan = t; + SETTINGS * s; target_to_rescan->rescanned = 1; - if (target_to_rescan->flags & T_FLAG_INTERNAL) { - target_to_rescan = t->original_target; - } + if ( target_to_rescan->flags & T_FLAG_INTERNAL ) + target_to_rescan = t->original_target; - /* Clean current includes */ - if (target_to_rescan->includes) { - target_to_rescan->includes = 0; - } + /* Clean current includes. */ + target_to_rescan->includes = 0; s = copysettings( target_to_rescan->settings ); pushsettings( s ); - headers(target_to_rescan); + headers( target_to_rescan ); popsettings( s ); freesettings( s ); - if (target_to_rescan->includes) { + if ( target_to_rescan->includes ) + { target_to_rescan->includes->rescanned = 1; - /* Tricky. The parents were already processed, but they - did not seen the internal node, because it was just - created. We need to make the calls to make1a that would - have been done by parents here, and also make sure all - unprocessed parents will pick up the includes. We must - make sure processing of the additional make1a invocations - is done before make1b which means this target is built, - otherwise the parent will be considered built before this - make1a processing is even started. - */ - make0(target_to_rescan->includes, target_to_rescan->parents->target, 0, 0, 0); - for( c = target_to_rescan->parents; c; c = c->next) { - c->target->depends = targetentry( c->target->depends, + /* Tricky. The parents have already been processed, but they + * have not seen the internal node, because it was just + * created. We need to make the calls to make1a() that would + * have been made by the parents here, and also make sure + * all unprocessed parents will pick up the includes. We + * must make sure processing of the additional make1a() + * invocations is done before make1b() which means this + * target is built, otherwise the parent would be considered + * built before this make1a() processing has even started. + */ + make0( target_to_rescan->includes, target_to_rescan->parents->target, 0, 0, 0 ); + for ( c = target_to_rescan->parents; c; c = c->next ) + c->target->depends = targetentry( c->target->depends, target_to_rescan->includes ); - } /* Will be processed below. */ additional_includes = target_to_rescan->includes; - } - } - - if (additional_includes) - for ( c = t->parents; c; c = c->next ) { - push_state(&temp_stack, additional_includes, c->target, T_STATE_MAKE1A); - } - - for( c = t->parents; c; c = c->next ) { - push_state(&temp_stack, c->target, NULL, T_STATE_MAKE1B); } - + if ( additional_includes ) + for ( c = t->parents; c; c = c->next ) + push_state( &temp_stack, additional_includes, c->target, T_STATE_MAKE1A ); + + for ( c = t->parents; c; c = c->next ) + push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B ); #ifdef OPT_SEMAPHORE - /* If there is a semaphore, its now free */ - if( t->semaphore ) - { - assert( t->semaphore->asynccnt == 1 ); - --(t->semaphore->asynccnt); + /* If there is a semaphore, it is now free. */ + if ( t->semaphore ) + { + assert( t->semaphore->asynccnt == 1 ); + --t->semaphore->asynccnt; - if( DEBUG_EXECCMD ) - printf( "SEM: %s is now free\n", t->semaphore->name); + if ( DEBUG_EXECCMD ) + printf( "SEM: %s is now free\n", t->semaphore->name ); - /* If anything is waiting, notify the next target. There's no - point in notifying all waiting targets, since they'll be - serialized again. */ - if( t->semaphore->parents ) - { - TARGETS *first = t->semaphore->parents; - if( first->next ) - first->next->tail = first->tail; - t->semaphore->parents = first->next; + /* If anything is waiting, notify the next target. There is no + * point in notifying waiting targets, since they will be + * notified again. + */ + if ( t->semaphore->parents ) + { + TARGETS * first = t->semaphore->parents; + if ( first->next ) + first->next->tail = first->tail; + t->semaphore->parents = first->next; - if( DEBUG_EXECCMD ) - printf( "SEM: placing %s on stack\n", first->target->name); - push_state(&temp_stack, first->target, NULL, T_STATE_MAKE1B); - BJAM_FREE( first ); - } - } + if ( DEBUG_EXECCMD ) + printf( "SEM: placing %s on stack\n", first->target->name ); + push_state( &temp_stack, first->target, NULL, T_STATE_MAKE1B ); + BJAM_FREE( first ); + } + } #endif - - /* must pop state before pushing any more */ - pop_state(&state_stack); - - /* using stacks reverses the order of execution. Reverse it back */ - push_stack_on_stack(&state_stack, &temp_stack); + /* Must pop state before pushing any more. */ + pop_state( &state_stack ); - } - } + /* Using stacks reverses the order of execution. Reverse it back. */ + push_stack_on_stack( &state_stack, &temp_stack ); + } + } } -/* Look up the __TIMING_RULE__ variable on the given target, and if - * non-empty, invoke the rule it names, passing the given - * timing_info + +/* + * call_timing_rule() - Look up the __TIMING_RULE__ variable on the given + * target, and if non-empty, invoke the rule it names, passing the given + * timing_info. */ -static void call_timing_rule(TARGET* target, timing_info* time) + +static void call_timing_rule( TARGET * target, timing_info * time ) { - LIST* timing_rule; - - pushsettings(target->settings); + LIST * timing_rule; + + pushsettings( target->settings ); timing_rule = var_get( "__TIMING_RULE__" ); - popsettings(target->settings); + popsettings( target->settings ); - if (timing_rule) + if ( timing_rule ) { - /* rule timing-rule ( - args * : - target : - start end user system ) */ + /* rule timing-rule ( args * : target : start end user system ) */ - /* Prepare the argument list */ - FRAME frame[1]; + /* Prepare the argument list. */ + FRAME frame[ 1 ]; frame_init( frame ); - /* args * :: $(__ACTION_RULE__[2-]) */ + /* args * :: $(__TIMING_RULE__[2-]) */ lol_add( frame->args, list_copy( L0, timing_rule->next ) ); /* target :: the name of the target */ lol_add( frame->args, list_new( L0, target->name ) ); /* start end user system :: info about the action command */ - lol_add( frame->args, - list_new( list_new( list_new( list_new( L0, - outf_time(time->start) ), - outf_time(time->end) ), - outf_double(time->user) ), - outf_double(time->system) ) ); + lol_add( frame->args, list_new( list_new( list_new( list_new( L0, + outf_time ( time->start ) ), + outf_time ( time->end ) ), + outf_double( time->user ) ), + outf_double( time->system ) ) ); /* Call the rule. */ evaluate_rule( timing_rule->string, frame ); - /* Clean up */ + /* Clean up. */ frame_free( frame ); } } -/* Look up the __ACTION_RULE__ variable on the given target, and if - * non-empty, invoke the rule it names, passing the given info, - * timing_info, executed command and command output + +/* + * call_action_rule() - Look up the __ACTION_RULE__ variable on the given + * target, and if non-empty, invoke the rule it names, passing the given info, + * timing_info, executed command and command output. */ -static void call_action_rule(TARGET* target, int status, timing_info* time, - char *executed_command, char *command_output) + +static void call_action_rule +( + TARGET * target, + int status, + timing_info * time, + char * executed_command, + char * command_output +) { - LIST* action_rule; + LIST * action_rule; - pushsettings(target->settings); + pushsettings( target->settings ); action_rule = var_get( "__ACTION_RULE__" ); - popsettings(target->settings); + popsettings( target->settings ); - if (action_rule) + if ( action_rule ) { /* rule action-rule ( args * : @@ -730,8 +725,8 @@ static void call_action_rule(TARGET* target, int status, timing_info* time, command status start end user system : output ? ) */ - /* Prepare the argument list */ - FRAME frame[1]; + /* Prepare the argument list. */ + FRAME frame[ 1 ]; frame_init( frame ); /* args * :: $(__ACTION_RULE__[2-]) */ @@ -743,409 +738,400 @@ static void call_action_rule(TARGET* target, int status, timing_info* time, /* command status start end user system :: info about the action command */ lol_add( frame->args, list_new( list_new( list_new( list_new( list_new( list_new( L0, - newstr(executed_command) ), - outf_int(status) ), - outf_time(time->start) ), - outf_time(time->end) ), - outf_double(time->user) ), - outf_double(time->system) ) ); + newstr( executed_command ) ), + outf_int( status ) ), + outf_time( time->start ) ), + outf_time( time->end ) ), + outf_double( time->user ) ), + outf_double( time->system ) ) ); /* output ? :: the output of the action command */ - if (command_output) - lol_add(frame->args, list_new(L0, newstr(command_output))); + if ( command_output ) + lol_add( frame->args, list_new( L0, newstr( command_output ) ) ); else - lol_add(frame->args, L0); + lol_add( frame->args, L0 ); /* Call the rule. */ evaluate_rule( action_rule->string, frame ); - /* Clean up */ + /* Clean up. */ frame_free( frame ); } } -static void make_closure( - void *closure, int status, timing_info* time, char *executed_command, - char *command_output) -{ - TARGET* built = (TARGET*)closure; - - call_timing_rule(built, time); - if (DEBUG_EXECCMD) - printf("%f sec system; %f sec user\n", time->system, time->user); - - call_action_rule(built, status, time, executed_command, command_output); - - push_state(&state_stack, built, NULL, T_STATE_MAKE1D)->status = status; -} - /* - * make1d() - handle command execution completion and call back make1c() + * make_closure() - internal function passed as a notification callback for when + * commands finish getting executed by the OS. */ -static void -make1d(state *pState) +static void make_closure +( + void * closure, + int status, + timing_info * time, + char * executed_command, + char * command_output +) { - TARGET *t = pState->t; - CMD *cmd = (CMD *)t->cmds; - int status = pState->status; + TARGET * built = (TARGET *)closure; - /* Execcmd() has completed. All we need to do is fiddle with the */ - /* status and signal our completion so make1c() can run the next */ - /* command. On interrupts, we bail heavily. */ + call_timing_rule( built, time ); + if ( DEBUG_EXECCMD ) + printf( "%f sec system; %f sec user\n", time->system, time->user ); - if ( t->flags & T_FLAG_FAIL_EXPECTED ) + call_action_rule( built, status, time, executed_command, command_output ); + + push_state( &state_stack, built, NULL, T_STATE_MAKE1D )->status = status; +} + + +/* + * make1d() - handle command execution completion and call back make1c(). + * + * exec_cmd() has completed and now all we need to do is fiddle with the status + * and call back to make1c() so it can run the next command scheduled for + * building this target or close up the target's build process in case there are + * no more commands scheduled for it. On interrupts, we bail heavily. + */ + +static void make1d( state * pState ) +{ + TARGET * t = pState->t; + CMD * cmd = (CMD *)t->cmds; + int status = pState->status; + + if ( t->flags & T_FLAG_FAIL_EXPECTED ) + { + /* Invert execution result when FAIL_EXPECTED has been applied. */ + switch ( status ) { - /* invert execution result when FAIL_EXPECTED was applied */ - switch (status) - { - case EXEC_CMD_FAIL: status = EXEC_CMD_OK; break; + case EXEC_CMD_FAIL: status = EXEC_CMD_OK ; break; case EXEC_CMD_OK: status = EXEC_CMD_FAIL; break; - default: - ; - } } - - if( status == EXEC_CMD_FAIL && ( cmd->rule->actions->flags & RULE_IGNORE ) ) - status = EXEC_CMD_OK; + } - /* On interrupt, set intr so _everything_ fails */ + if ( ( status == EXEC_CMD_FAIL ) && + ( cmd->rule->actions->flags & RULE_IGNORE ) ) + status = EXEC_CMD_OK; - if( status == EXEC_CMD_INTR ) - ++intr; + /* On interrupt, set intr so _everything_ fails. */ + if ( status == EXEC_CMD_INTR ) + ++intr; - if( status == EXEC_CMD_FAIL && DEBUG_MAKE ) - { - /* Print command text on failure */ + /* Print command text on failure. */ + if ( ( status == EXEC_CMD_FAIL ) && DEBUG_MAKE ) + { + if ( !DEBUG_EXEC ) + printf( "%s\n", cmd->buf ); - if( !DEBUG_EXEC ) - printf( "%s\n", cmd->buf ); + printf( "...failed %s ", cmd->rule->name ); + list_print( lol_get( &cmd->args, 0 ) ); + printf( "...\n" ); + } - printf( "...failed %s ", cmd->rule->name ); - list_print( lol_get( &cmd->args, 0 ) ); - printf( "...\n" ); - } + /* Treat failed commands as interrupts in case we were asked to stop the + * build in case of any errors. + */ + if ( ( status == EXEC_CMD_FAIL ) && globs.quitquick ) + ++intr; - if (status == EXEC_CMD_FAIL) - if( globs.quitquick ) ++intr; + /* If the command was interrupted or failed and the target is not + * "precious", remove the targets. + */ + if ( ( status != EXEC_CMD_OK ) && !( cmd->rule->actions->flags & RULE_TOGETHER ) ) + { + LIST * targets = lol_get( &cmd->args, 0 ); + for ( ; targets; targets = list_next( targets ) ) + if ( !unlink( targets->string ) ) + printf( "...removing %s\n", targets->string ); + } - /* If the command was interrupted or failed and the target */ - /* is not "precious", remove the targets */ - - if( status != EXEC_CMD_OK && !( cmd->rule->actions->flags & RULE_TOGETHER ) ) - { - LIST *targets = lol_get( &cmd->args, 0 ); - - for( ; targets; targets = list_next( targets ) ) - if( !unlink( targets->string ) ) - printf( "...removing %s\n", targets->string ); - } - - /* Free this command and call make1c() to move onto next command. */ - - t->status = status; - t->cmds = (char *)cmd_next( cmd ); - - cmd_free( cmd ); - - pState->curstate = T_STATE_MAKE1C; + /* Free this command and call make1c() to move onto the next one scheduled + * for building this same target. + */ + t->status = status; + t->cmds = (char *)cmd_next( cmd ); + cmd_free( cmd ); + pState->curstate = T_STATE_MAKE1C; } + /* - * swap_settings() - replace the settings from the current module and - * target with those from the new module and target + * swap_settings() - replace the settings from the current module and target + * with those from the new module and target */ -static void swap_settings( - module_t** current_module - , TARGET** current_target - , module_t* new_module - , TARGET* new_target) + +static void swap_settings +( + module_t * * current_module, + TARGET * * current_target, + module_t * new_module, + TARGET * new_target +) { - if (new_module == root_module()) + if ( new_module == root_module() ) new_module = 0; - - if (new_target == *current_target && new_module == *current_module) + + if ( ( new_target == *current_target ) && ( new_module == *current_module ) ) return; - if (*current_target) + if ( *current_target ) popsettings( (*current_target)->settings ); - - if (new_module != *current_module) + + if ( new_module != *current_module ) { - if (*current_module) + if ( *current_module ) exit_module( *current_module ); *current_module = new_module; - - if (new_module) + + if ( new_module ) enter_module( new_module ); } *current_target = new_target; - if (new_target) + if ( new_target ) pushsettings( new_target->settings ); } + /* - * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc + * make1cmds() - turn ACTIONS into CMDs, grouping, splitting, etc. * - * Essentially copies a chain of ACTIONs to a chain of CMDs, - * grouping RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions, - * and handling RULE_NEWSRCS actions. The result is a chain of - * CMDs which can be expanded by var_string() and executed with - * execcmd(). + * Essentially copies a chain of ACTIONs to a chain of CMDs, grouping + * RULE_TOGETHER actions, splitting RULE_PIECEMEAL actions, and handling + * RULE_NEWSRCS actions. The result is a chain of CMDs which can be expanded by + * var_string() and executed using exec_cmd(). */ -static CMD * -make1cmds( TARGET *t ) +static CMD * make1cmds( TARGET * t ) { - CMD *cmds = 0; - LIST *shell = 0; - - module_t *settings_module = 0; - TARGET *settings_target = 0; - - /* Step through actions */ - /* Actions may be shared with other targets or grouped with */ - /* RULE_TOGETHER, so actions already seen are skipped. */ - - ACTIONS* a0; - for(a0 = t->actions ; a0; a0 = a0->next ) - { - RULE *rule = a0->action->rule; - rule_actions *actions = rule->actions; - SETTINGS *boundvars; - LIST *nt, *ns; - ACTIONS *a1; - int start, chunk, length; + CMD * cmds = 0; + LIST * shell = 0; + module_t * settings_module = 0; + TARGET * settings_target = 0; + ACTIONS * a0; - /* Only do rules with commands to execute. */ - /* If this action has already been executed, use saved status */ + /* Step through actions. Actions may be shared with other targets or grouped + * using RULE_TOGETHER, so actions already seen are skipped. + */ + for ( a0 = t->actions ; a0; a0 = a0->next ) + { + RULE * rule = a0->action->rule; + rule_actions * actions = rule->actions; + SETTINGS * boundvars; + LIST * nt; + LIST * ns; + ACTIONS * a1; + int start; + int chunk; + int length; - if( !actions || a0->action->running ) - continue; + /* Only do rules with commands to execute. If this action has already + * been executed, use saved status. + */ + if ( !actions || a0->action->running ) + continue; - a0->action->running = 1; - - /* Make LISTS of targets and sources */ - /* If `execute together` has been specified for this rule, tack */ - /* on sources from each instance of this rule for this target. */ + a0->action->running = 1; - nt = make1list( L0, a0->action->targets, 0 ); - ns = make1list( L0, a0->action->sources, actions->flags ); + /* Make LISTS of targets and sources. If `execute together` has been + * specified for this rule, tack on sources from each instance of this + * rule for this target. + */ + nt = make1list( L0, a0->action->targets, 0 ); + ns = make1list( L0, a0->action->sources, actions->flags ); + if ( actions->flags & RULE_TOGETHER ) + for ( a1 = a0->next; a1; a1 = a1->next ) + if ( a1->action->rule == rule && !a1->action->running ) + { + ns = make1list( ns, a1->action->sources, actions->flags ); + a1->action->running = 1; + } - if( actions->flags & RULE_TOGETHER ) - for( a1 = a0->next; a1; a1 = a1->next ) - if( a1->action->rule == rule && !a1->action->running ) - { - ns = make1list( ns, a1->action->sources, actions->flags ); - a1->action->running = 1; - } + /* If doing only updated (or existing) sources, but none have been + * updated (or exist), skip this action. + */ + if ( !ns && ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) ) + { + list_free( nt ); + continue; + } - /* If doing only updated (or existing) sources, but none have */ - /* been updated (or exist), skip this action. */ + swap_settings( &settings_module, &settings_target, rule->module, t ); + if ( !shell ) + shell = var_get( "JAMSHELL" ); /* shell is per-target */ - if( !ns && ( actions->flags & ( RULE_NEWSRCS | RULE_EXISTING ) ) ) - { - list_free( nt ); - continue; - } + /* If we had 'actions xxx bind vars' we bind the vars now. */ + boundvars = make1settings( actions->bindlist ); + pushsettings( boundvars ); - swap_settings( &settings_module, &settings_target, rule->module, t ); - if (!shell) - shell = var_get( "JAMSHELL" ); /* shell is per-target */ - - /* If we had 'actions xxx bind vars' we bind the vars now */ + /* + * Build command, starting with all source args. + * + * If cmd_new returns 0, it is because the resulting command length is + * > MAXLINE. In this case, we will slowly reduce the number of source + * arguments presented until it does fit. This only applies to actions + * that allow PIECEMEAL commands. + * + * While reducing slowly takes a bit of compute time to get things just + * right, it is worth it to get as close to MAXLINE as possible, because + * launching the commands we are executing is likely to be much more + * compute intensive. + * + * Note we loop through at least once, for sourceless actions. + */ - boundvars = make1settings( actions->bindlist ); - pushsettings( boundvars ); + start = 0; + chunk = length = list_length( ns ); - /* - * Build command, starting with all source args. - * - * If cmd_new returns 0, it's because the resulting command - * length is > MAXLINE. In this case, we'll slowly reduce - * the number of source arguments presented until it does - * fit. This only applies to actions that allow PIECEMEAL - * commands. - * - * While reducing slowly takes a bit of compute time to get - * things just right, it's worth it to get as close to MAXLINE - * as possible, because launching the commands we're executing - * is likely to be much more compute intensive! - * - * Note we loop through at least once, for sourceless actions. - */ + do + { + /* Build cmd: cmd_new consumes its lists. */ + CMD * cmd = cmd_new( rule, + list_copy( L0, nt ), + list_sublist( ns, start, chunk ), + list_copy( L0, shell ) ); - start = 0; - chunk = length = list_length( ns ); + if ( cmd ) + { + /* It fit: chain it up. */ + if ( !cmds ) cmds = cmd; + else cmds->tail->next = cmd; + cmds->tail = cmd; + start += chunk; + } + else if ( ( actions->flags & RULE_PIECEMEAL ) && ( chunk > 1 ) ) + { + /* Reduce chunk size slowly. */ + chunk = chunk * 9 / 10; + } + else + { + /* Too long and not splittable. */ + printf( "%s actions too long (max %d):\n", rule->name, MAXLINE + ); - do - { - /* Build cmd: cmd_new consumes its lists. */ + /* Tell the user what didn't fit. */ + cmd = cmd_new( rule, list_copy( L0, nt ), + list_sublist( ns, start, chunk ), + list_new( L0, newstr( "%" ) ) ); + fputs( cmd->buf, stdout ); + exit( EXITBAD ); + } + } + while ( start < length ); - CMD *cmd = cmd_new( rule, - list_copy( L0, nt ), - list_sublist( ns, start, chunk ), - list_copy( L0, shell ) ); + /* These were always copied when used. */ + list_free( nt ); + list_free( ns ); - if( cmd ) - { - /* It fit: chain it up. */ + /* Free the variables whose values were bound by 'actions xxx bind + * vars'. + */ + popsettings( boundvars ); + freesettings( boundvars ); + } - if( !cmds ) cmds = cmd; - else cmds->tail->next = cmd; - cmds->tail = cmd; - start += chunk; - } - else if( ( actions->flags & RULE_PIECEMEAL ) && chunk > 1 ) - { - /* Reduce chunk size slowly. */ - - chunk = chunk * 9 / 10; - } - else - { - /* Too long and not splittable. */ - - printf( "%s actions too long (max %d):\n", - rule->name, MAXLINE ); - - /* Tell the user what didn't fit */ - cmd = cmd_new( - rule, list_copy( L0, nt ), - list_sublist( ns, start, chunk ), - list_new( L0, newstr( "%" ) ) ); - - printf( cmd->buf ); - - exit( EXITBAD ); - } - } - while( start < length ); - - /* These were always copied when used. */ - - list_free( nt ); - list_free( ns ); - - /* Free the variables whose values were bound by */ - /* 'actions xxx bind vars' */ - - popsettings( boundvars ); - freesettings( boundvars ); - } - - swap_settings( &settings_module, &settings_target, 0, 0 ); - return cmds; + swap_settings( &settings_module, &settings_target, 0, 0 ); + return cmds; } + /* - * make1list() - turn a list of targets into a LIST, for $(<) and $(>) + * make1list() - turn a list of targets into a LIST, for $(<) and $(>). */ -static LIST * -make1list( - LIST *l, - TARGETS *targets, - int flags ) +static LIST * make1list( LIST * l, TARGETS * targets, int flags ) { - for( ; targets; targets = targets->next ) + for ( ; targets; targets = targets->next ) { - TARGET *t = targets->target; + TARGET * t = targets->target; - if( t->binding == T_BIND_UNBOUND ) - make1bind( t ); + if ( t->binding == T_BIND_UNBOUND ) + make1bind( t ); - if ( ( flags & RULE_EXISTING ) && ( flags & RULE_NEWSRCS ) ) - { - if ( t->binding != T_BIND_EXISTS && t->fate <= T_FATE_STABLE) - continue; - } - else - { - if( ( flags & RULE_EXISTING ) && t->binding != T_BIND_EXISTS ) - continue; + if ( ( flags & RULE_EXISTING ) && ( flags & RULE_NEWSRCS ) ) + { + if ( ( t->binding != T_BIND_EXISTS ) && ( t->fate <= T_FATE_STABLE ) ) + continue; + } + else + { + if ( ( flags & RULE_EXISTING ) && ( t->binding != T_BIND_EXISTS ) ) + continue; - if( ( flags & RULE_NEWSRCS ) && t->fate <= T_FATE_STABLE ) - continue; - } + if ( ( flags & RULE_NEWSRCS ) && ( t->fate <= T_FATE_STABLE ) ) + continue; + } - /* Prohibit duplicates for RULE_TOGETHER */ + /* Prohibit duplicates for RULE_TOGETHER. */ + if ( flags & RULE_TOGETHER ) + { + LIST * m; + for ( m = l; m; m = m->next ) + if ( !strcmp( m->string, t->boundname ) ) + break; + if ( m ) + continue; + } - if( flags & RULE_TOGETHER ) - { - LIST *m; - - for( m = l; m; m = m->next ) - if( !strcmp( m->string, t->boundname ) ) - break; - - if( m ) - continue; - } - - /* Build new list */ - - l = list_new( l, copystr( t->boundname ) ); + /* Build new list. */ + l = list_new( l, copystr( t->boundname ) ); } return l; } + /* - * make1settings() - for vars that get bound values, build up replacement lists + * make1settings() - for vars that get bound values, build up replacement lists. */ -static SETTINGS * -make1settings( LIST *vars ) +static SETTINGS * make1settings( LIST * vars ) { - SETTINGS *settings = 0; + SETTINGS * settings = 0; - for( ; vars; vars = list_next( vars ) ) - { - LIST *l = var_get( vars->string ); - LIST *nl = 0; + for ( ; vars; vars = list_next( vars ) ) + { + LIST * l = var_get( vars->string ); + LIST * nl = 0; - for( ; l; l = list_next( l ) ) - { - TARGET *t = bindtarget( l->string ); + for ( ; l; l = list_next( l ) ) + { + TARGET * t = bindtarget( l->string ); - /* Make sure the target is bound */ + /* Make sure the target is bound. */ + if ( t->binding == T_BIND_UNBOUND ) + make1bind( t ); - if( t->binding == T_BIND_UNBOUND ) - make1bind( t ); + /* Build a new list. */ + nl = list_new( nl, copystr( t->boundname ) ); + } - /* Build new list */ + /* Add to settings chain. */ + settings = addsettings( settings, VAR_SET, vars->string, nl ); + } - nl = list_new( nl, copystr( t->boundname ) ); - } - - /* Add to settings chain */ - - settings = addsettings( settings, VAR_SET, vars->string, nl ); - } - - return settings; + return settings; } + /* - * make1bind() - bind targets that weren't bound in dependency analysis + * make1bind() - bind targets that were not bound during dependency analysis * - * Spot the kludge! If a target is not in the dependency tree, it didn't - * get bound by make0(), so we have to do it here. Ugly. + * Spot the kludge! If a target is not in the dependency tree, it did not get + * bound by make0(), so we have to do it here. Ugly. */ -static void -make1bind( - TARGET *t ) +static void make1bind( TARGET * t ) { - if( t->flags & T_FLAG_NOTFILE ) - return; + if ( t->flags & T_FLAG_NOTFILE ) + return; - pushsettings( t->settings ); - t->boundname = search( t->name, &t->time, 0 ); - t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; - popsettings( t->settings ); + pushsettings( t->settings ); + t->boundname = search( t->name, &t->time, 0, ( t->flags & T_FLAG_ISFILE ) ); + t->binding = t->time ? T_BIND_EXISTS : T_BIND_MISSING; + popsettings( t->settings ); } diff --git a/src/engine/mem.c b/src/engine/mem.c index a53640731..6a11fb38a 100644 --- a/src/engine/mem.c +++ b/src/engine/mem.c @@ -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" diff --git a/src/engine/mem.h b/src/engine/mem.h index afc653f37..71b2fb4be 100644 --- a/src/engine/mem.h +++ b/src/engine/mem.h @@ -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 diff --git a/src/engine/mkjambase.c b/src/engine/mkjambase.c index 815c76cfe..cdf599820 100644 --- a/src/engine/mkjambase.c +++ b/src/engine/mkjambase.c @@ -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 -# include +#include +#include -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; } diff --git a/src/engine/modules.c b/src/engine/modules.c index 938802ae0..729525941 100644 --- a/src/engine/modules.c +++ b/src/engine/modules.c @@ -16,11 +16,12 @@ #include "strings.h" #include -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; } diff --git a/src/engine/modules/order.c b/src/engine/modules/order.c index 48761e80d..54b58cd54 100644 --- a/src/engine/modules/order.c +++ b/src/engine/modules/order.c @@ -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 diff --git a/src/engine/modules/property-set.c b/src/engine/modules/property-set.c index 847f6be6f..2b0fb5d97 100644 --- a/src/engine/modules/property-set.c +++ b/src/engine/modules/property-set.c @@ -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); } - } diff --git a/src/engine/native.c b/src/engine/native.c index 5933156f5..4c2899595 100644 --- a/src/engine/native.c +++ b/src/engine/native.c @@ -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); } } - diff --git a/src/engine/native.h b/src/engine/native.h index c252e41ca..3fc710b9c 100644 --- a/src/engine/native.h +++ b/src/engine/native.h @@ -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); diff --git a/src/engine/newstr.c b/src/engine/newstr.c index 47eabd69f..6a229eb21 100644 --- a/src/engine/newstr.c +++ b/src/engine/newstr.c @@ -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 ); */ } diff --git a/src/engine/newstr.h b/src/engine/newstr.h index cf2dd34b7..84a4d7b6d 100644 --- a/src/engine/newstr.h +++ b/src/engine/newstr.h @@ -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(); diff --git a/src/engine/option.c b/src/engine/option.c index 5826d1154..69f3bf802 100644 --- a/src/engine/option.c +++ b/src/engine/option.c @@ -12,92 +12,83 @@ * * {o >o * \<>) "Process command line options as defined in . - * 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; } diff --git a/src/engine/option.h b/src/engine/option.h index 657a763a0..872bf1ff4 100644 --- a/src/engine/option.h +++ b/src/engine/option.h @@ -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 ); diff --git a/src/engine/output.c b/src/engine/output.c index 1204d8d4f..ae20013f8 100644 --- a/src/engine/output.c +++ b/src/engine/output.c @@ -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 ); } - diff --git a/src/engine/output.h b/src/engine/output.h index 6cd1b6c88..9e9876cfc 100644 --- a/src/engine/output.h +++ b/src/engine/output.h @@ -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) diff --git a/src/engine/parse.c b/src/engine/parse.c index fc92ce95f..9114fa057 100644 --- a/src/engine/parse.c +++ b/src/engine/parse.c @@ -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 ); } diff --git a/src/engine/parse.h b/src/engine/parse.h index ae9e9efc5..e324972f7 100644 --- a/src/engine/parse.h +++ b/src/engine/parse.h @@ -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 - diff --git a/src/engine/patchlevel.h b/src/engine/patchlevel.h index d425bb715..c3ed4cb86 100644 --- a/src/engine/patchlevel.h +++ b/src/engine/patchlevel.h @@ -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" diff --git a/src/engine/pathmac.c b/src/engine/pathmac.c index 4cbe8d40c..e2c250e33 100644 --- a/src/engine/pathmac.c +++ b/src/engine/pathmac.c @@ -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 */ + 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 */ - /* 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 */ diff --git a/src/engine/pathsys.h b/src/engine/pathsys.h index 92034b7ef..49d2bf8e2 100644 --- a/src/engine/pathsys.h +++ b/src/engine/pathsys.h @@ -5,7 +5,7 @@ */ /* - * pathsys.h - PATHNAME struct + * pathsys.h - PATHNAME struct */ /* @@ -13,7 +13,7 @@ * * 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 diff --git a/src/engine/pathunix.c b/src/engine/pathunix.c index 725a51f5f..2daad14b7 100644 --- a/src/engine/pathunix.c +++ b/src/engine/pathunix.c @@ -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 */ + 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 */ - /* 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) _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; } diff --git a/src/engine/pathvms.c b/src/engine/pathvms.c index 86e3f0e59..975fe5a57 100644 --- a/src/engine/pathvms.c +++ b/src/engine/pathvms.c @@ -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 */ + 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 */ - /* 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 */ diff --git a/src/engine/pwd.c b/src/engine/pwd.c index 896524820..90c8eb175 100644 --- a/src/engine/pwd.c +++ b/src/engine/pwd.c @@ -6,25 +6,29 @@ #include "lists.h" #include "newstr.h" #include "pathsys.h" +#include "mem.h" #include +#include /* MinGW on windows declares PATH_MAX in limits.h */ #if defined(NT) && ! defined(__GNUC__) #include #define PATH_MAX _MAX_PATH #else -#include #include #if defined(__COMO__) #include #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); } - diff --git a/src/engine/regexp.c b/src/engine/regexp.c index ea2875109..30197a2fe 100644 --- a/src/engine/regexp.c +++ b/src/engine/regexp.c @@ -1,22 +1,22 @@ /* * regcomp and regexec -- regsub and regerror are elsewhere * - * Copyright (c) 1986 by University of Toronto. - * Written by Henry Spencer. Not derived from licensed software. + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. * - * Permission is granted to anyone to use this software for any - * purpose on any computer system, and to redistribute it freely, - * subject to the following restrictions: + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: * - * 1. The author is not responsible for the consequences of use of - * this software, no matter how awful, even if they arise - * from defects in it. + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. * - * 2. The origin of this software must not be misrepresented, either - * by explicit claim or by omission. + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. * - * 3. Altered versions must be plainly marked as such, and must not - * be misrepresented as being the original software. + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to | *** to assist in implementing egrep. @@ -37,94 +37,96 @@ *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald *** seiwald@perforce.com, on 20 January 2000, to use function prototypes. * - * Beware that some of this code is subtly aware of the way operator - * precedence is structured in regular expressions. Serious changes in - * regular-expression syntax might require a total rethink. + * Beware that some of this code is subtly aware of the way operator precedence + * is structured in regular expressions. Serious changes in regular-expression + * syntax might require a total rethink. */ + + #include "jam.h" #include "regexp.h" #include #include #ifndef ultrix -#include + #include #endif #include + /* * The "internal use only" fields in regexp.h are present to pass info from * compile to execute that permits the execute phase to run lots faster on - * simple cases. They are: - * - * regstart char that must begin a match; '\0' if none obvious - * reganch is the match anchored (at beginning-of-line only)? - * regmust string (pointer into program) that match must include, or NULL - * regmlen length of regmust string + * simple cases. They are: + : + * regstart char that must begin a match; '\0' if none obvious. + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL. + * regmlen length of regmust string. * * Regstart and reganch permit very fast decisions on suitable starting points - * for a match, cutting down the work a lot. Regmust permits fast rejection - * of lines that cannot possibly match. The regmust tests are costly enough - * that regcomp() supplies a regmust only if the r.e. contains something - * potentially expensive (at present, the only such thing detected is * or + - * at the start of the r.e., which can involve a lot of backup). Regmlen is - * supplied because the test in regexec() needs it and regcomp() is computing - * it anyway. + * for a match, cutting down the work a lot. Regmust permits fast rejection of + * lines that cannot possibly match. The regmust tests are costly enough that + * regcomp() supplies a regmust only if the r.e. contains something potentially + * expensive (at present, the only such thing detected is * or + at the start of + * the r.e., which can involve a lot of backup). Regmlen is supplied because the + * test in regexec() needs it and regcomp() is computing it anyway. */ /* - * Structure for regexp "program". This is essentially a linear encoding - * of a nondeterministic finite-state machine (aka syntax charts or - * "railroad normal form" in parsing technology). Each node is an opcode - * plus a "next" pointer, possibly plus an operand. "Next" pointers of - * all nodes except BRANCH implement concatenation; a "next" pointer with - * a BRANCH on both ends of it is connecting two alternatives. (Here we - * have one of the subtle syntax dependencies: an individual BRANCH (as - * opposed to a collection of them) is never concatenated with anything - * because of operator precedence.) The operand of some types of node is - * a literal string; for others, it is a node leading into a sub-FSM. In - * particular, the operand of a BRANCH node is the first node of the branch. - * (NB this is *not* a tree structure: the tail of the branch connects - * to the thing following the set of BRANCHes.) The opcodes are: + * Structure for regexp "program". This is essentially a linear encoding of a + * nondeterministic finite-state machine (aka syntax charts or "railroad normal + * form" in parsing technology). Each node is an opcode plus a "next" pointer, + * possibly plus an operand. "Next" pointers of all nodes except BRANCH + * implement concatenation; a "next" pointer with a BRANCH on both ends of it is + * connecting two alternatives. [Here we have one of the subtle syntax + * dependencies: an individual BRANCH, as opposed to a collection of them, is + * never concatenated with anything because of operator precedence.] The operand + * of some types of node is a literal string; for others, it is a node leading + * into a sub-FSM. In particular, the operand of a BRANCH node is the first node + * of the branch. [NB this is *not* a tree structure: the tail of the branch + * connects to the thing following the set of BRANCHes.] The opcodes are: */ -/* definition number opnd? meaning */ -#define END 0 /* no End of program. */ -#define BOL 1 /* no Match "" at beginning of line. */ -#define EOL 2 /* no Match "" at end of line. */ -#define ANY 3 /* no Match any one character. */ -#define ANYOF 4 /* str Match any character in this string. */ -#define ANYBUT 5 /* str Match any character not in this string. */ -#define BRANCH 6 /* node Match this alternative, or the next... */ -#define BACK 7 /* no Match "", "next" ptr points backward. */ -#define EXACTLY 8 /* str Match this string. */ -#define NOTHING 9 /* no Match empty string. */ -#define STAR 10 /* node Match this (simple) thing 0 or more times. */ -#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ -#define WORDA 12 /* no Match "" at wordchar, where prev is nonword */ -#define WORDZ 13 /* no Match "" at nonwordchar, where prev is word */ -#define OPEN 20 /* no Mark this point in input as start of #n. */ - /* OPEN+1 is number 1, etc. */ -#define CLOSE 30 /* no Analogous to OPEN. */ +/* definition number opnd? meaning */ +#define END 0 /* no End of program. */ +#define BOL 1 /* no Match "" at beginning of line. */ +#define EOL 2 /* no Match "" at end of line. */ +#define ANY 3 /* no Match any one character. */ +#define ANYOF 4 /* str Match any character in this string. */ +#define ANYBUT 5 /* str Match any character not in this string. */ +#define BRANCH 6 /* node Match this alternative, or the next... */ +#define BACK 7 /* no Match "", "next" ptr points backward. */ +#define EXACTLY 8 /* str Match this string. */ +#define NOTHING 9 /* no Match empty string. */ +#define STAR 10 /* node Match this (simple) thing 0 or more times. */ +#define PLUS 11 /* node Match this (simple) thing 1 or more times. */ +#define WORDA 12 /* no Match "" at wordchar, where prev is nonword */ +#define WORDZ 13 /* no Match "" at nonwordchar, where prev is word */ +#define OPEN 20 /* no Mark this point in input as start of #n. */ + /* OPEN+1 is number 1, etc. */ +#define CLOSE 30 /* no Analogous to OPEN. */ + /* * Opcode notes: * - * BRANCH The set of branches constituting a single choice are hooked - * together with their "next" pointers, since precedence prevents - * anything being concatenated to any individual branch. The - * "next" pointer of the last BRANCH in a choice points to the - * thing following the whole choice. This is also where the - * final "next" pointer of each individual branch points; each - * branch starts with the operand node of a BRANCH node. + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. * - * BACK Normal "next" pointers all implicitly point forward; BACK - * exists to make loop structures possible. + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. * - * STAR,PLUS '?', and complex '*' and '+', are implemented as circular - * BRANCH structures using BACK. Simple cases (one character - * per match) are implemented with STAR and PLUS for speed - * and to minimize recursive plunges. + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. * - * OPEN,CLOSE ...are numbered at compile time. + * OPEN,CLOSE ...are numbered at compile time. */ /* @@ -137,9 +139,9 @@ * Using two bytes for the "next" pointer is vast overkill for most things, * but allows patterns to get big without disasters. */ -#define OP(p) (*(p)) -#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) -#define OPERAND(p) ((p) + 3) +#define OP(p) (*(p)) +#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) +#define OPERAND(p) ((p) + 3) /* * See regmagic.h for one further detail of program structure. @@ -150,36 +152,36 @@ * Utility definitions. */ #ifndef CHARBITS -#define UCHARAT(p) ((int)*(unsigned char *)(p)) +#define UCHARAT(p) ((int)*(unsigned char *)(p)) #else -#define UCHARAT(p) ((int)*(p)&CHARBITS) +#define UCHARAT(p) ((int)*(p)&CHARBITS) #endif -#define FAIL(m) { regerror(m); return(NULL); } -#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') +#define FAIL(m) { regerror(m); return(NULL); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?') /* * Flags to be passed up and down. */ -#define HASWIDTH 01 /* Known never to match null string. */ -#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ -#define SPSTART 04 /* Starts with * or +. */ -#define WORST 0 /* Worst case. */ +#define HASWIDTH 01 /* Known never to match null string. */ +#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +#define SPSTART 04 /* Starts with * or +. */ +#define WORST 0 /* Worst case. */ /* * Global work variables for regcomp(). */ -static char *regparse; /* Input-scan pointer. */ -static int regnpar; /* () count. */ +static char *regparse; /* Input-scan pointer. */ +static int regnpar; /* () count. */ static char regdummy; -static char *regcode; /* Code-emit pointer; ®dummy = don't. */ -static long regsize; /* Code size. */ +static char *regcode; /* Code-emit pointer; ®dummy = don't. */ +static long regsize; /* Code size. */ /* * Forward declarations for regcomp()'s friends. */ #ifndef STATIC -#define STATIC static +#define STATIC static #endif STATIC char *reg( int paren, int *flagp ); STATIC char *regbranch( int *flagp ); @@ -213,81 +215,81 @@ STATIC int strcspn(); regexp * regcomp( char *exp ) { - register regexp *r; - register char *scan; - register char *longest; - register unsigned len; - int flags; + register regexp *r; + register char *scan; + register char *longest; + register unsigned len; + int flags; - if (exp == NULL) - FAIL("NULL argument"); + if (exp == NULL) + FAIL("NULL argument"); - /* First pass: determine size, legality. */ + /* First pass: determine size, legality. */ #ifdef notdef - if (exp[0] == '.' && exp[1] == '*') exp += 2; /* aid grep */ + if (exp[0] == '.' && exp[1] == '*') exp += 2; /* aid grep */ #endif - regparse = (char *)exp; - regnpar = 1; - regsize = 0L; - regcode = ®dummy; - regc(MAGIC); - if (reg(0, &flags) == NULL) - return(NULL); + regparse = (char *)exp; + regnpar = 1; + regsize = 0L; + regcode = ®dummy; + regc(MAGIC); + if (reg(0, &flags) == NULL) + return(NULL); - /* Small enough for pointer-storage convention? */ - if (regsize >= 32767L) /* Probably could be 65535L. */ - FAIL("regexp too big"); + /* Small enough for pointer-storage convention? */ + if (regsize >= 32767L) /* Probably could be 65535L. */ + FAIL("regexp too big"); - /* Allocate space. */ - r = (regexp *)BJAM_MALLOC(sizeof(regexp) + (unsigned)regsize); - if (r == NULL) - FAIL("out of space"); + /* Allocate space. */ + r = (regexp *)BJAM_MALLOC(sizeof(regexp) + (unsigned)regsize); + if (r == NULL) + FAIL("out of space"); - /* Second pass: emit code. */ - regparse = (char *)exp; - regnpar = 1; - regcode = r->program; - regc(MAGIC); - if (reg(0, &flags) == NULL) - return(NULL); + /* Second pass: emit code. */ + regparse = (char *)exp; + regnpar = 1; + regcode = r->program; + regc(MAGIC); + if (reg(0, &flags) == NULL) + return(NULL); - /* Dig out information for optimizations. */ - r->regstart = '\0'; /* Worst-case defaults. */ - r->reganch = 0; - r->regmust = NULL; - r->regmlen = 0; - scan = r->program+1; /* First BRANCH. */ - if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ - scan = OPERAND(scan); + /* Dig out information for optimizations. */ + r->regstart = '\0'; /* Worst-case defaults. */ + r->reganch = 0; + r->regmust = NULL; + r->regmlen = 0; + scan = r->program+1; /* First BRANCH. */ + if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ + scan = OPERAND(scan); - /* Starting-point info. */ - if (OP(scan) == EXACTLY) - r->regstart = *OPERAND(scan); - else if (OP(scan) == BOL) - r->reganch++; + /* Starting-point info. */ + if (OP(scan) == EXACTLY) + r->regstart = *OPERAND(scan); + else if (OP(scan) == BOL) + r->reganch++; - /* - * If there's something expensive in the r.e., find the - * longest literal string that must appear and make it the - * regmust. Resolve ties in favor of later strings, since - * the regstart check works with the beginning of the r.e. - * and avoiding duplication strengthens checking. Not a - * strong reason, but sufficient in the absence of others. - */ - if (flags&SPSTART) { - longest = NULL; - len = 0; - for (; scan != NULL; scan = regnext(scan)) - if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { - longest = OPERAND(scan); - len = strlen(OPERAND(scan)); - } - r->regmust = longest; - r->regmlen = len; - } - } + /* + * If there's something expensive in the r.e., find the + * longest literal string that must appear and make it the + * regmust. Resolve ties in favor of later strings, since + * the regstart check works with the beginning of the r.e. + * and avoiding duplication strengthens checking. Not a + * strong reason, but sufficient in the absence of others. + */ + if (flags&SPSTART) { + longest = NULL; + len = 0; + for (; scan != NULL; scan = regnext(scan)) + if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) { + longest = OPERAND(scan); + len = strlen(OPERAND(scan)); + } + r->regmust = longest; + r->regmlen = len; + } + } - return(r); + return(r); } /* @@ -301,69 +303,69 @@ regcomp( char *exp ) */ static char * reg( - int paren, /* Parenthesized? */ - int *flagp ) + int paren, /* Parenthesized? */ + int *flagp ) { - register char *ret; - register char *br; - register char *ender; - register int parno; - int flags; + register char *ret; + register char *br; + register char *ender; + register int parno = 0; + int flags; - *flagp = HASWIDTH; /* Tentatively. */ + *flagp = HASWIDTH; /* Tentatively. */ - /* Make an OPEN node, if parenthesized. */ - if (paren) { - if (regnpar >= NSUBEXP) - FAIL("too many ()"); - parno = regnpar; - regnpar++; - ret = regnode(OPEN+parno); - } else - ret = NULL; + /* Make an OPEN node, if parenthesized. */ + if (paren) { + if (regnpar >= NSUBEXP) + FAIL("too many ()"); + parno = regnpar; + regnpar++; + ret = regnode(OPEN+parno); + } else + ret = NULL; - /* Pick up the branches, linking them together. */ - br = regbranch(&flags); - if (br == NULL) - return(NULL); - if (ret != NULL) - regtail(ret, br); /* OPEN -> first. */ - else - ret = br; - if (!(flags&HASWIDTH)) - *flagp &= ~HASWIDTH; - *flagp |= flags&SPSTART; - while (*regparse == '|' || *regparse == '\n') { - regparse++; - br = regbranch(&flags); - if (br == NULL) - return(NULL); - regtail(ret, br); /* BRANCH -> BRANCH. */ - if (!(flags&HASWIDTH)) - *flagp &= ~HASWIDTH; - *flagp |= flags&SPSTART; - } + /* Pick up the branches, linking them together. */ + br = regbranch(&flags); + if (br == NULL) + return(NULL); + if (ret != NULL) + regtail(ret, br); /* OPEN -> first. */ + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*regparse == '|' || *regparse == '\n') { + regparse++; + br = regbranch(&flags); + if (br == NULL) + return(NULL); + regtail(ret, br); /* BRANCH -> BRANCH. */ + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } - /* Make a closing node, and hook it on the end. */ - ender = regnode((paren) ? CLOSE+parno : END); - regtail(ret, ender); + /* Make a closing node, and hook it on the end. */ + ender = regnode((paren) ? CLOSE+parno : END); + regtail(ret, ender); - /* Hook the tails of the branches to the closing node. */ - for (br = ret; br != NULL; br = regnext(br)) - regoptail(br, ender); + /* Hook the tails of the branches to the closing node. */ + for (br = ret; br != NULL; br = regnext(br)) + regoptail(br, ender); - /* Check for proper termination. */ - if (paren && *regparse++ != ')') { - FAIL("unmatched ()"); - } else if (!paren && *regparse != '\0') { - if (*regparse == ')') { - FAIL("unmatched ()"); - } else - FAIL("junk on end"); /* "Can't happen". */ - /* NOTREACHED */ - } + /* Check for proper termination. */ + if (paren && *regparse++ != ')') { + FAIL("unmatched ()"); + } else if (!paren && *regparse != '\0') { + if (*regparse == ')') { + FAIL("unmatched ()"); + } else + FAIL("junk on end"); /* "Can't happen". */ + /* NOTREACHED */ + } - return(ret); + return(ret); } /* @@ -374,31 +376,31 @@ reg( static char * regbranch( int *flagp ) { - register char *ret; - register char *chain; - register char *latest; - int flags; + register char *ret; + register char *chain; + register char *latest; + int flags; - *flagp = WORST; /* Tentatively. */ + *flagp = WORST; /* Tentatively. */ - ret = regnode(BRANCH); - chain = NULL; - while (*regparse != '\0' && *regparse != ')' && - *regparse != '\n' && *regparse != '|') { - latest = regpiece(&flags); - if (latest == NULL) - return(NULL); - *flagp |= flags&HASWIDTH; - if (chain == NULL) /* First piece. */ - *flagp |= flags&SPSTART; - else - regtail(chain, latest); - chain = latest; - } - if (chain == NULL) /* Loop ran zero times. */ - (void) regnode(NOTHING); + ret = regnode(BRANCH); + chain = NULL; + while (*regparse != '\0' && *regparse != ')' && + *regparse != '\n' && *regparse != '|') { + latest = regpiece(&flags); + if (latest == NULL) + return(NULL); + *flagp |= flags&HASWIDTH; + if (chain == NULL) /* First piece. */ + *flagp |= flags&SPSTART; + else + regtail(chain, latest); + chain = latest; + } + if (chain == NULL) /* Loop ran zero times. */ + (void) regnode(NOTHING); - return(ret); + return(ret); } /* @@ -413,56 +415,56 @@ regbranch( int *flagp ) static char * regpiece( int *flagp ) { - register char *ret; - register char op; - register char *next; - int flags; + register char *ret; + register char op; + register char *next; + int flags; - ret = regatom(&flags); - if (ret == NULL) - return(NULL); + ret = regatom(&flags); + if (ret == NULL) + return(NULL); - op = *regparse; - if (!ISMULT(op)) { - *flagp = flags; - return(ret); - } + op = *regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } - if (!(flags&HASWIDTH) && op != '?') - FAIL("*+ operand could be empty"); - *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); + if (!(flags&HASWIDTH) && op != '?') + FAIL("*+ operand could be empty"); + *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH); - if (op == '*' && (flags&SIMPLE)) - reginsert(STAR, ret); - else if (op == '*') { - /* Emit x* as (x&|), where & means "self". */ - reginsert(BRANCH, ret); /* Either x */ - regoptail(ret, regnode(BACK)); /* and loop */ - regoptail(ret, ret); /* back */ - regtail(ret, regnode(BRANCH)); /* or */ - regtail(ret, regnode(NOTHING)); /* null. */ - } else if (op == '+' && (flags&SIMPLE)) - reginsert(PLUS, ret); - else if (op == '+') { - /* Emit x+ as x(&|), where & means "self". */ - next = regnode(BRANCH); /* Either */ - regtail(ret, next); - regtail(regnode(BACK), ret); /* loop back */ - regtail(next, regnode(BRANCH)); /* or */ - regtail(ret, regnode(NOTHING)); /* null. */ - } else if (op == '?') { - /* Emit x? as (x|) */ - reginsert(BRANCH, ret); /* Either x */ - regtail(ret, regnode(BRANCH)); /* or */ - next = regnode(NOTHING); /* null. */ - regtail(ret, next); - regoptail(ret, next); - } - regparse++; - if (ISMULT(*regparse)) - FAIL("nested *?+"); + if (op == '*' && (flags&SIMPLE)) + reginsert(STAR, ret); + else if (op == '*') { + /* Emit x* as (x&|), where & means "self". */ + reginsert(BRANCH, ret); /* Either x */ + regoptail(ret, regnode(BACK)); /* and loop */ + regoptail(ret, ret); /* back */ + regtail(ret, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '+' && (flags&SIMPLE)) + reginsert(PLUS, ret); + else if (op == '+') { + /* Emit x+ as x(&|), where & means "self". */ + next = regnode(BRANCH); /* Either */ + regtail(ret, next); + regtail(regnode(BACK), ret); /* loop back */ + regtail(next, regnode(BRANCH)); /* or */ + regtail(ret, regnode(NOTHING)); /* null. */ + } else if (op == '?') { + /* Emit x? as (x|) */ + reginsert(BRANCH, ret); /* Either x */ + regtail(ret, regnode(BRANCH)); /* or */ + next = regnode(NOTHING); /* null. */ + regtail(ret, next); + regoptail(ret, next); + } + regparse++; + if (ISMULT(*regparse)) + FAIL("nested *?+"); - return(ret); + return(ret); } /* @@ -476,199 +478,199 @@ regpiece( int *flagp ) static char * regatom( int *flagp ) { - register char *ret; - int flags; + register char *ret; + int flags; - *flagp = WORST; /* Tentatively. */ + *flagp = WORST; /* Tentatively. */ - switch (*regparse++) { - /* FIXME: these chars only have meaning at beg/end of pat? */ - case '^': - ret = regnode(BOL); - break; - case '$': - ret = regnode(EOL); - break; - case '.': - ret = regnode(ANY); - *flagp |= HASWIDTH|SIMPLE; - break; - case '[': { - register int classr; - register int classend; + switch (*regparse++) { + /* FIXME: these chars only have meaning at beg/end of pat? */ + case '^': + ret = regnode(BOL); + break; + case '$': + ret = regnode(EOL); + break; + case '.': + ret = regnode(ANY); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + register int classr; + register int classend; - if (*regparse == '^') { /* Complement of range. */ - ret = regnode(ANYBUT); - regparse++; - } else - ret = regnode(ANYOF); - if (*regparse == ']' || *regparse == '-') - regc(*regparse++); - while (*regparse != '\0' && *regparse != ']') { - if (*regparse == '-') { - regparse++; - if (*regparse == ']' || *regparse == '\0') - regc('-'); - else { - classr = UCHARAT(regparse-2)+1; - classend = UCHARAT(regparse); - if (classr > classend+1) - FAIL("invalid [] range"); - for (; classr <= classend; classr++) - regc(classr); - regparse++; - } - } else - regc(*regparse++); - } - regc('\0'); - if (*regparse != ']') - FAIL("unmatched []"); - regparse++; - *flagp |= HASWIDTH|SIMPLE; - } - break; - case '(': - ret = reg(1, &flags); - if (ret == NULL) - return(NULL); - *flagp |= flags&(HASWIDTH|SPSTART); - break; - case '\0': - case '|': - case '\n': - case ')': - FAIL("internal urp"); /* Supposed to be caught earlier. */ - break; - case '?': - case '+': - case '*': - FAIL("?+* follows nothing"); - break; - case '\\': - switch (*regparse++) { - case '\0': - FAIL("trailing \\"); - break; - case '<': - ret = regnode(WORDA); - break; - case '>': - ret = regnode(WORDZ); - break; - /* FIXME: Someday handle \1, \2, ... */ - default: - /* Handle general quoted chars in exact-match routine */ - goto de_fault; - } - break; - de_fault: - default: - /* - * Encode a string of characters to be matched exactly. - * - * This is a bit tricky due to quoted chars and due to - * '*', '+', and '?' taking the SINGLE char previous - * as their operand. - * - * On entry, the char at regparse[-1] is going to go - * into the string, no matter what it is. (It could be - * following a \ if we are entered from the '\' case.) - * - * Basic idea is to pick up a good char in ch and - * examine the next char. If it's *+? then we twiddle. - * If it's \ then we frozzle. If it's other magic char - * we push ch and terminate the string. If none of the - * above, we push ch on the string and go around again. - * - * regprev is used to remember where "the current char" - * starts in the string, if due to a *+? we need to back - * up and put the current char in a separate, 1-char, string. - * When regprev is NULL, ch is the only char in the - * string; this is used in *+? handling, and in setting - * flags |= SIMPLE at the end. - */ - { - char *regprev; - register char ch; + if (*regparse == '^') { /* Complement of range. */ + ret = regnode(ANYBUT); + regparse++; + } else + ret = regnode(ANYOF); + if (*regparse == ']' || *regparse == '-') + regc(*regparse++); + while (*regparse != '\0' && *regparse != ']') { + if (*regparse == '-') { + regparse++; + if (*regparse == ']' || *regparse == '\0') + regc('-'); + else { + classr = UCHARAT(regparse-2)+1; + classend = UCHARAT(regparse); + if (classr > classend+1) + FAIL("invalid [] range"); + for (; classr <= classend; classr++) + regc(classr); + regparse++; + } + } else + regc(*regparse++); + } + regc('\0'); + if (*regparse != ']') + FAIL("unmatched []"); + regparse++; + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(1, &flags); + if (ret == NULL) + return(NULL); + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case '\n': + case ')': + FAIL("internal urp"); /* Supposed to be caught earlier. */ + break; + case '?': + case '+': + case '*': + FAIL("?+* follows nothing"); + break; + case '\\': + switch (*regparse++) { + case '\0': + FAIL("trailing \\"); + break; + case '<': + ret = regnode(WORDA); + break; + case '>': + ret = regnode(WORDZ); + break; + /* FIXME: Someday handle \1, \2, ... */ + default: + /* Handle general quoted chars in exact-match routine */ + goto de_fault; + } + break; + de_fault: + default: + /* + * Encode a string of characters to be matched exactly. + * + * This is a bit tricky due to quoted chars and due to + * '*', '+', and '?' taking the SINGLE char previous + * as their operand. + * + * On entry, the char at regparse[-1] is going to go + * into the string, no matter what it is. (It could be + * following a \ if we are entered from the '\' case.) + * + * Basic idea is to pick up a good char in ch and + * examine the next char. If it's *+? then we twiddle. + * If it's \ then we frozzle. If it's other magic char + * we push ch and terminate the string. If none of the + * above, we push ch on the string and go around again. + * + * regprev is used to remember where "the current char" + * starts in the string, if due to a *+? we need to back + * up and put the current char in a separate, 1-char, string. + * When regprev is NULL, ch is the only char in the + * string; this is used in *+? handling, and in setting + * flags |= SIMPLE at the end. + */ + { + char *regprev; + register char ch; - regparse--; /* Look at cur char */ - ret = regnode(EXACTLY); - for ( regprev = 0 ; ; ) { - ch = *regparse++; /* Get current char */ - switch (*regparse) { /* look at next one */ + regparse--; /* Look at cur char */ + ret = regnode(EXACTLY); + for ( regprev = 0 ; ; ) { + ch = *regparse++; /* Get current char */ + switch (*regparse) { /* look at next one */ - default: - regc(ch); /* Add cur to string */ - break; + default: + regc(ch); /* Add cur to string */ + break; - case '.': case '[': case '(': - case ')': case '|': case '\n': - case '$': case '^': - case '\0': - /* FIXME, $ and ^ should not always be magic */ - magic: - regc(ch); /* dump cur char */ - goto done; /* and we are done */ + case '.': case '[': case '(': + case ')': case '|': case '\n': + case '$': case '^': + case '\0': + /* FIXME, $ and ^ should not always be magic */ + magic: + regc(ch); /* dump cur char */ + goto done; /* and we are done */ - case '?': case '+': case '*': - if (!regprev) /* If just ch in str, */ - goto magic; /* use it */ - /* End mult-char string one early */ - regparse = regprev; /* Back up parse */ - goto done; + case '?': case '+': case '*': + if (!regprev) /* If just ch in str, */ + goto magic; /* use it */ + /* End mult-char string one early */ + regparse = regprev; /* Back up parse */ + goto done; - case '\\': - regc(ch); /* Cur char OK */ - switch (regparse[1]){ /* Look after \ */ - case '\0': - case '<': - case '>': - /* FIXME: Someday handle \1, \2, ... */ - goto done; /* Not quoted */ - default: - /* Backup point is \, scan * point is after it. */ - regprev = regparse; - regparse++; - continue; /* NOT break; */ - } - } - regprev = regparse; /* Set backup point */ - } - done: - regc('\0'); - *flagp |= HASWIDTH; - if (!regprev) /* One char? */ - *flagp |= SIMPLE; - } - break; - } + case '\\': + regc(ch); /* Cur char OK */ + switch (regparse[1]){ /* Look after \ */ + case '\0': + case '<': + case '>': + /* FIXME: Someday handle \1, \2, ... */ + goto done; /* Not quoted */ + default: + /* Backup point is \, scan * point is after it. */ + regprev = regparse; + regparse++; + continue; /* NOT break; */ + } + } + regprev = regparse; /* Set backup point */ + } + done: + regc('\0'); + *flagp |= HASWIDTH; + if (!regprev) /* One char? */ + *flagp |= SIMPLE; + } + break; + } - return(ret); + return(ret); } /* - regnode - emit a node */ -static char * /* Location. */ +static char * /* Location. */ regnode( int op ) { - register char *ret; - register char *ptr; + register char *ret; + register char *ptr; - ret = regcode; - if (ret == ®dummy) { - regsize += 3; - return(ret); - } + ret = regcode; + if (ret == ®dummy) { + regsize += 3; + return(ret); + } - ptr = ret; - *ptr++ = op; - *ptr++ = '\0'; /* Null "next" pointer. */ - *ptr++ = '\0'; - regcode = ptr; + ptr = ret; + *ptr++ = op; + *ptr++ = '\0'; /* Null "next" pointer. */ + *ptr++ = '\0'; + regcode = ptr; - return(ret); + return(ret); } /* @@ -677,10 +679,10 @@ regnode( int op ) static void regc( int b ) { - if (regcode != ®dummy) - *regcode++ = b; - else - regsize++; + if (regcode != ®dummy) + *regcode++ = b; + else + regsize++; } /* @@ -690,28 +692,28 @@ regc( int b ) */ static void reginsert( - char op, - char *opnd ) + char op, + char *opnd ) { - register char *src; - register char *dst; - register char *place; + register char *src; + register char *dst; + register char *place; - if (regcode == ®dummy) { - regsize += 3; - return; - } + if (regcode == ®dummy) { + regsize += 3; + return; + } - src = regcode; - regcode += 3; - dst = regcode; - while (src > opnd) - *--dst = *--src; + src = regcode; + regcode += 3; + dst = regcode; + while (src > opnd) + *--dst = *--src; - place = opnd; /* Op node, where operand used to be. */ - *place++ = op; - *place++ = '\0'; - *place++ = '\0'; + place = opnd; /* Op node, where operand used to be. */ + *place++ = op; + *place++ = '\0'; + *place++ = '\0'; } /* @@ -719,31 +721,31 @@ reginsert( */ static void regtail( - char *p, - char *val ) + char *p, + char *val ) { - register char *scan; - register char *temp; - register int offset; + register char *scan; + register char *temp; + register int offset; - if (p == ®dummy) - return; + if (p == ®dummy) + return; - /* Find last node. */ - scan = p; - for (;;) { - temp = regnext(scan); - if (temp == NULL) - break; - scan = temp; - } + /* Find last node. */ + scan = p; + for (;;) { + temp = regnext(scan); + if (temp == NULL) + break; + scan = temp; + } - if (OP(scan) == BACK) - offset = scan - val; - else - offset = val - scan; - *(scan+1) = (offset>>8)&0377; - *(scan+2) = offset&0377; + if (OP(scan) == BACK) + offset = scan - val; + else + offset = val - scan; + *(scan+1) = (offset>>8)&0377; + *(scan+2) = offset&0377; } /* @@ -752,13 +754,13 @@ regtail( static void regoptail( - char *p, - char *val ) + char *p, + char *val ) { - /* "Operandless" and "op != BRANCH" are synonymous in practice. */ - if (p == NULL || p == ®dummy || OP(p) != BRANCH) - return; - regtail(OPERAND(p), val); + /* "Operandless" and "op != BRANCH" are synonymous in practice. */ + if (p == NULL || p == ®dummy || OP(p) != BRANCH) + return; + regtail(OPERAND(p), val); } /* @@ -768,10 +770,10 @@ regoptail( /* * Global work variables for regexec(). */ -static char *reginput; /* String-input pointer. */ -static char *regbol; /* Beginning of input, for ^ check. */ -static char **regstartp; /* Pointer to startp array. */ -static char **regendp; /* Ditto for endp. */ +static char *reginput; /* String-input pointer. */ +static char *regbol; /* Beginning of input, for ^ check. */ +static char **regstartp; /* Pointer to startp array. */ +static char **regendp; /* Ditto for endp. */ /* * Forwards. @@ -791,298 +793,306 @@ STATIC char *regprop(); */ int regexec( - register regexp *prog, - register char *string ) + register regexp *prog, + register char *string ) { - register char *s; + register char *s; - /* Be paranoid... */ - if (prog == NULL || string == NULL) { - regerror("NULL parameter"); - return(0); - } + /* Be paranoid... */ + if (prog == NULL || string == NULL) { + regerror("NULL parameter"); + return(0); + } - /* Check validity of program. */ - if (UCHARAT(prog->program) != MAGIC) { - regerror("corrupted program"); - return(0); - } + /* Check validity of program. */ + if (UCHARAT(prog->program) != MAGIC) { + regerror("corrupted program"); + return(0); + } - /* If there is a "must appear" string, look for it. */ - if (prog->regmust != NULL) { - s = (char *)string; - while ((s = strchr(s, prog->regmust[0])) != NULL) { - if (strncmp(s, prog->regmust, prog->regmlen) == 0) - break; /* Found it. */ - s++; - } - if (s == NULL) /* Not present. */ - return(0); - } + /* If there is a "must appear" string, look for it. */ + if ( prog->regmust != NULL ) + { + s = (char *)string; + while ( ( s = strchr( s, prog->regmust[ 0 ] ) ) != NULL ) + { + if ( !strncmp( s, prog->regmust, prog->regmlen ) ) + break; /* Found it. */ + ++s; + } + if ( s == NULL ) /* Not present. */ + return 0; + } - /* Mark beginning of line for ^ . */ - regbol = (char *)string; + /* Mark beginning of line for ^ . */ + regbol = (char *)string; - /* Simplest case: anchored match need be tried only once. */ - if (prog->reganch) - return(regtry(prog, string)); + /* Simplest case: anchored match need be tried only once. */ + if ( prog->reganch ) + return regtry( prog, string ); - /* Messy cases: unanchored match. */ - s = (char *)string; - if (prog->regstart != '\0') - /* We know what char it must start with. */ - while ((s = strchr(s, prog->regstart)) != NULL) { - if (regtry(prog, s)) - return(1); - s++; - } - else - /* We don't -- general case. */ - do { - if (regtry(prog, s)) - return(1); - } while (*s++ != '\0'); + /* Messy cases: unanchored match. */ + s = (char *)string; + if (prog->regstart != '\0') + /* We know what char it must start with. */ + while ((s = strchr(s, prog->regstart)) != NULL) { + if (regtry(prog, s)) + return(1); + s++; + } + else + /* We do not -- general case. */ + do { + if ( regtry( prog, s ) ) + return( 1 ); + } while ( *s++ != '\0' ); - /* Failure. */ - return(0); + /* Failure. */ + return 0; } + /* - - regtry - try match at specific point + * regtry() - try match at specific point. */ -static int /* 0 failure, 1 success */ + +static int /* 0 failure, 1 success */ regtry( - regexp *prog, - char *string ) + regexp *prog, + char *string ) { - register int i; - register char **sp; - register char **ep; + register int i; + register char * * sp; + register char * * ep; - reginput = string; - regstartp = prog->startp; - regendp = prog->endp; + reginput = string; + regstartp = prog->startp; + regendp = prog->endp; - sp = prog->startp; - ep = prog->endp; - for (i = NSUBEXP; i > 0; i--) { - *sp++ = NULL; - *ep++ = NULL; - } - if (regmatch(prog->program + 1)) { - prog->startp[0] = string; - prog->endp[0] = reginput; - return(1); - } else - return(0); + sp = prog->startp; + ep = prog->endp; + for ( i = NSUBEXP; i > 0; --i ) + { + *sp++ = NULL; + *ep++ = NULL; + } + if ( regmatch( prog->program + 1 ) ) + { + prog->startp[ 0 ] = string; + prog->endp[ 0 ] = reginput; + return 1; + } + else + return 0; } + /* - - regmatch - main matching routine + * regmatch() - main matching routine. * - * Conceptually the strategy is simple: check to see whether the current - * node matches, call self recursively to see whether the rest matches, - * and then act accordingly. In practice we make some effort to avoid - * recursion, in particular by going through "ordinary" nodes (that don't - * need to know whether the rest of the match failed) by a loop instead of - * by recursion. + * Conceptually the strategy is simple: check to see whether the current node + * matches, call self recursively to see whether the rest matches, and then act + * accordingly. In practice we make some effort to avoid recursion, in + * particular by going through "ordinary" nodes (that do not need to know + * whether the rest of the match failed) by a loop instead of by recursion. */ -static int /* 0 failure, 1 success */ -regmatch( char *prog ) + +static int /* 0 failure, 1 success */ +regmatch( char * prog ) { - register char *scan; /* Current node. */ - char *next; /* Next node. */ + char * scan; /* Current node. */ + char * next; /* Next node. */ - scan = prog; + scan = prog; #ifdef DEBUG - if (scan != NULL && regnarrate) - fprintf(stderr, "%s(\n", regprop(scan)); + if (scan != NULL && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); #endif - while (scan != NULL) { + while (scan != NULL) { #ifdef DEBUG - if (regnarrate) - fprintf(stderr, "%s...\n", regprop(scan)); + if (regnarrate) + fprintf(stderr, "%s...\n", regprop(scan)); #endif - next = regnext(scan); + next = regnext(scan); - switch (OP(scan)) { - case BOL: - if (reginput != regbol) - return(0); - break; - case EOL: - if (*reginput != '\0') - return(0); - break; - case WORDA: - /* Must be looking at a letter, digit, or _ */ - if ((!isalnum(*reginput)) && *reginput != '_') - return(0); - /* Prev must be BOL or nonword */ - if (reginput > regbol && - (isalnum(reginput[-1]) || reginput[-1] == '_')) - return(0); - break; - case WORDZ: - /* Must be looking at non letter, digit, or _ */ - if (isalnum(*reginput) || *reginput == '_') - return(0); - /* We don't care what the previous char was */ - break; - case ANY: - if (*reginput == '\0') - return(0); - reginput++; - break; - case EXACTLY: { - register int len; - register char *opnd; + switch (OP(scan)) { + case BOL: + if (reginput != regbol) + return(0); + break; + case EOL: + if (*reginput != '\0') + return(0); + break; + case WORDA: + /* Must be looking at a letter, digit, or _ */ + if ((!isalnum(*reginput)) && *reginput != '_') + return(0); + /* Prev must be BOL or nonword */ + if (reginput > regbol && + (isalnum(reginput[-1]) || reginput[-1] == '_')) + return(0); + break; + case WORDZ: + /* Must be looking at non letter, digit, or _ */ + if (isalnum(*reginput) || *reginput == '_') + return(0); + /* We don't care what the previous char was */ + break; + case ANY: + if (*reginput == '\0') + return(0); + reginput++; + break; + case EXACTLY: { + register int len; + register char *opnd; - opnd = OPERAND(scan); - /* Inline the first character, for speed. */ - if (*opnd != *reginput) - return(0); - len = strlen(opnd); - if (len > 1 && strncmp(opnd, reginput, len) != 0) - return(0); - reginput += len; - } - break; - case ANYOF: - if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) - return(0); - reginput++; - break; - case ANYBUT: - if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) - return(0); - reginput++; - break; - case NOTHING: - break; - case BACK: - break; - case OPEN+1: - case OPEN+2: - case OPEN+3: - case OPEN+4: - case OPEN+5: - case OPEN+6: - case OPEN+7: - case OPEN+8: - case OPEN+9: { - register int no; - register char *save; + opnd = OPERAND(scan); + /* Inline the first character, for speed. */ + if (*opnd != *reginput) + return(0); + len = strlen(opnd); + if (len > 1 && strncmp(opnd, reginput, len) != 0) + return(0); + reginput += len; + } + break; + case ANYOF: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL) + return(0); + reginput++; + break; + case ANYBUT: + if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL) + return(0); + reginput++; + break; + case NOTHING: + break; + case BACK: + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: { + register int no; + register char *save; - no = OP(scan) - OPEN; - save = reginput; + no = OP(scan) - OPEN; + save = reginput; - if (regmatch(next)) { - /* - * Don't set startp if some later - * invocation of the same parentheses - * already has. - */ - if (regstartp[no] == NULL) - regstartp[no] = save; - return(1); - } else - return(0); - } - break; - case CLOSE+1: - case CLOSE+2: - case CLOSE+3: - case CLOSE+4: - case CLOSE+5: - case CLOSE+6: - case CLOSE+7: - case CLOSE+8: - case CLOSE+9: { - register int no; - register char *save; + if (regmatch(next)) { + /* + * Don't set startp if some later + * invocation of the same parentheses + * already has. + */ + if (regstartp[no] == NULL) + regstartp[no] = save; + return(1); + } else + return(0); + } + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: { + register int no; + register char *save; - no = OP(scan) - CLOSE; - save = reginput; + no = OP(scan) - CLOSE; + save = reginput; - if (regmatch(next)) { - /* - * Don't set endp if some later - * invocation of the same parentheses - * already has. - */ - if (regendp[no] == NULL) - regendp[no] = save; - return(1); - } else - return(0); - } - break; - case BRANCH: { - register char *save; + if (regmatch(next)) { + /* + * Don't set endp if some later + * invocation of the same parentheses + * already has. + */ + if (regendp[no] == NULL) + regendp[no] = save; + return(1); + } else + return(0); + } + break; + case BRANCH: { + register char *save; - if (OP(next) != BRANCH) /* No choice. */ - next = OPERAND(scan); /* Avoid recursion. */ - else { - do { - save = reginput; - if (regmatch(OPERAND(scan))) - return(1); - reginput = save; - scan = regnext(scan); - } while (scan != NULL && OP(scan) == BRANCH); - return(0); - /* NOTREACHED */ - } - } - break; - case STAR: - case PLUS: { - register char nextch; - register int no; - register char *save; - register int min; + if (OP(next) != BRANCH) /* No choice. */ + next = OPERAND(scan); /* Avoid recursion. */ + else { + do { + save = reginput; + if (regmatch(OPERAND(scan))) + return(1); + reginput = save; + scan = regnext(scan); + } while (scan != NULL && OP(scan) == BRANCH); + return(0); + /* NOTREACHED */ + } + } + break; + case STAR: + case PLUS: { + register char nextch; + register int no; + register char *save; + register int min; - /* - * Lookahead to avoid useless match attempts - * when we know what character comes next. - */ - nextch = '\0'; - if (OP(next) == EXACTLY) - nextch = *OPERAND(next); - min = (OP(scan) == STAR) ? 0 : 1; - save = reginput; - no = regrepeat(OPERAND(scan)); - while (no >= min) { - /* If it could work, try it. */ - if (nextch == '\0' || *reginput == nextch) - if (regmatch(next)) - return(1); - /* Couldn't or didn't -- back up. */ - no--; - reginput = save + no; - } - return(0); - } - break; - case END: - return(1); /* Success! */ - break; - default: - regerror("memory corruption"); - return(0); - break; - } + /* + * Lookahead to avoid useless match attempts + * when we know what character comes next. + */ + nextch = '\0'; + if (OP(next) == EXACTLY) + nextch = *OPERAND(next); + min = (OP(scan) == STAR) ? 0 : 1; + save = reginput; + no = regrepeat(OPERAND(scan)); + while (no >= min) { + /* If it could work, try it. */ + if (nextch == '\0' || *reginput == nextch) + if (regmatch(next)) + return(1); + /* Couldn't or didn't -- back up. */ + no--; + reginput = save + no; + } + return(0); + } + break; + case END: + return(1); /* Success! */ + break; + default: + regerror("memory corruption"); + return(0); + break; + } - scan = next; - } + scan = next; + } - /* - * We get here only if there's trouble -- normally "case END" is - * the terminating point. - */ - regerror("corrupted pointers"); - return(0); + /* + * We get here only if there's trouble -- normally "case END" is + * the terminating point. + */ + regerror("corrupted pointers"); + return(0); } /* @@ -1091,43 +1101,43 @@ regmatch( char *prog ) static int regrepeat( char *p ) { - register int count = 0; - register char *scan; - register char *opnd; + register int count = 0; + register char *scan; + register char *opnd; - scan = reginput; - opnd = OPERAND(p); - switch (OP(p)) { - case ANY: - count = strlen(scan); - scan += count; - break; - case EXACTLY: - while (*opnd == *scan) { - count++; - scan++; - } - break; - case ANYOF: - while (*scan != '\0' && strchr(opnd, *scan) != NULL) { - count++; - scan++; - } - break; - case ANYBUT: - while (*scan != '\0' && strchr(opnd, *scan) == NULL) { - count++; - scan++; - } - break; - default: /* Oh dear. Called inappropriately. */ - regerror("internal foulup"); - count = 0; /* Best compromise. */ - break; - } - reginput = scan; + scan = reginput; + opnd = OPERAND(p); + switch (OP(p)) { + case ANY: + count = strlen(scan); + scan += count; + break; + case EXACTLY: + while (*opnd == *scan) { + count++; + scan++; + } + break; + case ANYOF: + while (*scan != '\0' && strchr(opnd, *scan) != NULL) { + count++; + scan++; + } + break; + case ANYBUT: + while (*scan != '\0' && strchr(opnd, *scan) == NULL) { + count++; + scan++; + } + break; + default: /* Oh dear. Called inappropriately. */ + regerror("internal foulup"); + count = 0; /* Best compromise. */ + break; + } + reginput = scan; - return(count); + return(count); } /* @@ -1136,19 +1146,19 @@ regrepeat( char *p ) static char * regnext( register char *p ) { - register int offset; + register int offset; - if (p == ®dummy) - return(NULL); + if (p == ®dummy) + return(NULL); - offset = NEXT(p); - if (offset == 0) - return(NULL); + offset = NEXT(p); + if (offset == 0) + return(NULL); - if (OP(p) == BACK) - return(p-offset); - else - return(p+offset); + if (OP(p) == BACK) + return(p-offset); + else + return(p+offset); } #ifdef DEBUG @@ -1161,40 +1171,40 @@ STATIC char *regprop(); void regdump( regexp *r ) { - register char *s; - register char op = EXACTLY; /* Arbitrary non-END op. */ - register char *next; + register char *s; + register char op = EXACTLY; /* Arbitrary non-END op. */ + register char *next; - s = r->program + 1; - while (op != END) { /* While that wasn't END last time... */ - op = OP(s); - printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ - next = regnext(s); - if (next == NULL) /* Next ptr. */ - printf("(0)"); - else - printf("(%d)", (s-r->program)+(next-s)); - s += 3; - if (op == ANYOF || op == ANYBUT || op == EXACTLY) { - /* Literal string, where present. */ - while (*s != '\0') { - putchar(*s); - s++; - } - s++; - } - putchar('\n'); - } + s = r->program + 1; + while (op != END) { /* While that wasn't END last time... */ + op = OP(s); + printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ + next = regnext(s); + if (next == NULL) /* Next ptr. */ + printf("(0)"); + else + printf("(%d)", (s-r->program)+(next-s)); + s += 3; + if (op == ANYOF || op == ANYBUT || op == EXACTLY) { + /* Literal string, where present. */ + while (*s != '\0') { + putchar(*s); + s++; + } + s++; + } + putchar('\n'); + } - /* Header fields of interest. */ - if (r->regstart != '\0') - printf("start `%c' ", r->regstart); - if (r->reganch) - printf("anchored "); - if (r->regmust != NULL) - printf("must have \"%s\"", r->regmust); - printf("\n"); + /* Header fields of interest. */ + if (r->regstart != '\0') + printf("start `%c' ", r->regstart); + if (r->reganch) + printf("anchored "); + if (r->regmust != NULL) + printf("must have \"%s\"", r->regmust); + printf("\n"); } /* @@ -1203,85 +1213,85 @@ regdump( regexp *r ) static char * regprop( char *op ) { - register char *p; - static char buf[50]; + register char *p; + static char buf[50]; - (void) strcpy(buf, ":"); + (void) strcpy(buf, ":"); - switch (OP(op)) { - case BOL: - p = "BOL"; - break; - case EOL: - p = "EOL"; - break; - case ANY: - p = "ANY"; - break; - case ANYOF: - p = "ANYOF"; - break; - case ANYBUT: - p = "ANYBUT"; - break; - case BRANCH: - p = "BRANCH"; - break; - case EXACTLY: - p = "EXACTLY"; - break; - case NOTHING: - p = "NOTHING"; - break; - case BACK: - p = "BACK"; - break; - case END: - p = "END"; - break; - case OPEN+1: - case OPEN+2: - case OPEN+3: - case OPEN+4: - case OPEN+5: - case OPEN+6: - case OPEN+7: - case OPEN+8: - case OPEN+9: - sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); - p = NULL; - break; - case CLOSE+1: - case CLOSE+2: - case CLOSE+3: - case CLOSE+4: - case CLOSE+5: - case CLOSE+6: - case CLOSE+7: - case CLOSE+8: - case CLOSE+9: - sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); - p = NULL; - break; - case STAR: - p = "STAR"; - break; - case PLUS: - p = "PLUS"; - break; - case WORDA: - p = "WORDA"; - break; - case WORDZ: - p = "WORDZ"; - break; - default: - regerror("corrupted opcode"); - break; - } - if (p != NULL) - (void) strcat(buf, p); - return(buf); + switch (OP(op)) { + case BOL: + p = "BOL"; + break; + case EOL: + p = "EOL"; + break; + case ANY: + p = "ANY"; + break; + case ANYOF: + p = "ANYOF"; + break; + case ANYBUT: + p = "ANYBUT"; + break; + case BRANCH: + p = "BRANCH"; + break; + case EXACTLY: + p = "EXACTLY"; + break; + case NOTHING: + p = "NOTHING"; + break; + case BACK: + p = "BACK"; + break; + case END: + p = "END"; + break; + case OPEN+1: + case OPEN+2: + case OPEN+3: + case OPEN+4: + case OPEN+5: + case OPEN+6: + case OPEN+7: + case OPEN+8: + case OPEN+9: + sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN); + p = NULL; + break; + case CLOSE+1: + case CLOSE+2: + case CLOSE+3: + case CLOSE+4: + case CLOSE+5: + case CLOSE+6: + case CLOSE+7: + case CLOSE+8: + case CLOSE+9: + sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE); + p = NULL; + break; + case STAR: + p = "STAR"; + break; + case PLUS: + p = "PLUS"; + break; + case WORDA: + p = "WORDA"; + break; + case WORDZ: + p = "WORDZ"; + break; + default: + regerror("corrupted opcode"); + break; + } + if (p != NULL) + (void) strcat(buf, p); + return(buf); } #endif @@ -1299,20 +1309,20 @@ regprop( char *op ) static int strcspn( - char *s1, - char *s2 ) + char *s1, + char *s2 ) { - register char *scan1; - register char *scan2; - register int count; + register char *scan1; + register char *scan2; + register int count; - count = 0; - for (scan1 = s1; *scan1 != '\0'; scan1++) { - for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ - if (*scan1 == *scan2++) - return(count); - count++; - } - return(count); + count = 0; + for (scan1 = s1; *scan1 != '\0'; scan1++) { + for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */ + if (*scan1 == *scan2++) + return(count); + count++; + } + return(count); } #endif diff --git a/src/engine/regexp.h b/src/engine/regexp.h index b0fac0a04..9d4604f60 100644 --- a/src/engine/regexp.h +++ b/src/engine/regexp.h @@ -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 diff --git a/src/engine/rules.c b/src/engine/rules.c index 40d54b53f..3d1a3a86e 100644 --- a/src/engine/rules.c +++ b/src/engine/rules.c @@ -28,54 +28,71 @@ * * External routines: * - * bindrule() - return pointer to RULE, creating it if necessary - * bindtarget() - return pointer to TARGET, creating it if necessary - * touchtarget() - mark a target to simulate being new - * targetlist() - turn list of target names into a TARGET chain - * targetentry() - add a TARGET to a chain of TARGETS - * actionlist() - append to an ACTION chain - * addsettings() - add a deferred "set" command to a target -#ifndef OPT_FIX_TARGET_VARIABLES_EXT - * usesettings() - set all target specific variables -#endif - * pushsettings() - set all target specific variables - * popsettings() - reset target specific variables to their pre-push values - * freesettings() - delete a settings list - * donerules() - free RULE and TARGET tables + * bindrule() - return pointer to RULE, creating it if necessary. + * bindtarget() - return pointer to TARGET, creating it if necessary. + * touch_target() - mark a target to simulate being new. + * targetlist() - turn list of target names into a TARGET chain. + * targetentry() - add a TARGET to a chain of TARGETS. + * actionlist() - append to an ACTION chain. + * addsettings() - add a deferred "set" command to a target. + * pushsettings() - set all target specific variables. + * popsettings() - reset target specific variables to their pre-push values. + * freesettings() - delete a settings list. + * rules_done() - free RULE and TARGET tables. * * 04/12/94 (seiwald) - actionlist() now just appends a single action. * 08/23/94 (seiwald) - Support for '+=' (append to variable) */ -static void set_rule_actions( RULE* rule, rule_actions* actions ); -static void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure ); -static struct hash *targethash = 0; +static void set_rule_actions( RULE *, rule_actions * ); +static void set_rule_body ( RULE *, argument_list *, PARSE * procedure ); +static struct hash * targethash = 0; + +struct _located_target +{ + char * file_name; + TARGET * target; +}; typedef struct _located_target LOCATED_TARGET ; -struct _located_target { - char* file_name; - TARGET* target; -}; -static struct hash *located_targets = 0; +static struct hash * located_targets = 0; - +/* + * target_include() - adds the 'included' TARGET to the list of targets included + * by the 'including' TARGET. Such targets are modeled as dependencies of the + * internal include node belonging to the 'including' TARGET. + */ + +void target_include( TARGET * including, TARGET * included ) +{ + TARGET * internal; + if ( !including->includes ) + { + including->includes = copytarget( including ); + including->includes->original_target = including; + } + internal = including->includes; + internal->depends = targetentry( internal->depends, included ); +} + /* * enter_rule() - return pointer to RULE, creating it if necessary in * target_module. */ -static RULE * -enter_rule( char *rulename, module_t *target_module ) + +static RULE * enter_rule( char * rulename, module_t * target_module ) { - RULE rule, *r = &rule; + RULE rule; + RULE * r = &rule; r->name = rulename; - if ( hashenter( demand_rules( target_module ), (HASHDATA **)&r ) ) + if ( hashenter( demand_rules( target_module ), (HASHDATA * *)&r ) ) { - r->name = newstr( rulename ); /* never freed */ + r->name = newstr( rulename ); /* never freed */ r->procedure = (PARSE *)0; r->module = 0; r->actions = 0; @@ -89,117 +106,129 @@ enter_rule( char *rulename, module_t *target_module ) return r; } + /* * define_rule() - return pointer to RULE, creating it if necessary in * target_module. Prepare it to accept a body or action originating in * src_module. */ -static RULE * -define_rule( module_t *src_module, char *rulename, module_t *target_module ) -{ - RULE *r = enter_rule( rulename, target_module ); +static RULE * define_rule +( + module_t * src_module, + char * rulename, + module_t * target_module +) +{ + RULE * r = enter_rule( rulename, target_module ); if ( r->module != src_module ) /* if the rule was imported from elsewhere, clear it now */ { - set_rule_body( r, 0, 0 ); + set_rule_body( r, 0, 0 ); set_rule_actions( r, 0 ); r->module = src_module; /* r will be executed in the source module */ } - return r; } -void -rule_free( RULE* r ) + +void rule_free( RULE * r ) { freestr( r->name ); r->name = ""; parse_free( r->procedure ); r->procedure = 0; - if ( r->arguments ) - args_free( r->arguments ); + if ( r->arguments ) + args_free( r->arguments ); r->arguments = 0; if ( r->actions ) - actions_free( r->actions ); + actions_free( r->actions ); r->actions = 0; } + /* - * bindtarget() - return pointer to TARGET, creating it if necessary + * bindtarget() - return pointer to TARGET, creating it if necessary. */ -TARGET * -bindtarget( const char *targetname ) +TARGET * bindtarget( char const * target_name ) { - TARGET target, *t = ⌖ + TARGET target; + TARGET * t = ⌖ - if( !targethash ) - targethash = hashinit( sizeof( TARGET ), "targets" ); + if ( !targethash ) + targethash = hashinit( sizeof( TARGET ), "targets" ); /* Perforce added const everywhere. No time to merge that change. */ - t->name = (char*)targetname; +#ifdef NT + target_name = short_path_to_long_path( (char *)target_name ); +#endif + t->name = (char *)target_name; - if( hashenter( targethash, (HASHDATA **)&t ) ) - { - memset( (char *)t, '\0', sizeof( *t ) ); - t->name = newstr( (char*)targetname ); /* never freed */ - t->boundname = t->name; /* default for T_FLAG_NOTFILE */ - } + if ( hashenter( targethash, (HASHDATA * *)&t ) ) + { + memset( (char *)t, '\0', sizeof( *t ) ); + t->name = newstr( (char *)target_name ); /* never freed */ + t->boundname = t->name; /* default for T_FLAG_NOTFILE */ + } - return t; + return t; } -static void bind_explicitly_located_target(void* xtarget, void* data) +static void bind_explicitly_located_target( void * xtarget, void * data ) { - TARGET* t = (TARGET*)xtarget; - if (! (t->flags & T_FLAG_NOTFILE) ) + TARGET * t = (TARGET *)xtarget; + if ( !( t->flags & T_FLAG_NOTFILE ) ) { /* Check if there's a setting for LOCATE */ - SETTINGS* s = t->settings; - for(; s ; s = s->next) - { - if (strcmp(s->symbol, "LOCATE") == 0) + SETTINGS * s = t->settings; + for ( ; s ; s = s->next ) + { + if ( strcmp( s->symbol, "LOCATE" ) == 0 ) { - pushsettings(t->settings); - /* We're binding a target with explicit LOCATE. So - third argument is of now use: nothing will be returned - through it. */ - t->boundname = search( t->name, &t->time, 0 ); - popsettings(t->settings); + pushsettings( t->settings ); + /* We are binding a target with explicit LOCATE. So third + * argument is of no use: nothing will be returned through it. + */ + t->boundname = search( t->name, &t->time, 0, 0 ); + popsettings( t->settings ); break; } } } } + void bind_explicitly_located_targets() { - if (targethash) - hashenumerate(targethash, bind_explicitly_located_target, (void*)0); + if ( targethash ) + hashenumerate( targethash, bind_explicitly_located_target, (void *)0 ); } -/* TODO: this is probably not a good idea to use functions in other modules like - that. */ -void call_bind_rule(char* target, char* boundname); -TARGET* search_for_target ( char * name, LIST* search_path ) +/* TODO: It is probably not a good idea to use functions in other modules like + this. */ +void call_bind_rule( char * target, char * boundname ); + + +TARGET * search_for_target ( char * name, LIST * search_path ) { PATHNAME f[1]; string buf[1]; - LOCATED_TARGET lt, *lta = < + LOCATED_TARGET lt; + LOCATED_TARGET * lta = < time_t time; int found = 0; - TARGET* result; + TARGET * result; string_new( buf ); - path_parse( name, f ); + path_parse( name, f ); f->f_grist.ptr = 0; f->f_grist.len = 0; - while( search_path ) + while ( search_path ) { f->f_root.ptr = search_path->string; f->f_root.len = strlen( search_path->string ); @@ -209,18 +238,17 @@ TARGET* search_for_target ( char * name, LIST* search_path ) lt.file_name = buf->value ; - if (! located_targets ) + if ( !located_targets ) located_targets = hashinit( sizeof(LOCATED_TARGET), "located targets" ); - - if ( hashcheck( located_targets, (HASHDATA **)<a ) ) + if ( hashcheck( located_targets, (HASHDATA * *)<a ) ) { return lta->target; } timestamp( buf->value, &time ); - if (time) + if ( time ) { found = 1; break; @@ -229,7 +257,7 @@ TARGET* search_for_target ( char * name, LIST* search_path ) search_path = list_next( search_path ); } - if ( ! found ) + if ( !found ) { f->f_root.ptr = 0; f->f_root.len = 0; @@ -237,7 +265,7 @@ TARGET* search_for_target ( char * name, LIST* search_path ) string_truncate( buf, 0 ); path_build( f, buf, 1 ); - timestamp( buf->value, &time ); + timestamp( buf->value, &time ); } result = bindtarget( name ); @@ -246,256 +274,216 @@ TARGET* search_for_target ( char * name, LIST* search_path ) result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING; call_bind_rule( result->name, result->boundname ); - + string_free( buf ); return result; - } + /* - * copytarget() - make a new target with the old target's name + * copytarget() - make a new target with the old target's name. * * Not entered into hash table -- for internal nodes. */ -TARGET * -copytarget( const TARGET *ot ) +TARGET * copytarget( const TARGET * ot ) { - TARGET *t; + TARGET * t = (TARGET *)BJAM_MALLOC( sizeof( *t ) ); + memset( (char *)t, '\0', sizeof( *t ) ); + t->name = copystr( ot->name ); + t->boundname = t->name; - t = (TARGET *)BJAM_MALLOC( sizeof( *t ) ); - memset( (char *)t, '\0', sizeof( *t ) ); - t->name = copystr( ot->name ); - t->boundname = t->name; + t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL; - t->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL; - - return t; + return t; } + /* - * touchtarget() - mark a target to simulate being new + * touch_target() - mark a target to simulate being new. */ -void -touchtarget( char *t ) +void touch_target( char * t ) { - bindtarget( t )->flags |= T_FLAG_TOUCHED; + bindtarget( t )->flags |= T_FLAG_TOUCHED; } + /* - * targetlist() - turn list of target names into a TARGET chain + * targetlist() - turn list of target names into a TARGET chain. * * Inputs: - * chain existing TARGETS to append to - * targets list of target names + * chain existing TARGETS to append to + * targets list of target names */ -TARGETS * -targetlist( - TARGETS *chain, - LIST *targets ) +TARGETS * targetlist( TARGETS * chain, LIST * target_names ) { - for( ; targets; targets = list_next( targets ) ) - chain = targetentry( chain, bindtarget( targets->string ) ); - - return chain; + for ( ; target_names; target_names = list_next( target_names ) ) + chain = targetentry( chain, bindtarget( target_names->string ) ); + return chain; } + /* - * targetentry() - add a TARGET to a chain of TARGETS + * targetentry() - add a TARGET to a chain of TARGETS. * * Inputs: - * chain exisitng TARGETS to append to - * target new target to append + * chain existing TARGETS to append to + * target new target to append */ -TARGETS * -targetentry( - TARGETS *chain, - TARGET *target ) +TARGETS * targetentry( TARGETS * chain, TARGET * target ) { - TARGETS *c; + TARGETS * c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) ); + c->target = target; - c = (TARGETS *)BJAM_MALLOC( sizeof( TARGETS ) ); - c->target = target; + if ( !chain ) chain = c; + else chain->tail->next = c; + chain->tail = c; + c->next = 0; - if( !chain ) chain = c; - else chain->tail->next = c; - chain->tail = c; - c->next = 0; - - return chain; + return chain; } + /* - * targetchain() - append two TARGET chains + * targetchain() - append two TARGET chains. * * Inputs: - * chain exisitng TARGETS to append to - * target new target to append + * chain exisitng TARGETS to append to + * target new target to append */ -TARGETS * -targetchain( - TARGETS *chain, - TARGETS *targets ) +TARGETS * targetchain( TARGETS * chain, TARGETS * targets ) { - TARGETS *c; + if ( !targets ) return chain; + if ( !chain ) return targets; - if( !targets ) - return chain; - else if( !chain ) - return targets; + chain->tail->next = targets; + chain->tail = targets->tail; - chain->tail->next = targets; - chain->tail = targets->tail; - - return chain; + return chain; } /* - * actionlist() - append to an ACTION chain + * actionlist() - append to an ACTION chain. */ -ACTIONS * -actionlist( - ACTIONS *chain, - ACTION *action ) +ACTIONS * actionlist( ACTIONS * chain, ACTION * action ) { - ACTIONS *actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) ); + ACTIONS * actions = (ACTIONS *)BJAM_MALLOC( sizeof( ACTIONS ) ); - actions->action = action; + actions->action = action; - if( !chain ) chain = actions; - else chain->tail->next = actions; - chain->tail = actions; - actions->next = 0; + if ( !chain ) chain = actions; + else chain->tail->next = actions; + chain->tail = actions; + actions->next = 0; - return chain; + return chain; } -static SETTINGS* settings_freelist; +static SETTINGS * settings_freelist; + /* - * addsettings() - add a deferred "set" command to a target + * addsettings() - add a deferred "set" command to a target. * - * Adds a variable setting (varname=list) onto a chain of settings - * for a particular target. - * 'flag' controls the relationship between new and old values in the same - * way as in var_set() function (see variable.c). - * Returns the head of the chain of settings. + * Adds a variable setting (varname=list) onto a chain of settings for a + * particular target. 'flag' controls the relationship between new and old + * values in the same way as in var_set() function (see variable.c). Returns + * the head of the settings chain. */ -SETTINGS * -addsettings( - SETTINGS *head, - int flag, - char *symbol, - LIST *value ) +SETTINGS * addsettings( SETTINGS * head, int flag, char * symbol, LIST * value ) { - SETTINGS *v; - - /* Look for previous setting */ + SETTINGS * v; - for( v = head; v; v = v->next ) - if( !strcmp( v->symbol, symbol ) ) - break; + /* Look for previous settings. */ + for ( v = head; v; v = v->next ) + if ( !strcmp( v->symbol, symbol ) ) + break; - /* If not previously set, alloc a new. */ - /* If appending, do so. */ - /* Else free old and set new. */ - - if( !v ) - { + /* If not previously set, alloc a new. */ + /* If appending, do so. */ + /* Else free old and set new. */ + if ( !v ) + { v = settings_freelist; - + if ( v ) settings_freelist = v->next; else - { v = (SETTINGS *)BJAM_MALLOC( sizeof( *v ) ); - } - - v->symbol = newstr( symbol ); - v->value = value; - v->next = head; - head = v; - } - else if( flag == VAR_APPEND ) - { - v->value = list_append( v->value, value ); - } - else if( flag != VAR_DEFAULT ) - { - list_free( v->value ); - v->value = value; - } - else - list_free( value ); - /* Return (new) head of list. */ + v->symbol = newstr( symbol ); + v->value = value; + v->next = head; + head = v; + } + else if ( flag == VAR_APPEND ) + { + v->value = list_append( v->value, value ); + } + else if ( flag != VAR_DEFAULT ) + { + list_free( v->value ); + v->value = value; + } + else + list_free( value ); - return head; + /* Return (new) head of list. */ + return head; } + /* - * pushsettings() - set all target specific variables + * pushsettings() - set all target specific variables. */ -void -pushsettings( SETTINGS *v ) +void pushsettings( SETTINGS * v ) { - for( ; v; v = v->next ) - v->value = var_swap( v->symbol, v->value ); + for ( ; v; v = v->next ) + v->value = var_swap( v->symbol, v->value ); } + /* - * popsettings() - reset target specific variables to their pre-push values + * popsettings() - reset target specific variables to their pre-push values. */ -void -popsettings( SETTINGS *v ) +void popsettings( SETTINGS * v ) { - pushsettings( v ); /* just swap again */ + pushsettings( v ); /* just swap again */ } + /* - * copysettings() - duplicate a settings list, returning the new copy + * copysettings() - duplicate a settings list, returning the new copy. */ -SETTINGS* -copysettings( SETTINGS *head ) + +SETTINGS * copysettings( SETTINGS * head ) { - SETTINGS *copy = 0, *v; - - for (v = head; v; v = v->next) - copy = addsettings(copy, VAR_SET, v->symbol, list_copy(0, v->value)); - + SETTINGS * copy = 0; + SETTINGS * v; + for ( v = head; v; v = v->next ) + copy = addsettings( copy, VAR_SET, v->symbol, list_copy( 0, v->value ) ); return copy; } -/* - * freetargets() - delete a targets list - */ -void freetargets( TARGETS *chain ) -{ - while( chain ) - { - TARGETS* n = chain->next; - BJAM_FREE( chain ); - chain = n; - } -} /* - * freeactions() - delete an action list + * freetargets() - delete a targets list. */ -void freeactions( ACTIONS *chain ) + +void freetargets( TARGETS * chain ) { - while( chain ) + while ( chain ) { - ACTIONS* n = chain->next; + TARGETS * n = chain->next; BJAM_FREE( chain ); chain = n; } @@ -503,118 +491,139 @@ void freeactions( ACTIONS *chain ) /* - * freesettings() - delete a settings list + * freeactions() - delete an action list. */ -void -freesettings( SETTINGS *v ) +void freeactions( ACTIONS * chain ) { - while( v ) - { - SETTINGS *n = v->next; + while ( chain ) + { + ACTIONS * n = chain->next; + BJAM_FREE( chain ); + chain = n; + } +} - freestr( v->symbol ); - list_free( v->value ); + +/* + * freesettings() - delete a settings list. + */ + +void freesettings( SETTINGS * v ) +{ + while ( v ) + { + SETTINGS * n = v->next; + freestr( v->symbol ); + list_free( v->value ); v->next = settings_freelist; settings_freelist = v; - - v = n; - } + v = n; + } } -static void freetarget( void *xt, void *data ) + +static void freetarget( void * xt, void * data ) { - TARGET* t = (TARGET *)xt; - if ( t->settings ) - freesettings( t->settings ); - if ( t->depends ) - freetargets( t->depends ); - if ( t->includes ) - freetarget( t->includes, (void*)0); - if ( t->actions ) - freeactions( t->actions ); + TARGET * t = (TARGET *)xt; + if ( t->settings ) freesettings( t->settings ); + if ( t->depends ) freetargets ( t->depends ); + if ( t->includes ) freetarget ( t->includes, (void *)0 ); + if ( t->actions ) freeactions ( t->actions ); } + /* - * donerules() - free TARGET tables + * rules_done() - free RULE and TARGET tables. */ -void -donerules() +void rules_done() { - hashenumerate( targethash, freetarget, 0 ); - hashdone( targethash ); + hashenumerate( targethash, freetarget, 0 ); + hashdone( targethash ); while ( settings_freelist ) { - SETTINGS* n = settings_freelist->next; + SETTINGS * n = settings_freelist->next; BJAM_FREE( settings_freelist ); settings_freelist = n; } } + /* - * args_new() - make a new reference-counted argument list + * args_new() - make a new reference-counted argument list. */ -argument_list* args_new() + +argument_list * args_new() { - argument_list* r = (argument_list*)BJAM_MALLOC( sizeof(argument_list) ); + argument_list * r = (argument_list *)BJAM_MALLOC( sizeof(argument_list) ); r->reference_count = 0; - lol_init(r->data); + lol_init( r->data ); return r; } + /* - * args_refer() - add a new reference to the given argument list + * args_refer() - add a new reference to the given argument list. */ -void args_refer( argument_list* a ) + +void args_refer( argument_list * a ) { ++a->reference_count; } + /* - * args_free() - release a reference to the given argument list + * args_free() - release a reference to the given argument list. */ -void args_free( argument_list* a ) + +void args_free( argument_list * a ) { - if (--a->reference_count <= 0) + if ( --a->reference_count <= 0 ) { - lol_free(a->data); - BJAM_FREE(a); + lol_free( a->data ); + BJAM_FREE( a ); } } + /* - * actions_refer() - add a new reference to the given actions + * actions_refer() - add a new reference to the given actions. */ -void actions_refer(rule_actions* a) + +void actions_refer( rule_actions * a ) { ++a->reference_count; } + /* - * actions_free() - release a reference to the given actions + * actions_free() - release a reference to the given actions. */ -void actions_free(rule_actions* a) + +void actions_free( rule_actions * a ) { - if (--a->reference_count <= 0) + if ( --a->reference_count <= 0 ) { - freestr(a->command); - list_free(a->bindlist); - BJAM_FREE(a); + freestr( a->command ); + list_free( a->bindlist ); + BJAM_FREE( a ); } } + /* - * set_rule_body() - set the argument list and procedure of the given rule + * set_rule_body() - set the argument list and procedure of the given rule. */ -static void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure ) + +static void set_rule_body( RULE * rule, argument_list * args, PARSE * procedure ) { if ( args ) args_refer( args ); if ( rule->arguments ) args_free( rule->arguments ); rule->arguments = args; - + if ( procedure ) parse_refer( procedure ); if ( rule->procedure ) @@ -622,59 +631,61 @@ static void set_rule_body( RULE* rule, argument_list* args, PARSE* procedure ) rule->procedure = procedure; } + /* - * global_name() - given a rule, return the name for a corresponding rule in the global module + * global_name() - given a rule, return the name for a corresponding rule in the + * global module. */ -static char* global_rule_name( RULE* r ) + +static char * global_rule_name( RULE * r ) { if ( r->module == root_module() ) - { return r->name; - } - else + { char name[4096] = ""; - strncat(name, r->module->name, sizeof(name) - 1); - strncat(name, r->name, sizeof(name) - 1 ); - return newstr(name); + strncat( name, r->module->name, sizeof( name ) - 1 ); + strncat( name, r->name, sizeof( name ) - 1 ); + return newstr( name); } } + /* - * global_rule() - given a rule, produce the corresponding entry in the global module + * global_rule() - given a rule, produce the corresponding entry in the global + * module. */ -static RULE* global_rule( RULE* r ) + +static RULE * global_rule( RULE * r ) { if ( r->module == root_module() ) - { return r; - } - else + { - char* name = global_rule_name( r ); - RULE* result = define_rule( r->module, name, root_module() ); - freestr(name); + char * name = global_rule_name( r ); + RULE * result = define_rule( r->module, name, root_module() ); + freestr( name ); return result; } } + /* - * new_rule_body() - make a new rule named rulename in the given - * module, with the given argument list and procedure. If exported is - * true, the rule is exported to the global module as - * modulename.rulename. + * new_rule_body() - make a new rule named rulename in the given module, with + * the given argument list and procedure. If exported is true, the rule is + * exported to the global module as modulename.rulename. */ -RULE* new_rule_body( module_t* m, char* rulename, argument_list* args, PARSE* procedure, int exported ) + +RULE * new_rule_body( module_t * m, char * rulename, argument_list * args, PARSE * procedure, int exported ) { - RULE* local = define_rule( m, rulename, m ); + RULE * local = define_rule( m, rulename, m ); local->exported = exported; set_rule_body( local, args, procedure ); - - /* Mark the procedure with the global rule name, regardless of - * whether the rule is exported. That gives us something - * reasonably identifiable that we can use, e.g. in profiling - * output. Only do this once, since this could be called multiple - * times with the same procedure. + + /* Mark the procedure with the global rule name, regardless of whether the + * rule is exported. That gives us something reasonably identifiable that we + * can use, e.g. in profiling output. Only do this once, since this could be + * called multiple times with the same procedure. */ if ( procedure->rulename == 0 ) procedure->rulename = global_rule_name( local ); @@ -682,19 +693,20 @@ RULE* new_rule_body( module_t* m, char* rulename, argument_list* args, PARSE* pr return local; } -static void set_rule_actions( RULE* rule, rule_actions* actions ) + +static void set_rule_actions( RULE * rule, rule_actions * actions ) { if ( actions ) actions_refer( actions ); if ( rule->actions ) actions_free( rule->actions ); rule->actions = actions; - } -static rule_actions* actions_new( char* command, LIST* bindlist, int flags ) + +static rule_actions * actions_new( char * command, LIST * bindlist, int flags ) { - rule_actions* result = (rule_actions*)BJAM_MALLOC(sizeof(rule_actions)); + rule_actions * result = (rule_actions *)BJAM_MALLOC( sizeof( rule_actions ) ); result->command = copystr( command ); result->bindlist = bindlist; result->flags = flags; @@ -702,88 +714,95 @@ static rule_actions* actions_new( char* command, LIST* bindlist, int flags ) return result; } -RULE* new_rule_actions( module_t* m, char* rulename, char* command, LIST* bindlist, int flags ) + +RULE * new_rule_actions( module_t * m, char * rulename, char * command, LIST * bindlist, int flags ) { - RULE* local = define_rule( m, rulename, m ); - RULE* global = global_rule( local ); + RULE * local = define_rule( m, rulename, m ); + RULE * global = global_rule( local ); set_rule_actions( local, actions_new( command, bindlist, flags ) ); set_rule_actions( global, local->actions ); return local; } -/* Looks for a rule in the specified module, and returns it, if found. - First checks if the rule is present in the module's rule table. - Second, if name of the rule is in the form name1.name2 and name1 is in - the list of imported modules, look in module 'name1' for rule 'name2'. -*/ -RULE *lookup_rule( char *rulename, module_t *m, int local_only ) + +/* + * Looks for a rule in the specified module, and returns it, if found. First + * checks if the rule is present in the module's rule table. Second, if name of + * the rule is in the form name1.name2 and name1 is in the list of imported + * modules, look in module 'name1' for rule 'name2'. + */ + +RULE * lookup_rule( char * rulename, module_t * m, int local_only ) { - RULE rule, *r = &rule, *result = 0; - module_t* original_module = m; + RULE rule; + RULE * r = &rule; + RULE * result = 0; + module_t * original_module = m; + r->name = rulename; - if (m->class_module) + if ( m->class_module ) m = m->class_module; - if (m->rules && hashcheck( m->rules, (HASHDATA **)&r ) ) + if ( m->rules && hashcheck( m->rules, (HASHDATA * *)&r ) ) result = r; - else if (!local_only && m->imported_modules) { + else if ( !local_only && m->imported_modules ) + { /* Try splitting the name into module and rule. */ - char *p = strchr(r->name, '.') ; - if (p) { + char *p = strchr( r->name, '.' ) ; + if ( p ) + { *p = '\0'; - /* Now, r->name keeps the module name, and p+1 keeps the rule name. */ - if (hashcheck( m->imported_modules, (HASHDATA **)&r)) - { - result = lookup_rule(p+1, bindmodule(rulename), 1); - } + /* Now, r->name keeps the module name, and p+1 keeps the rule name. + */ + if ( hashcheck( m->imported_modules, (HASHDATA * *)&r ) ) + result = lookup_rule( p + 1, bindmodule( rulename ), 1 ); *p = '.'; - } + } } - if (result) + if ( result ) { - if (local_only && !result->exported) + if ( local_only && !result->exported ) result = 0; else { - /* Lookup started in class module. We've found a rule in class module, - which is marked for execution in that module, or in some instances. - Mark it for execution in the instance where we've started lookup. - */ - int execute_in_class = (result->module == m); - int execute_in_some_instance = - (result->module->class_module && result->module->class_module == m); - if (original_module != m && (execute_in_class || execute_in_some_instance)) - result->module = original_module; + /* Lookup started in class module. We have found a rule in class + * module, which is marked for execution in that module, or in some + * instances. Mark it for execution in the instance where we started + * the lookup. + */ + int execute_in_class = ( result->module == m ); + int execute_in_some_instance = ( result->module->class_module && + ( result->module->class_module == m ) ); + if ( ( original_module != m ) && + ( execute_in_class || execute_in_some_instance ) ) + result->module = original_module; } } return result; - } -RULE *bindrule( char *rulename, module_t* m) +RULE * bindrule( char * rulename, module_t * m ) { - RULE *result; - - result = lookup_rule(rulename, m, 0); - if (!result) - result = lookup_rule(rulename, root_module(), 0); - /* We've only one caller, 'evaluate_rule', which will complain about - calling underfined rule. We could issue the error - here, but we don't have necessary information, such as frame. - */ - if (!result) + RULE * result = lookup_rule( rulename, m, 0 ); + if ( !result ) + result = lookup_rule( rulename, root_module(), 0 ); + /* We have only one caller, 'evaluate_rule', which will complain about + * calling an undefined rule. We could issue the error here, but we do not + * have the necessary information, such as frame. + */ + if ( !result ) result = enter_rule( rulename, m ); - return result; } -RULE* import_rule( RULE* source, module_t* m, char* name ) + +RULE * import_rule( RULE * source, module_t * m, char * name ) { - RULE* dest = define_rule( source->module, name, m ); + RULE * dest = define_rule( source->module, name, m ); set_rule_body( dest, source->arguments, source->procedure ); set_rule_actions( dest, source->actions ); return dest; diff --git a/src/engine/rules.h b/src/engine/rules.h index 563808252..9ad4171b6 100644 --- a/src/engine/rules.h +++ b/src/engine/rules.h @@ -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 diff --git a/src/engine/scan.c b/src/engine/scan.c index fd198b68d..1e3ffca41 100644 --- a/src/engine/scan.c +++ b/src/engine/scan.c @@ -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; diff --git a/src/engine/scan.h b/src/engine/scan.h index 8f1454c25..3fad1c24c 100644 --- a/src/engine/scan.h +++ b/src/engine/scan.h @@ -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 */ diff --git a/src/engine/search.c b/src/engine/search.c index d8f77b383..6c23d97a1 100644 --- a/src/engine/search.c +++ b/src/engine/search.c @@ -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 +#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 -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 ); diff --git a/src/engine/search.h b/src/engine/search.h index af3e890fd..c364cac03 100644 --- a/src/engine/search.h +++ b/src/engine/search.h @@ -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 ); diff --git a/src/engine/strings.c b/src/engine/strings.c index 5a4efe27f..895612377 100644 --- a/src/engine/strings.c +++ b/src/engine/strings.c @@ -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 diff --git a/src/engine/subst.c b/src/engine/subst.c index c164729ec..75524ecc1 100644 --- a/src/engine/subst.c +++ b/src/engine/subst.c @@ -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; } diff --git a/src/engine/timestamp.c b/src/engine/timestamp.c index 14a16d9af..8a59c8c0e 100644 --- a/src/engine/timestamp.c +++ b/src/engine/timestamp.c @@ -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 ); } diff --git a/src/engine/timestamp.h b/src/engine/timestamp.h index f290f82cb..f57527639 100644 --- a/src/engine/timestamp.h +++ b/src/engine/timestamp.h @@ -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(); diff --git a/src/engine/variable.c b/src/engine/variable.c index 808d92547..795f34584 100644 --- a/src/engine/variable.c +++ b/src/engine/variable.c @@ -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 -# include +#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 +#include /* - * 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 ); } diff --git a/src/engine/variable.h b/src/engine/variable.h index 4a3ae6982..5c49e3ca5 100644 --- a/src/engine/variable.h +++ b/src/engine/variable.h @@ -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 */ diff --git a/src/engine/w32_getreg.c b/src/engine/w32_getreg.c index 8da65a558..5a06f43e9 100644 --- a/src/engine/w32_getreg.c +++ b/src/engine/w32_getreg.c @@ -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") ) diff --git a/src/engine/yyacc.c b/src/engine/yyacc.c index 3debec0d7..b5efc96b5 100644 --- a/src/engine/yyacc.c +++ b/src/engine/yyacc.c @@ -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";