summaryrefslogtreecommitdiff
path: root/db-4.8.30/dist/winmsi/s_winmsi.fcn
diff options
context:
space:
mode:
Diffstat (limited to 'db-4.8.30/dist/winmsi/s_winmsi.fcn')
-rw-r--r--db-4.8.30/dist/winmsi/s_winmsi.fcn1473
1 files changed, 1473 insertions, 0 deletions
diff --git a/db-4.8.30/dist/winmsi/s_winmsi.fcn b/db-4.8.30/dist/winmsi/s_winmsi.fcn
new file mode 100644
index 0000000..9dcacf3
--- /dev/null
+++ b/db-4.8.30/dist/winmsi/s_winmsi.fcn
@@ -0,0 +1,1473 @@
+# $Id$
+#
+# The common functions used by the s_winmsi scripts (both
+# for core DB and DB/XML).
+#
+# This script uses several bash extensions that are convenient
+# since we "know" it will always run under Cygwin: shell functions,
+# 'return', declaration of 'local' variables, $(command) syntax,
+# ${#X} (counting chars), ${X#regexp} (searching) $((expr)) (arithmetic)
+#
+# These functions use 'global' variables:
+# ERRORLOG - a filename
+# PRODUCT_NAME - e.g. "Berkeley DB"
+# PRODUCT_VERSION - e.g. "4.1.25", derived from dist/RELEASE
+# PRODUCT_MAJOR - e.g. "4", (for release 4.1.25) from dist/RELEASE
+# PRODUCT_MINOR - e.g. "1", (for release 4.1.25) from dist/RELEASE
+# PRODUCT_PATCH - e.g. "25", (for release 4.1.25) from dist/RELEASE
+# PRODUCT_MAJMIN - e.g. "41", (for release 4.1.25) from dist/RELEASE
+# PRODUCT_MSVC_VERSION - e.g. "71" for Visual Studio 7, "80" for VS 8
+# PRODUCT_STAGE - the staging directory for temp files and builds
+# PRODUCT_LICENSEDIR - the tree containing LICENSE and README
+# PRODUCT_SUB_BLDDIR - top of the subproduct build e.g. "dbxml-2.0.1/dbxml"
+# PRODUCT_BLDDIR - top of the build tree e.g. "dbxml-2.0.1"
+# PRODUCT_SRCDIR - the dir we unzip to e.g. "dbxml-2.0.1"
+# PRODUCT_DBBUILDDIR - where build_unix dir is for Berkeley DB (for Perl)
+# PRODUCT_SHARED_WINMSIDIR - where the master winmsi directory is
+# PRODUCT_IMAGEDIR - where the images are (usually winmsi/images)
+# PRODUCT_ZIP_FILEFMT - what zip file looks like e.g. "db-X.Y.Z.NC.zip"
+# PRODUCT_MSI_FILEFMT - what msi file looks like e.g. "db-X.Y.Z.NC.msi"
+#
+# Some of these may seem redundant, but there are options to take
+# an already built tree from a different place than where we'll unzip
+# to and take our sources from, for example. This allows a lot of flexibility
+# for development and debugging (especially when these trees can be huge).
+
+# This is the magic tag that creates a new unique GUID in Wix.
+# GUIDs are needed on every <Component ... > entry to ensure
+# that the component can be uninstalled.
+GENGUID='Guid="GUID_CREATE_UNIQUE()"'
+PERSISTGUID='Guid="WIX_DB_PERSISTENT_GUID()"'
+
+# MakeRtf()
+# Standard input is plain text, standard output is RTF.
+#
+MakeRtf() {
+ temp1=/tmp/sbm$$a
+ cat > $temp1
+
+
+# Courier is a good font, but the lines with all caps
+# overflows our current dialog size:
+# {\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Courier New;}}
+# \viewkind4\uc1\pard\lang1033\f0\fs16
+#
+# Using Small fonts works:
+# {\rtf1\ansi\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Small Fonts;}}
+# {\colortbl ;\red0\green0\blue0;}
+# \viewkind4\uc1\pard\cf1\lang1033\f0\fs14
+
+# Arial is the best compromise:
+ sed -e 's/^ *//' << 'EndOfRTFHeader'
+ {\rtf1\ansi\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
+ {\colortbl ;\red0\green0\blue0;}
+ \viewkind4\uc1\pard\cf1\lang1033\f0\fs16
+EndOfRTFHeader
+
+# Embedded '<' and '>' can cause problems for Wix
+ sed -e 's:$:\\par:' -e 's:<: \\lquote :' -e 's:>: \\rquote :' < $temp1
+ echo -n '}'
+ rm -f $temp1
+}
+
+# NextId()
+# Get the next available unique id, a simple integer counter.
+# We use a file, rather than a shell variable to track the
+# number, because this is called from subshells at various
+# points, and they cannot affect the variables in the parent shell.
+#
+ComponentID=component.id
+NextId()
+{
+ local id=`cat $ComponentID 2>/dev/null`
+ if [ "$id" = '' ]; then
+ id=0
+ fi
+ id=$(($id + 1))
+ echo "$id" > $ComponentID
+ echo "$id"
+}
+
+# CleanFileName(FILENAME)
+# Removes any strange characters in file names,
+# returning the new name on standard output.
+CleanFileName()
+{
+ echo "$1" | sed -e 's/[-%@!]//g'
+}
+
+# GetShortName(FILENAME)
+# Get a Windows short name for the file,
+# to fit into the 8.3 name space.
+# This is not a great algorithm, but it works.
+# The fact is, the names must be unique, but on
+# Win2000 and WinXP, we'll never see them.
+
+ShortID=short.id
+GetShortName()
+{
+ local name=`echo "$1" | tr '[a-z]' '[A-Z]'`
+
+ # See if the name fits into 8.3. If so,
+ # return it right away.
+ #
+ case "$name" in
+ ?????????*.* ) ;;
+ *.????* ) ;;
+ *.*.* ) ;;
+ *[-%@!]* ) ;;
+ *.* ) echo "$name"
+ return
+ ;;
+ * )
+ if [ "${#1}" -le 8 ]; then
+ echo "$name"
+ return
+ fi
+ ;;
+ esac
+
+ # From NAMEISLONG.EXTLONG, build a name
+ # like NAME~ZZZ.EXT, where ZZZ is a unique (hex)
+ # number we build. This is
+
+ local id=`cat $ShortID 2>/dev/null`
+ if [ "$id" = '' ]; then
+ id=0
+ fi
+ id=$(($id + 1))
+ echo "$id" > $ShortID
+ if [ "$id" -ge 4096 ]; then
+ echo "BADBADBAD.TXT" # return something that will give an error
+ Error "ShortId overflow"
+ exit 1
+ fi
+
+ # Convert the id to hex (I ran out of space using decimal)
+ # This is too slow: id=`echo 16 o $id p | dc`
+ id=`printf "%x" $id`
+
+ # Collect and clean up the part of the name before, and after, the dot
+ local before=`CleanFileName "$name" | sed -e 's/^\([^.]*\)[.].*$/\1/'`
+ local after=`CleanFileName "$name" | sed -e 's/^[^.]*[.]\(.*\)$/\1/'`
+
+ # Make sure the before part fits in 5 chars (not 8, since
+ # we need a few for the unique number).
+ if [ "${#before}" -gt 5 ]; then
+ before=`echo "$before" | sed -e 's/^\(.....\).*/\1/'`
+ fi
+ if [ "${#after}" -gt 3 ]; then
+ after=`echo "$after" | sed -e 's/^\(...\).*/\1/'`
+ fi
+ echo "${before}~${id}.${after}"
+}
+
+# Progress([OPTION,]STRING...)
+# Show a major processing step via echo to stdout and to the error log.
+# An OPTION is "-minor", indicating no big banner.
+#
+Progress()
+{
+ if [ "$1" = -minor ]; then
+ shift
+ else
+ echo "" >> $ERRORLOG
+ echo "============================" >> $ERRORLOG
+ fi
+ echo "$@" >> $ERRORLOG
+ echo "$@" >&15
+}
+
+# Error(STRING...)
+# Show an error in a standard way.
+#
+Error()
+{
+ echo "" >> $ERRORLOG
+ echo "****************** FAIL ******************" >> $ERRORLOG
+ echo "ERROR: $@" >> $ERRORLOG
+ echo "ERROR: $@" >&15
+ echo "See $ERRORLOG for details" >&15
+ return 1
+}
+
+# RequireFileInPath(NAME, PATHVAL, FILE)
+# Look for FILE in the path that has value PATHVAL.
+# The path's name is NAME if it needs to be shown.
+#
+RequireFileInPath()
+{
+ local type="$1"
+ local origpath="$2"
+ local file="$3"
+ local upath="$origpath"
+ if [ "$1" != PATH ]; then
+ upath=`cygpath -up "$origpath"`
+ fi
+
+ SAVEIFS="$IFS"
+ IFS=":"
+ found=no
+ for dir in $upath; do
+ if [ -f "$dir/$file" ]; then
+ IFS="$SAVEIFS"
+ return
+ fi
+ done
+ IFS="$SAVEIFS"
+ Error "File $file not found in $type path: $origpath"
+ exit 1
+}
+
+# Rand4X()
+# Return 4 random hex digits on output
+#
+Rand4X() {
+ # The sed command pads the front with 0's as needed
+ (echo 'obase=16'; echo $RANDOM ) | bc |
+ sed -e 's/^/0000/' -e 's/^.*\(....\)$/\1/'
+
+}
+
+# RunM4()
+# Run M4, making appropriate substitutions.
+# This function uses GLOBAL variables: PRODUCT_VERSION (e.g. "4.1.25")
+# and PRODUCT_LICENSEDIR, which is where certain text files are found
+#
+RunM4() {
+
+ # Given a version number, like 2.3.45, we want to
+ # create a 8 character name for the directory like db2_3_45.
+ # This name is under a "Oracle" directory,
+ # so it only needs to be unique within the universe of BDB versions.
+ # TODO: instead of using a version number like $DB_VERSION,
+ # maybe use $DB_VERSION_UNIQUE_NAME which looks like "_2003"
+
+ local DB_8CHAR_VERSION=`echo $PRODUCT_VERSION | sed -e 's/[.]/_/g'`
+ if [ ${#DB_8CHAR_VERSION} -le 6 ]; then
+ DB_8CHAR_VERSION="db$DB_8CHAR_VERSION"
+ elif [ ${#DB_8CHAR_VERSION} -le 7 ]; then
+ DB_8CHAR_VERSION="d$DB_8CHAR_VERSION"
+ else
+ Error "Version number too large for simple version number algorithm"
+ exit 1
+ fi
+
+ # Remove leading ./ from PRODUCT_LICENSEDIR if present.
+ local licensedir=`cygpath -w "$PRODUCT_LICENSEDIR"`
+
+ # Create a GUID prefix of the form: ????????-????-????-????-????
+ # This leaves 8 digits of GUID to be manipulated by m4.
+ local GUID_PREFIX="`Rand4X``Rand4X`-`Rand4X`-`Rand4X`-`Rand4X`-`Rand4X`"
+
+ # -P requires that all m4 macros, like define, eval, etc.
+ # are prefixed, like m4_define, m4_eval, etc. This avoids
+ # various name conflicts with input files.
+ # TODO: rename DB_SRCDIR as DB_LICENSEDIR
+ m4 -P \
+ -DWIX_DB_VERSION="$PRODUCT_VERSION" \
+ -DWIX_DB_8CHAR_VERSION="$DB_8CHAR_VERSION" \
+ -DWIX_DB_GUID_PREFIX="$GUID_PREFIX" \
+ -DWIX_DB_PRODUCT_NAME="$PRODUCT_NAME" \
+ -DWIX_DB_SRCDIR="$licensedir" \
+ -DWIX_DB_TOP="`cygpath -w $PRODUCT_BLDDIR`" \
+ -DWIX_DB_SHARED_WINMSIDIR="$PRODUCT_SHARED_WINMSIDIR" \
+ -DWIX_DB_IMAGEDIR="`cygpath -w $PRODUCT_IMAGEDIR`" \
+ -DWIX_DB_FEATURE_STRUCTURE="m4_include(features.wixinc)" \
+ -DWIX_DB_DIRECTORY_STRUCTURE="m4_include(directory.wixinc)" \
+ -DWIX_DB_LINKS="m4_include(links.wixinc)" \
+ -DWIX_DB_LICENSE_RTF="m4_include(license.rtf)" \
+ -DWIX_DB_ENV_FEATURE_PROPS="m4_include(envprops.wixinc)" \
+ -DWIX_DB_ENV_FEATURE_SET="m4_include(envset.wixinc)" \
+ -DWIX_DB_ENV_FEATURE_SHOW="m4_include(envshow.wixinc)"
+}
+
+# RunTallow(DIR, OPTIONS)
+# Run Tallow, a tool from the WiX distribution
+RunTallow() {
+ local dir="$1"
+ shift
+
+ Id1=`NextId`
+ Id2=`NextId`
+ Id3=`NextId`
+
+ # Tallow is a tool that walks a tree, producing
+ # a WiX directory heirarchy naming the files.
+ # The IDs it produces are not unique (between tallow
+ # runs), so we must make them so here. Thus "directory78"
+ # becomes "MyFeatureName.123.78" where 123 is an id from NextId.
+ # Secondly, instead of using the tallow output as a separately
+ # compiled fragment, we want to include it directly, so
+ # we need to strip out some extraneous XML entries at the top
+ # and bottom of its output.
+ #
+ # Another thing we do is when we see <Directory></Directory>
+ # pairs, we call m4 macros WIX_DB_{BEGIN,END}_SUBDIR because
+ # we need to track the current directory to generate 'persistent'
+ # GUIDs. See the discussion about GUIDs in dbwix.m4 .
+ #
+ # !!! For stripping out the extraneous XML, we rely heavily
+ # !!! on the output format, so this is likely to be fragile
+ # !!! between versions of tallow. Fortunately, it should fail hard.
+ #
+ echo "=============" >> tallow.log
+ echo tallow -nologo -d `cygpath -w "$dir"` "$@" >> tallow.log
+ echo " <!-- TALLOW output begins here -->"
+ tallow -nologo -d `cygpath -w "$dir"` "$@" > tallow.out || exit 1
+ cat tallow.out >> tallow.log
+ echo "-------------" >> tallow.log
+
+ sed -e '1,/<DirectoryRef/d' -e '/<\/DirectoryRef/,$d' \
+ -e "s/Id=\"directory/Id=\"$feature.$Id1./" \
+ -e "s/Id=\"component/Id=\"$feature.$Id2./" \
+ -e "s/Id=\"file/Id=\"$feature.$Id3./" \
+ -e '/^ <Directory/d' \
+ -e '/^ <\/Directory/d' \
+ -e '/<Directory/s/Name=\"\([^"]*\)"/Name="\1" WIX_DB_BEGIN_SUBDIR(\1) /' \
+ -e '/<\/Directory>/s/$/ WIX_DB_END_SUBDIR()/' \
+ -e "/<Component/s/>/ $PERSISTGUID>/" \
+ < tallow.out > tallow.postsed || exit 1
+
+ echo 'WIX_DB_SET_CURFILE()'
+ echo 'WIX_DB_CLEAR_SUBDIR()'
+ cat tallow.postsed
+ echo 'WIX_DB_CLEAR_SUBDIR()'
+
+ cat tallow.postsed >> tallow.log
+ echo " <!-- TALLOW output ends here -->"
+}
+
+# ProcessFeatures(INFILES, INFEATURES, INENV, OUTDIRECTORIES, OUTFEATURES,
+# OUTSET)
+# Use the files.in and features.in files as
+# input to create two output files, one containing a WiX XML
+# fragment showing directories and needed files,
+# and another containing a WiX XML fragment showing
+# the features in a dependency tree.
+#
+# This creates the heart of the installer flexibility.
+#
+ProcessFeatures() {
+ InFiles="infiles.tmp"; CleanInputFile "$1" "$InFiles" 3 4
+ InFeatures="infeatures.tmp"; CleanInputFile "$2" "$InFeatures" 3 4
+ InEnv="inenv.tmp"; CleanInputFile "$3" "$InEnv" 3 4
+ OutDirs="$4"
+ OutFeatures="$5"
+ OutSet="$6"
+
+ rm -f $OutDirs; touch $OutDirs
+ rm -f $OutFeatures; touch $OutFeatures
+
+ # Initialize the feature list.
+ # This will be expanded (per feature) in ProcessOneFeature
+ #
+ XmlLevel=4
+ Xecho "<Publish Property=\"FeatureList\" Value=\"[NULL]\">" >> $OutSet
+ Xecho " <![CDATA[1]]></Publish>" >> $OutSet
+
+ Dirs=`cut -f 3 < $InFiles | sort | uniq`
+ Prevdir="/"
+ ProcessDirTransition "$Prevdir" "/" >> $OutDirs
+
+ for Dir in $Dirs; do
+ ProcessDirTransition "$Prevdir" "$Dir" >> $OutDirs
+ ProcessOneDirectory "$Dir" < $InFiles >> $OutDirs || exit 1
+ Prevdir="$Dir"
+ done
+ ProcessDirTransition "$Prevdir" "/" >> $OutDirs
+
+ cat $InEnv | (
+ read line
+ while [ "$line" != '' ]; do
+ local FeatureName=`echo "$line" | cut -f 1`
+ local EnvVariable=`echo "$line" | cut -f 2`
+ local EnvValue=`echo "$line" | cut -f 3`
+ local EnvOption=`echo "$line" | cut -f 4`
+ ProcessOneEnv "$FeatureName" "$EnvVariable" "$EnvValue" "$EnvOption" "$OutDirs" "$OutSet"
+ read line
+ done
+ return 0
+ ) || Error "Error processing environment" || exit 1
+
+ cat $InFeatures | (
+ read line
+ while [ "$line" != '' ]; do
+ local FeaturePath=`echo "$line" | cut -f 1`
+ local ShortName=`echo "$line" | cut -f 2 | StripDoubleQuotes`
+ local Description=`echo "$line" | cut -f 3 | StripDoubleQuotes`
+ local FeatureOptions=`echo "$line" | cut -f 4 | StripDoubleQuotes`
+ ProcessOneFeature "$FeaturePath" "$ShortName" "$Description" "$FeatureOptions" "$OutDirs" "$OutFeatures" "$OutSet"
+ read line
+ done
+ return 0
+ ) || Error "Error processing features" || exit 1
+
+# (PBR)
+# This test code didn't work. My hope was that I could force INSTALLLEVEL
+# to 4 and this would then enable the debug features.
+# Xecho "<Publish Property=\"INSTALLLEVEL\" Value=\"4\" />" >> $OutSet
+# Xecho "<Publish Event=\"SetInstallLevel\" Value=\"4\" />" >> $OutSet
+
+}
+
+# ProcessLinks(INLINKS, OUTFEATURES)
+# Process the INLINKS file, and produce XML on stdout.
+# Each line of the input file requires the creation
+# of a '.URL' file in the installation, and a Shortcut
+# in the Windows menu to point to that.
+# Also add the components generated to a feature, put in OUTFEATURES.
+#
+# TODO: We ought to have a Features column in the links.in file,
+# otherwise, the local doc link is always installed.
+#
+ProcessLinks() {
+ # Set a var to a carriage return without actually putting one in this file
+ local CR=`echo A | tr A '\015'`
+ local InLinks="infiles.tmp"; CleanInputFile "$1" "$InLinks" 3 4
+ local here_win=`cygpath -w $(pwd)`
+ # TODO: maybe get a real modification time, but not sure why we need it.
+ local MODTIMEHEX="0000000007DCC301DE"
+ XmlLevel=6
+ local OutFeatures="$2"
+
+ Xecho + "<Feature Id=\"LinksFeature\" Title=\"Links\"" >> $OutFeatures
+ Xecho " Description=\"Links\" Display=\"hidden\"" >> $OutFeatures
+ Xecho " Level=\"1\" AllowAdvertise=\"no\"" >> $OutFeatures
+ Xecho " ConfigurableDirectory=\"INSTALLUTIL\"" >> $$OUTFeatures
+ Xecho " Absent=\"disallow\">" >> $OutFeatures
+
+ Xecho "<DirectoryRef Id=\"INSTALLUTIL\">"
+ Xecho " <Directory Id=\"INSTALLURL\" Name=\"url\">"
+ Xecho "WIX_DB_SET_CURDIR(/installutil/url)"
+ cat $InLinks | (
+ read line
+ while [ "$line" != '' ]; do
+ local Shortname=`echo "$line" | cut -f 1 | StripDoubleQuotes`
+ local Name=`echo "$line" | cut -f 2 | StripDoubleQuotes`
+ local Url=`echo "$line" | cut -f 3 | StripDoubleQuotes`
+ read line
+
+ # We register the name .bdbsc extension to get the proper icon
+ local UrlName="$Shortname.bdbsc"
+ local UrlShortName="$Shortname.d1b"
+ local TargetFile="[INSTALLDIR]\\installutil\\url\\$UrlName"
+ local CreateUrlFile=true
+ local CommandShortcut=false
+ local Program=""
+ case "$Url" in
+ file:* ) CreateUrlFile=false
+ TargetFile=`echo $Url | sed -e 's/file://'`
+ TargetFile="[INSTALLDIR]"`cygpath -w $TargetFile`;;
+ cmd:* ) CreateUrlFile=false
+ UrlName="$Shortname.bat"
+ UrlShortName="$Shortname.bat"
+ TargetFile="[INSTALLDIR]\\installutil\\url\\$UrlName"
+ Program=`echo $Url | sed -e 's/cmd://'`
+ CommandShortcut=true;;
+ esac
+
+ Xecho "WIX_DB_SET_CURFILE($Shortname)"
+ Xecho + "<Component Id=\"Links.$Shortname\""
+ Xecho " $PERSISTGUID"
+ Xecho " SharedDllRefCount=\"yes\" Location=\"either\">"
+
+ if $CreateUrlFile; then
+ echo "[Default]$CR" > $UrlName
+ echo "BASEURL=$Url$CR" | RunM4 >> $UrlName || exit 1
+ echo "[InternetShortcut]$CR" >> $UrlName
+ echo "URL=$Url$CR" | RunM4 >> $UrlName || exit 1
+ echo "Modified=$MODTIMEHEX$CR" >> $UrlName
+ # TODO: we could have an Entry for IconFile=oracleweb.ico IconIndex=1?
+ echo ''
+ Xecho "<File Id=\"File.$Shortname\" "
+ Xecho " LongName=\"$UrlName\" Name=\"$UrlShortName\""
+ Xecho " Compressed=\"yes\" DiskId=\"1\""
+ Xecho " src=\"$here_win\\$UrlName\" />"
+ fi
+
+ if $CommandShortcut; then
+ echo "@echo off" > $UrlName
+ echo "set DBROOTDIR=" >> $UrlName
+ echo "for /F \"tokens=3 delims= \" %%A in ('REG QUERY \"HKLM\\SOFTWARE\\Oracle\\$PRODUCT_NAME\\$PRODUCT_VERSION\" /v RootDirectory') do set DBROOTDIR=%%A" >> $UrlName
+ echo "if ERRORLEVEL 2 goto MISSING" >> $UrlName
+ echo "if not defined DBROOTDIR goto MISSING" >> $UrlName
+ echo "set FN=\"%DBROOTDIR%$Program\"" >> $UrlName
+ echo "if not exist %FN% goto NOTFOUND" >> $UrlName
+ echo "cmd /k \"%DBROOTDIR%$Program\"$CR" >> $UrlName
+ echo "goto END" >> $UrlName
+ echo ":NOTFOUND" >> $UrlName
+ echo "echo" >> $UrlName
+ echo "echo Error: The program does not appear to be installed." >> $UrlName
+ echo "echo" >> $UrlName
+ echo "cmd /k" >> $UrlName
+ echo "goto END" >> $UrlName
+ echo ":MISSING" >> $UrlName
+ echo "echo" >> $UrlName
+ echo "echo NOTE:" >> $UrlName
+ echo "echo The $PRODUCT_NAME version could not be determined." >> $UrlName
+ echo "echo If you are running on Windows 2000, make sure the" >> $UrlName
+ echo "echo REG.EXE program is installed from the Tools disk" >> $UrlName
+ echo "echo" >> $UrlName
+ echo "cmd /k" >> $UrlName
+ echo ":END" >> $UrlName
+
+ Xecho "<File Id=\"File.$Shortname\" "
+ Xecho " LongName=\"$UrlName\" Name=\"$UrlShortName\""
+ Xecho " Compressed=\"yes\" DiskId=\"1\""
+ Xecho " src=\"$here_win\\$UrlName\" />"
+
+ Xecho "<Shortcut Id=\"Short.$Shortname\" Directory=\"BerkeleyDbMenu\""
+ Xecho " Name=\"$Shortname\" LongName=\"$Name\""
+ Xecho " WorkingDirectory=\"INSTALLDIR\""
+ Xecho " Target='$TargetFile'"
+ Xecho " Show=\"normal\" />"
+ else
+ Xecho "<Shortcut Id=\"Short.$Shortname\" Directory=\"BerkeleyDbMenu\""
+ Xecho " Name=\"$Shortname\" LongName=\"$Name\""
+ Xecho " Target='$TargetFile'"
+ Xecho " Show=\"normal\" />"
+ fi
+
+
+ Xecho - "</Component>"
+
+ Xecho "<ComponentRef Id=\"Links.$Shortname\" />" >> $OutFeatures
+ done
+ return 0
+ ) || Error "Error processing links" || exit 1
+
+ Xecho "</Directory>"
+ Xecho "</DirectoryRef>"
+ Xecho - "</Feature>" >> $OutFeatures
+}
+
+# ProcessOneDirectory(DIRECTORYNAME)
+# Called by ProcessFeatures.
+# Argument is the directory name to process
+# Standard input is cleaned up files.in (dirname is 3rd column)
+# Standard output will be WiX XML Component/File entries
+#
+ProcessOneDirectory()
+{
+ Dir="$1"
+ grep " ${Dir} " | (
+ read line
+ while [ "$line" != '' ]; do
+ local feature=`echo "$line" | cut -f 1`
+ local srcfile=`echo "$line" | cut -f 2`
+ local targetdir=`echo "$line" | cut -f 3`
+ local shortname=`echo "$line" | cut -f 4`
+
+ ProcessOneDirectoryFile "$feature" "$srcfile" "$targetdir" "$shortname" || exit 1
+ read line
+ done
+ return 0
+ ) || Error "Error processing directory $Dir" || exit 1
+}
+
+# ProcessOneDirectoryFile(DIRECTORYNAME)
+# Called by ProcessOneDirectory to process a single file in a directory.
+# Standard output will be a single WiX XML Component/File entries
+#
+ProcessOneDirectoryFile()
+{
+ local feature="$1"
+ local srcfile="$2"
+ local targetdir="$3"
+ local shortname="$4"
+ local base=`basename $srcfile`
+
+ #echo "processing file $srcfile in $feature to directory $targetdir..." >&2
+
+ # Prepend the WIX_DB_TOP unless the source file is absolute
+
+ local root=
+ local checkfile=
+ local wsrcfile=
+
+ case "$srcfile" in
+ /* ) root=""
+ wsrcfile=`cygpath -w $srcfile`
+ checkfile="$srcfile"
+ ;;
+ * ) root="$PRODUCT_BLDDIR/"
+ wsrcfile="WIX_DB_TOP()\\`cygpath -w $srcfile`"
+ checkfile="$PRODUCT_BLDDIR/$srcfile"
+ ;;
+ esac
+
+ # If srcfile ends in / then we'll use tallow to walk the directory
+ case "$srcfile" in
+ */ ) if [ ! -d "$root$srcfile" ]; then
+ Error "$root$srcfile: not a directory"
+ exit 1
+ fi
+ Progress -minor " expanding $root$srcfile..."
+ RunTallow "$root$srcfile"
+ return 0
+ ;;
+ *'*'* )
+ local dirname=`dirname "$root$srcfile"`
+ RunTallow "$dirname" -df "$base"
+ return 0
+ ;;
+ esac
+
+ if [ "$shortname" = '' ]; then
+ shortname=`GetShortName "$base"`
+ fi
+ ID=`NextId`
+
+ if [ ! -r "$checkfile" ]; then
+ Error "$srcfile: file in feature $feature does not exist"
+ Error " curdir=`pwd`, pathname=$checkfile"
+ exit 1
+ fi
+
+ Xecho "WIX_DB_SET_CURFILE(${base})"
+ Xecho + "<Component Id=\"$feature.$ID\" Location=\"either\" $PERSISTGUID>"
+ Xecho "<File Id=\"${feature}.${ID}\" Name=\"${shortname}\" LongName=\"${base}\" Compressed=\"yes\" KeyPath=\"yes\" DiskId=\"1\" src=\"${wsrcfile}\" />"
+ Xecho - "</Component>"
+ return 0
+}
+
+# ProcessOneFeature(FEATUREPATH, SHORTNAME, DESCRIPTION, OPTS, INDIRECTORYFILE,
+# OUTFEATURE, OUTSET)
+# Called by ProcessFeatures to process a line in the features.in file.
+# The first three arguments are the values of the first three columns:
+# the feature dependency path (e.g. "Java/JavaExamples"), the short
+# name, and a descriptive name. The last argument is the directory
+# file that lists the components. We use the last name of the feature
+# path (e.g. JavaExamples) to locate all components (really directories)
+# named accordingly, so they can be listed as needed parts of the Feature.
+# Standard output will be WiX XML Feature entries.
+#
+ProcessOneFeature() {
+ local featurename="$1"
+ local shortname="$2"
+ local opts="$4"
+ local dirfile="$5"
+ local outfeature="$6"
+ local outset="$7"
+
+ XmlLevel=4
+ local featcount=0
+ local featurestring=""
+ if [ $(SlashCount $featurename) -gt 0 ]; then
+ local parent=`echo $featurename | sed -e 's:/[^/]*$::' -e 's:.*/::'`
+ featurename=`echo $featurename | sed -e 's:^.*/::'`
+ featcount=1
+ Xecho "<FeatureRef Id=\"$parent\">" >> $outfeature
+ fi
+
+
+ # TODO: how to get +default to work?
+ # have tried messing with level="0" (doesn't show it)
+ # InstallDefault=\"source\" (doesn't make a difference)
+ #
+ local leveldebug="Level=\"4\""
+ local levelparam="Level=\"1\""
+ local leveldisable="Level=\"0\""
+ local defparam="InstallDefault=\"source\""
+ local displayparam="Display=\"expand\""
+ local params="AllowAdvertise=\"no\""
+ local regfeature=""
+
+ local descparam=""
+ if [ "$3" != '' ]; then
+ descparam="Description=\"$3\""
+ fi
+
+ local opt
+ local reqtext=""
+ local isdebugFeature=false
+ for opt in $opts; do
+ case "$opt" in
+ +default ) ;;
+ +required ) params="$params Absent=\"disallow\""
+ reqtext=" (required)";;
+ +invisible ) displayparam="Display=\"hidden\""
+ params="$params Absent=\"disallow\"";;
+ +debug ) isdebugFeature=true;;
+
+ * ) Error "features.in: Bad option $opt"
+ exit 1;;
+ esac
+ done
+
+
+# (PBR)
+# I tried to get debugging features to work but I could not. The last thing I
+# tried was to set either ADDSOURCE or INSTALLLEVEL. Neither of these solutions
+# will cause the feature conditions to rerun. The only thing I've found to do
+# that is to rerun CostFinalize. The problem with this is it will re-enable all
+# the options again. I'm keeping the basic framework for +debug support
+ if "$isdebugFeature"; then
+ regfeature="${featurename:1}"
+ echo "regfeature = $regfeature"
+
+ Xecho + "<Feature Id=\"$featurename\" Title=\"$shortname$reqtext\" $descparam $params $displayparam $leveldebug $defparam>" >> $outfeature
+ else
+ Xecho + "<Feature Id=\"$featurename\" Title=\"$shortname$reqtext\" $descparam $params $displayparam $levelparam $defparam>" >> $outfeature
+ fi
+
+
+ grep 'Component.*Id="'$featurename'[.0-9]*"' "$dirfile" | sed -e 's/\(Id="[^"]*"\).*/\1 \/>/' -e 's/Component /ComponentRef /' >> $outfeature
+
+ # Create a separate subfeature for any environment variables
+ # associated with the main feature.
+ # The <Condition> stuff is the magic that enables/disables
+ # setting the environment variables depending on the check box property.
+
+ Xecho + "<Feature Id=\"env.$featurename\" Title=\"env vars\" $params Display=\"hidden\" $levelparam $defparam>" >> $outfeature
+
+ Xecho "<Condition $leveldisable><![CDATA[EnvironmentSetCheck<>1]]></Condition>" >> $outfeature
+ Xecho "<Condition $levelparam><![CDATA[EnvironmentSetCheck=1]]></Condition>" >> $outfeature
+ grep 'Component.*Id="env\.'$featurename'[.0-9]*"' "$dirfile" | sed -e 's/\(Id="[^"]*"\).*/\1 \/>/' -e 's/Component /ComponentRef /' >> $outfeature
+
+ Xecho - "</Feature>" >> $outfeature
+ Xecho - "</Feature>" >> $outfeature
+
+ while [ "$featcount" -gt 0 ]; do
+ Xecho - "</FeatureRef>" >> $outfeature
+ featcount=$(($featcount - 1))
+ done
+
+ # Append the name to the feature list if it is to be installed.
+ # This publish fragment gets 'executed' when leaving the
+ # dialog to select features. Note that we have to quote
+ # the comma for m4 (`,') since this appears in a macro usage.
+ #
+
+# (PBR)
+# This code sets ADDSOURCE to show which debug options to include. This does not work
+ # If this is a debug feature, only turn on the value if the parent is on
+ if "$isdebugFeature"; then
+ regfeature="${featurename:1}"
+
+# Xecho "<Publish Property=\"ADDSOURCE\" Value=\"[ADDSOURCE]\`,'\">" >> $outset
+# Xecho " <![CDATA[&${regfeature} = 3 AND DebugCheck=\"yes\" AND ADDSOURCE <> NULL]]></Publish>" >> $outset
+
+# Xecho "<Publish Property=\"ADDSOURCE\" Value=\"[ADDSOURCE]${featurename}\">" >> $outset
+# Xecho " <![CDATA[&${regfeature} = 3 AND DebugCheck=\"yes\"]]></Publish>" >> $outset
+
+ Xecho "<Publish Property=\"FeatureList\" Value=\"[FeatureList]\`,' ${shortname}\">" >> $outset
+ Xecho " <![CDATA[&${regfeature} = 3 AND DebugCheck=\"yes\"]]></Publish>" >> $outset
+
+ else
+ Xecho "<Publish Property=\"FeatureList\" Value=\"[FeatureList]\`,' ${shortname}\">" >> $outset
+ Xecho " <![CDATA[&${featurename} = 3]]></Publish>" >> $outset
+ fi
+}
+
+# ProcessOneEnv(FEATURE, ENVNAME, ENVVALUE, OPTS, OUTDIRS, OUTSET)
+# Called by ProcessFeatures to process a line in the environment.in file.
+# The four arguments are the values of the four columns.
+# The output will be into two files:
+# OUTDIRS: WiX XML Component entries, that contain environment values.
+# This controls the actual setting of the variables.
+# OUTSET: WiX XML to set the installer variables if an env variable
+# is set or a feature selected.
+#
+ProcessOneEnv() {
+ local feature="$1"
+ local envname="$2"
+ local envvalue="$3"
+ local opts="$4"
+ local outdirs="$5"
+ local outset="$6"
+
+ # Make the path uniform.
+ # echo "c:\Program Files\...\/Lib/Hello" | sed -e 's:\\/:\\:' -e 's:/:\\:g`
+ # This produces c:\Program Files\...\Lib\Hello
+ case "$envvalue" in
+ /* ) envvalue=`echo "$envvalue" | sed -e 's:^/::'`
+ esac
+
+ local path="[INSTALLDIR]$envvalue"
+
+ local opt
+ part="last"
+ for opt in $opts; do
+ case "$opt" in
+ +first ) part="first";;
+ +last ) part="last";;
+ * ) Error "environment.in: Bad option $opt"
+ exit 1;;
+ esac
+ done
+
+ # Generate the OUTDIRS fragment
+ # This looks like:
+ #
+ # <Component Id="env.CoreAPI.43" Guid="4B75755F-1129-292C-3434-238410000247">
+ # <Environment Id="env.44" Name="+-LIB" Action="set"
+ # Permanent="no" Part="first" Value="[INSTALLDIR]Lib" />
+ # </Component>
+ #
+ # Having a unique guid makes uninstall work.
+ # Note: We really want these installed as System rather than
+ # User vars (using the System="yes" tag), but only if user
+ # installs for *all* users. There is no convenient way to
+ # do that, so we leave them as default (User variables).
+
+
+ XmlLevel=4
+ local Id=`NextId`
+ Xecho "WIX_DB_SET_CURFILE(${envname})" >> $outdirs
+ Xecho + "<Component Id=\"env.$feature.$Id\" $PERSISTGUID>" >> $outdirs
+ Id=`NextId`
+
+ Xecho "<Environment Id=\"env.$Id\" Name=\"+-$envname\" Action=\"set\"" >> $outdirs
+ Xecho " Permanent=\"no\" Part=\"$part\" Value=\"$path\" />" >> $outdirs
+
+ Xecho "</Component>" >> $outdirs
+
+ # Generate the OUTSET fragment
+ # This looks like:
+ #
+ # <Publish Property="CLASSPATHValue" Value="[INSTALLDIR]Lib/db.jar;[CLASSPATHValue]">
+ # <![CDATA[&JavaAPI = 3]]></Publish>
+ # <Publish Property="CLASSPATHEscValue" Value="[INSTALLDIR]Lib/db.jar;[CLASSPATHEscValue]">
+ # <![CDATA[&JavaAPI = 3]]></Publish>
+ #
+ # This is equivalent to pseudocode:
+ # if (InstallFeature(JavaAPI)) {
+ # Prepend CLASSPATHValue with "Lib/db.jar;"
+ # Prepend CLASSPATHEscValue with "Lib/db.jar;"
+ # }
+ #
+ XmlLevel=4
+ Xecho "<Publish Property=\"${envname}Value\" Value=\"[INSTALLDIR]${envvalue};[${envname}Value]\">" >> $outset
+ Xecho " <![CDATA[&${feature} = 3]]></Publish>" >> $outset
+
+ Xecho "<Publish Property=\"${envname}EscValue\" Value=\"[INSTALLDIR]${envvalue};[${envname}EscValue]\">" >> $outset
+ Xecho " <![CDATA[&${feature} = 3]]></Publish>" >> $outset
+
+
+}
+
+# CreateProperty(ID, VALUE)
+# Generate a <Property...> tag on the stdout
+CreateProperty() {
+ Xecho "<Property Id=\"$1\" Hidden=\"yes\"><![CDATA[$2]]></Property>"
+}
+
+# ProcessTagProperties(OUTPROPS)
+# Generate some identification tags as properties.
+# This will let us look at an installer and figure out
+# when it was built, etc.
+ProcessTagProperties() {
+ local outprops="$1"
+ local insdate=`date`
+ XmlLevel=4
+
+ CreateProperty _DB_MSI_INSTALLER_DATE "$insdate" >> $outprops
+ CreateProperty _DB_MSI_PRODUCT_NAME "$PRODUCT_NAME" >> $outprops
+ CreateProperty _DB_MSI_PRODUCT_VERSION "$PRODUCT_VERSION" >> $outprops
+ CreateProperty ARPCOMMENTS "Installer for $PRODUCT_NAME $PRODUCT_VERSION built on $insdate" >> $outprops
+}
+
+# ProcessEnv(INENVFILE, INBATFILE, OUTPROPS, OUTSET, OUTSHOW)
+# We generate some Property magic to show the user what is set.
+#
+ProcessEnv() {
+ InEnv="inenv.tmp"; CleanInputFile "$1" "$InEnv" 3 4
+ inbat="$2"
+ outprops="$3"
+ outset="$4"
+ outshow="$5"
+
+ # Get a list of the environment variables
+ local envvar
+ local envvars=`cut -f 2 < $InEnv | sort | uniq`
+
+ # For each environment var, create lines that declare
+ # a pair of properties in the envprops.wixinc file like:
+ #
+ # <Property Id="CLASSPATHValue" Hidden="yes"></Property>
+ # <Property Id="CLASSPATHEscValue" Hidden="yes"></Property>
+ #
+ # And create lines in the envset.wixinc file like:
+ #
+ # <Publish Property="CLASSPATHValue" Value="%CLASSPATH%">
+ # <![CDATA[1]]></Publish>
+ # <Publish Property="CLASSPATHEscValue" Value="\\%CLASSPATH\\%">
+ # <![CDATA[1]]></Publish>
+ #
+ # More will be added to that file later.
+ # Then, create lines in the envshow.wixinc file like:
+ #
+ # <Control Id="CLASSPATHText" Type="Text"
+ # X="23" Width="316" PARTIALHEIGHT(10, 2)
+ # TabSkip="no" Text="CLASSPATH:" />
+ #
+ # <Control Id="CLASSPATHValueText" Type="Text"
+ # X="37" Width="316" PARTIALHEIGHT(20, 7)
+ # TabSkip="no" Text="[CLASSPATHValue]" />
+
+ for envvar in $envvars; do
+ XmlLevel=4
+ CreateProperty "${envvar}Value" "" >> $outprops
+ CreateProperty "${envvar}EscValue" "" >> $outprops
+
+ XmlLevel=4
+ Xecho "<Publish Property=\"${envvar}Value\" Value=\"%${envvar}%\">" >> $outset
+ Xecho " <![CDATA[1]]></Publish>" >> $outset
+ Xecho "<Publish Property=\"${envvar}EscValue\" Value=\"\\%${envvar}\\%\">" >> $outset
+ Xecho " <![CDATA[1]]></Publish>" >> $outset
+
+ XmlLevel=4
+ Xecho "<Control Id=\"${envvar}Text\" Type=\"Text\"" >> $outshow
+ Xecho " X=\"23\" Width=\"316\" PARTIALHEIGHT(10, 2)" >> $outshow
+ Xecho " TabSkip=\"no\" Text=\"${envvar}:\" />" >> $outshow
+
+ Xecho "<Control Id=\"${envvar}ValueText\" Type=\"Text\"" >> $outshow
+ Xecho " X=\"37\" Width=\"316\" PARTIALHEIGHT(20, 7)" >> $outshow
+ Xecho " TabSkip=\"no\" Text=\"[${envvar}Value]\" />" >> $outshow
+
+ done
+
+ # Create the dbvars.bat file from the .bat template file
+ # TODO: the bat template file currently knows the variables
+ # and their values, it should get them from the environment.in
+
+ RunM4 <"$inbat" >"$PRODUCT_STAGE/dbvars.bat" || Error "m4 failed" || exit 1
+}
+
+
+# CleanInputFile(INFILENAME, OUTFILENAME, MINELEMENTS, MAXELEMENTS)
+# A filter to preprocess and validate input files.
+# We end up without comment lines, a single tab between elements,
+# and a trailing tab.
+# Also some selected shell variables are expanded for convenience.
+# We verify that each line has the number of elements that fall within
+# the given min and max.
+#
+CleanInputFile() {
+ sed \
+ -e 's/#.*//' \
+ -e 's/ * / /g' \
+ -e 's/ */ /g' \
+ -e '/^[ ]*$/d' \
+ -e 's/$/ /' \
+ -e 's/ */ /g' \
+ -e 's:\${PRODUCT_VERSION}:'"${PRODUCT_VERSION}":g \
+ -e 's:\${PRODUCT_MAJOR}:'"${PRODUCT_MAJOR}":g \
+ -e 's:\${PRODUCT_MINOR}:'"${PRODUCT_MINOR}":g \
+ -e 's:\${PRODUCT_PATCH}:'"${PRODUCT_PATCH}":g \
+ -e 's:\${PRODUCT_MAJMIN}:'"${PRODUCT_MAJMIN}":g \
+ -e 's:\${PRODUCT_MSVC_VERSION}:'"${PRODUCT_MSVC_VERSION}":g \
+ -e 's:\${PRODUCT_STAGE}:'"${PRODUCT_STAGE}":g \
+ -e 's:\${PRODUCT_SHARED_WINMSIDIR}:'"${PRODUCT_SHARED_WINMSIDIR}":g \
+ -e 's/^[\r \t]*$//' \
+ < "$1" > "$2"
+
+ # count tabs on each line
+ sed -e 's/[^\t]//g' -e 's/[\t]/x/g' < "$2" | (
+ read line
+ linecount=1
+ while [ "$line" != '' ]; do
+ chars=`echo "$line" | wc -c`
+ chars=$(($chars - 1)) # Remove newline
+ if [ "$chars" -lt "$3" -o "$chars" -gt "$4" ]; then
+ Error "$1: Input file error on or after line $linecount"
+ fi
+ read line
+ linecount=$(($linecount + 1))
+ done
+ )
+}
+
+# StripDoubleQuotes()
+# In some input files, we allow double quotes around
+# multi-word strings for readability. We strip them
+# here from standard input and write to standard output.
+# We only expect them at the beginning and end.
+#
+StripDoubleQuotes() {
+ sed -e 's/^"//' -e 's/"$//'
+}
+
+# IndentXml(PLUSMINUS_ARG)
+# A global variable $XmlLevel is kept for the indent level.
+# Every call creates blank output that matches the indent level.
+# In addition, with a '-' argument, the indent level
+# decrements by one before printing.
+# With a '+', the indent level increments after printing.
+# This is generally just used by Xecho
+#
+XmlLevel=0
+IndentXml() {
+ if [ "$1" = '-' -a $XmlLevel != 0 ]; then
+ XmlLevel=$(($XmlLevel - 1))
+ fi
+ local idx=0
+ while [ "$idx" != "$XmlLevel" ]; do
+ echo -n ' '
+ idx=$(($idx + 1))
+ done
+ if [ "$1" = '+' ]; then
+ XmlLevel=$(($XmlLevel + 1))
+ fi
+}
+
+# Xecho [ - | + ] ...
+# echoes arguments (like) echo, except that the output
+# is indented for XML first. If +, the indentation changes
+# after printing, if -, the indentation changes before printing.
+#
+Xecho()
+{
+ local xarg=
+ if [ "$1" = '-' -o "$1" = '+' ]; then
+ xarg="$1"
+ shift
+ fi
+ IndentXml $xarg
+ echo "$@"
+}
+
+# SlashCount(PATH)
+# Returns the number of slashes in its argument
+# Note, we are relying on some advanced
+# features of bash shell substitution
+#
+SlashCount()
+{
+ local allslash=`echo "$1" | sed -e 's:[^/]*::g'`
+ echo "${#allslash}"
+}
+
+# ProcessDirTransition(PREVDIR, NEXTDIR)
+# Used by ProcessFeatures to create the parts
+# of an WiX <Directory> heirarchy (on stdout) needed to
+# transition from directory PREVDIR to NEXTDIR.
+# This may include any needed </Directory> entries as well.
+# For example, ProcessDirTransition /Bin/Stuff /Bin/Foo/Bar
+# produces:
+# </Directory> ...to go up one from 'Stuff'
+# <Directory Foo>
+# <Directory Bar>
+#
+ProcessDirTransition() {
+ local p="$1"
+ local n="$2"
+ if [ "$p" = '' ]; then p=/; fi
+ if [ "$n" = '' ]; then n=/; fi
+ local nextdir="$2"
+
+ # The number of slashes in $p is the current directory level.
+ XmlLevel=$(($(SlashCount $p) + 4))
+
+ while [ "$p" != / ]; do
+ if [ "${n#${p}}" != "$n" ]; then
+ break
+ fi
+
+ # go up one level, and keep $p terminated with a /
+ p=`dirname $p`
+ case "$p" in
+ */ ) ;;
+ * ) p=$p/;;
+ esac
+ Xecho - "</Directory>"
+ done
+ n=${n#${p}}
+ while [ "$n" != '' ]; do
+ local dirname=`echo $n | sed -e 's:/.*::'`
+ local cleanname=`CleanFileName "$dirname"`
+ local shortname=`GetShortName "$cleanname"`
+ local dirid=`NextId`
+
+ local larg=""
+ if [ "${shortname}" != "${dirname}" ]; then
+ larg="LongName=\"${dirname}\""
+ fi
+ Xecho + "<Directory Id=\"${cleanname}Dir.$dirid\" Name=\"${shortname}\" $larg>"
+
+ n=`echo $n | sed -e 's:^[^/]*/::'`
+ done
+
+ Xecho "WIX_DB_SET_CURDIR($nextdir)" # Tell the m4 macro what the current dir is
+}
+
+# SetupErrorLog()
+# Given the global variable ERRORLOG for the name of the
+# error output file, do any setup required to make that happen.
+#
+SetupErrorLog() {
+
+ # Before we start to use ERRORLOG, we get a full pathname,
+ # since the caller may change directories at times.
+ case "$ERRORLOG" in
+ /* ) ;;
+ *) ERRORLOG=`pwd`"/$ERRORLOG" ;;
+ esac
+
+ rm -f $ERRORLOG
+
+ # File descriptor tricks.
+ # Duplicate current stderr to 15, as we'll occasionally
+ # need to report progress to it. Then, redirect all
+ # stderr from now on to the ERRORLOG.
+ #
+ exec 15>&2
+ exec 2>>$ERRORLOG
+}
+
+# RequireCygwin
+# Cygwin does not install certain needed components by default.
+# Check to make sure that everything needed by the script
+# and functions is here.
+#
+RequireCygwin() {
+ Progress -minor "checking for Cygwin..."
+ RequireFileInPath PATH "$PATH" m4
+ RequireFileInPath PATH "$PATH" gcc
+ RequireFileInPath PATH "$PATH" make
+ RequireFileInPath PATH "$PATH" unzip
+ RequireFileInPath PATH "$PATH" bc
+ RequireFileInPath PATH "$PATH" openssl # needed for MD5 hashing
+}
+
+# RequireJava()
+# A java SDK (with include files) must be installed
+#
+RequireJava() {
+ Progress -minor "checking for Java..."
+ RequireFileInPath INCLUDE "$INCLUDE" jni.h
+ RequireFileInPath INCLUDE "$INCLUDE" jni_md.h
+ RequireFileInPath PATH "$PATH" jar.exe
+ RequireFileInPath PATH "$PATH" javac.exe
+}
+
+# RequireTcl()
+# A Tcl SDK (with compatible .lib files) must be installed
+#
+RequireTcl() {
+ Progress -minor "checking for Tcl..."
+ RequireFileInPath INCLUDE "$INCLUDE" tcl.h
+ RequireFileInPath LIB "$LIB" tcl84g.lib
+ RequireFileInPath LIB "$LIB" tcl84.lib
+}
+
+# RequireWix()
+# WiX must be installed
+#
+RequireWix() {
+ Progress -minor "checking for WiX..."
+ RequireFileInPath PATH "$PATH" candle.exe
+ RequireFileInPath PATH "$PATH" light.exe
+ RequireFileInPath PATH "$PATH" tallow.exe
+}
+
+# RequirePerl()
+# Perl must be installed
+#
+RequirePerl() {
+ Progress -minor "checking for Perl..."
+ RequireFileInPath PATH "$PATH" perl.exe
+}
+
+# RequirePython()
+# Python (and include files) must be installed
+#
+RequirePython() {
+ Progress -minor "checking for Python..."
+ RequireFileInPath INCLUDE "$INCLUDE" Python.h
+ RequireFileInPath PATH "$PATH" python.exe
+}
+
+# CreateDbPerl()
+# Build Perl interface (for Berkeley DB only).
+#
+CreateDbPerl() {
+
+ # First build Berkeley DB using cygwin, as that version is
+ # needed for the Perl build
+ local here=`pwd`
+ Progress "building using Cygwin tools (needed for perl)"
+ cd "${PRODUCT_DBBUILDDIR}"
+ insdir="${PRODUCT_STAGE}/install_unix"
+ ../dist/configure --prefix="$insdir" >>$ERRORLOG || exit 1
+ make install >>$ERRORLOG || exit 1
+
+ Progress "building perl"
+ cd ../perl/BerkeleyDB
+ BERKELEYDB_INCLUDE="$insdir/include" BERKELEYDB_LIB="$insdir/lib" \
+ perl Makefile.PL >>$ERRORLOG || exit 1
+ make >>$ERRORLOG
+ cd $here
+}
+
+# CreateWindowsSystem()
+# Copy Windows system files
+#
+CreateWindowsSystem() {
+ local here=`pwd`
+ Progress "Copy Windows system files..."
+ cd "${PRODUCT_SUB_BLDDIR}"
+
+ if [ $PRODUCT_MSVC_VERSION = "80" ]; then
+ cp -f "$MSVC_ROOT_DIR/VC/redist/x86/Microsoft.VC80.CRT/msvcm80.dll" build_windows/Win32/Release/ || exit 1
+ cp -f "$MSVC_ROOT_DIR/VC/redist/x86/Microsoft.VC80.CRT/msvcp80.dll" build_windows/Win32/Release/ || exit 1
+ cp -f "$MSVC_ROOT_DIR/VC/redist/x86/Microsoft.VC80.CRT/msvcr80.dll" build_windows/Win32/Release/ || exit 1
+ cp -f "$MSVC_ROOT_DIR/VC/redist/x86/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest" build_windows/Win32/Release/ || exit 1
+ cp -f "$MSVC_ROOT_DIR/VC/redist/x86/Microsoft.VC80.CRT/msvcm80.dll" build_windows/Win32/Debug/ || exit 1
+ cp -f "$MSVC_ROOT_DIR/VC/redist/x86/Microsoft.VC80.CRT/msvcp80.dll" build_windows/Win32/Debug/ || exit 1
+ cp -f "$MSVC_ROOT_DIR/VC/redist/x86/Microsoft.VC80.CRT/msvcr80.dll" build_windows/Win32/Debug/ || exit 1
+ cp -f "$MSVC_ROOT_DIR/VC/redist/x86/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest" build_windows/Win32/Debug/ || exit 1
+ else
+ cp -f $SYSTEMROOT/system32/msvcr$PRODUCT_MSVC_VERSION.dll build_windows/Win32/Release/ || exit 1
+ cp -f $SYSTEMROOT/system32/msvcp$PRODUCT_MSVC_VERSION.dll build_windows/Win32/Release/ || exit 1
+ cp -f $SYSTEMROOT/system32/msvcr$PRODUCT_MSVC_VERSION.dll build_windows/Win32/Debug/ || exit 1
+ cp -f $SYSTEMROOT/system32/msvcp$PRODUCT_MSVC_VERSION.dll build_windows/Win32/Debug/ || exit 1
+ fi
+ cd $here
+}
+
+# CreateInclude(DIR, FILES)
+# Create an include directory populated with the files given
+#
+CreateInclude() {
+
+ local incdir="$1"
+ shift
+
+ Progress "creating the "$incdir" directory..."
+ rm -rf "$incdir"
+ mkdir "$incdir" || exit 1
+ cp -r "$@" "$incdir"
+}
+
+# CreateWindowsBuild()
+# Do the windows build as defined by the winbuild.bat file
+#
+CreateWindowsBuild() {
+ local here=`pwd`
+ Progress "building using Windows tools..."
+ cd "${PRODUCT_SUB_BLDDIR}" || exit 1
+
+ # Before starting, copy any installer tools here.
+ # This makes building these tools straightforward
+ # and the results are left in the build directory.
+ #
+ cp -r ${PRODUCT_SHARED_WINMSIDIR}/instenv .
+
+ # We create a wbuild.bat file, which is essentially
+ # identical, except it has the carriage returns added.
+ # This allows us to use our favorite editors on winbuild.bat .
+ #
+ sed -e 's/$//' < ${PRODUCT_STAGE}/../winbuild.bat | tr '\001' '\015' > wbuild.bat
+ rm -f winbld.out winbld.err
+ touch winbld.out winbld.err
+ echo "Build output and errors are collected in" >> $ERRORLOG
+ echo " winbld.{out,err} until the build has completed." >> $ERRORLOG
+ cmd.exe /x /c call wbuild.bat
+ status=$?
+ cat winbld.out >> $ERRORLOG
+ if [ -s winbld.err -o "$status" != 0 ]; then
+ cat winbld.err >> $ERRORLOG
+ Error "Errors during windows build"
+ exit 1
+ fi
+ cd $here
+}
+
+# CreateSources(SOURCESDIR,DOCDIR...)
+# Create the sources directory, ignoring things in the docdirs
+#
+CreateSources() {
+ local sources="$1"
+
+ Progress "creating the Sources directory in $sources..."
+ rm -rf "$sources" "$sources/../docs/"
+ unzip -q -u ../../$OPT_INFILE -d tmp_dir || exit 1
+ mv ./tmp_dir/${dbver}/docs "$sources/../" || exit 1
+ mv ./tmp_dir/${dbver} "$sources" || exit 1
+}
+
+# Usage()
+# Show the usage for this script.
+#
+Usage()
+{
+ echo "Usage: s_winmsi [ options ]" >&2
+ echo "Options: " >&2
+ echo " -input file use file rather than ${PRODUCT_ZIP_FILEFMT}" >&2
+ echo " where X.Y.Z is defined by ../RELEASE" >&2
+ echo " -output file use file rather than ${PRODUCT_MSI_FILEFMT}" >&2
+ echo " where X.Y.Z is defined by ../RELEASE" >&2
+ echo " -usebuild DIR use DIR for exes, DLLs, etc. " >&2
+ echo " rather than building from scratch" >&2
+ echo " -preserve preserve the winmsi/msi_staging directory" >&2
+ echo " -skipgen skip generating m4 include files" >&2
+}
+
+# SetupOptions()
+# Parse command line options and set global variables as indicated below.
+#
+SetupOptions() {
+ OPT_USEBUILD=
+ OPT_PRESERVE=false
+ OPT_CONTINUE=false
+ OPT_INFILE=
+ OPT_OUTFILE=
+ OPT_SKIPGEN=false
+ while [ "$#" -gt 0 ]; do
+ arg="$1"; shift
+ case "$arg" in
+ -usebuild ) OPT_USEBUILD="$1"; shift ;;
+ -skipgen ) OPT_SKIPGEN=true ;;
+ -preserve ) OPT_PRESERVE=true;;
+ -continue ) OPT_CONTINUE=true;;
+ -input ) OPT_INFILE="$1"; shift ;;
+ -output ) OPT_OUTFILE="$1"; shift ;;
+ * )
+ echo "ERROR: Unknown argument '$arg' to s_winmsi" >&2
+ Usage
+ exit 1
+ ;;
+ esac
+ done
+ if [ "$OPT_INFILE" = '' -o ! -f "$OPT_INFILE" ]; then
+ echo "$OPT_INFILE: not found"
+ exit 1
+ fi
+}
+
+# CreateStage()
+# Create the staging area
+#
+CreateStage() {
+ Progress "creating staging area..."
+ if [ "$PRODUCT_STAGE" = '' ]; then
+ Error "PRODUCT_STAGE not set"
+ exit 1
+ fi
+ if ! $OPT_PRESERVE; then
+ trap 'rm -rf ${PRODUCT_STAGE} ; exit 0' 0 1 2 3 13 15
+ fi
+ if ! $OPT_CONTINUE; then
+ rm -rf ${PRODUCT_STAGE} || exit 1
+ else
+ # Cleanup files that would break :)
+ rm -f ${PRODUCT_STAGE}/*wxs || exit 1
+ rm -f ${PRODUCT_STAGE}/*wixinc || exit 1
+ rm -f ${PRODUCT_STAGE}/*tmp || exit 1
+ rm -f ${PRODUCT_STAGE}/*bdbsc || exit 1
+ rm -f ${PRODUCT_STAGE}/tallow* || exit 1
+ fi
+ if [ ! -d ${PRODUCT_STAGE} ]; then
+ mkdir ${PRODUCT_STAGE} || exit 1
+ fi
+
+ cd ${PRODUCT_STAGE}
+
+ Progress "extracting $OPT_INFILE..."
+ unzip -q -u ../../$OPT_INFILE || exit 1
+
+ if [ ! -d $PRODUCT_LICENSEDIR ]; then
+ Error "$OPT_INFILE: no top level $PRODUCT_LICENSEDIR directory"
+ exit 1
+ fi
+
+ # TODO: In the 4.8.12 package this file was not writable, it needs to
+ # be for the build. Make it so. Remove me.
+ chmod 664 ${PRODUCT_SRCDIR}/csharp/doc/libdb_dotnet${PRODUCT_MAJMIN}.XML
+}
+
+# CreateLicenseRtf(LICENSEIN, LICENSERTF)
+# From a text LICENSE file, create the equivalent in .rtf format.
+#
+CreateLicenseRtf() {
+ local licensein="$1"
+ local licensertf="$2"
+
+ if [ ! -f "$licensein" ]; then
+ Error "License file $licensein: does not exist"
+ exit 1
+ fi
+ Progress "creating ${licensertf}..."
+
+ # Build a list of references to components ids (i.e. directories)
+ # that are listed in the .wxs file. This is needed to refer to
+ # all of the source (sadly it appears there is no better way!)
+ #
+ if ! grep '^=-=-=-=' $licensein > /dev/null; then
+ Error "LICENSE has changed format, this script must be adapted"
+ exit 1
+ fi
+
+ sed -e '1,/^=-=-=-=-=/d' < $licensein | MakeRtf > $licensertf
+}
+
+
+# CreateMsi(INFILE,WXSFILE,MSIFILE)
+# Do the final creation of the output .MSI file.
+# It is assumed that all *.wixinc files are now in place.
+# INFILE is an absolute name of the m4 input WiX file.
+# WXSFILE is a short (basename) of the postprocessed WiX file,
+# after macro expansion, it will be left in staging directory.
+# MSIFILE is a short (basename) of the output .MSI name
+#
+CreateMsi() {
+ local infile="$1"
+ local wxs="$2"
+ local msifile="$3"
+ local o=`echo "$wxs" | sed -e 's/[.]wxs$//' -e 's/$/.wixobj/'`
+ local tmpfile="dbcore.wxs.tmp"
+
+ rm -f $o $wxs
+
+ # Preprocess the ${PROD}wix.in file, adding the things we need
+ #
+ Progress "Running m4 to create $wxs..."
+ RunM4 < "$infile" > "$PRODUCT_STAGE/$wxs" || Error "m4 failed" || exit 1
+ # Remove any stray "PUT-GUID-HERE" tags.
+ # They are added by some recent versions of WiX, including 2.0.5805.0
+ # The scripts already insert valid GUIDs.
+ sed -e 's/ Guid="PUT-GUID-HERE" / /' < "$wxs" > "$tmpfile"
+ rm -f "$wxs"
+ mv "$tmpfile" "$wxs"
+
+ local here=`pwd`
+ cd "$PRODUCT_STAGE"
+ rm -f "$o" "$msifile"
+ Progress "compiling $wxs..."
+ candle -w0 $wxs >> $ERRORLOG || Error "candle (compiler) failed" || exit 1
+
+ Progress "linking .msi file..."
+ light -o "$msifile" $o >> $ERRORLOG || Error "light (linker) failed" || exit 1
+ (rm -f "../../$msifile" && mv "$msifile" ../..) >> $ERRORLOG || exit 1
+ cd $here
+}
+
+# CreateWixIncludeFiles()
+# Do all processing of input files to produce
+# the include files that we need to process the Wix input file.
+#
+CreateWixIncludeFiles() {
+ local here=`pwd`
+ cd "$PRODUCT_STAGE"
+ # Touch all the wix include files in case any end up empty.
+ touch directory.wixinc features.wixinc envprops.wixinc \
+ envset.wixinc envshow.wixinc links.wixinc
+
+ Progress "tagging the installer..."
+ ProcessTagProperties envprops.wixinc
+
+ Progress "processing environment..."
+ ProcessEnv ../environment.in ../dbvarsbat.in envprops.wixinc envset.wixinc envshow.wixinc
+
+ Progress "processing features and files..."
+ ProcessFeatures ../files.in ../features.in ../environment.in \
+ directory.wixinc features.wixinc \
+ envset.wixinc
+
+ Progress "processing links..."
+ ProcessLinks ../links.in features.wixinc > links.wixinc
+ cd $here
+}