Index: /trunk/configure.vbs
===================================================================
--- /trunk/configure.vbs	(revision 85822)
+++ /trunk/configure.vbs	(revision 85823)
@@ -394,8 +394,8 @@
 ' Generic helper for looking for a tools under g_strPathDev.
 '
-' The callback function takes the '.../tools/win.arch/tool/version' dir as
-' argument and returns an non-empty string if it was found suitable.
-'
-function SearchToolsEx(strTool, strVerPrefix, ByRef fnCallback, ByRef arrToolsDirs)
+' The callback function takes the '.../tools/win.arch/tool/version' dir and
+' varUser as arguments, returning an non-empty string if it was found suitable.
+'
+function SearchToolsEx(strTool, strVerPrefix, ByRef fnCallback, ByRef varUser, ByRef arrToolsDirs)
    dim strToolsDir, arrDirs, strDir
    SearchToolsEx = ""
@@ -403,5 +403,5 @@
       arrDirs = GetSubdirsStartingWithRVerSorted(strToolsDir, strVerPrefix)
       for each strDir in arrDirs
-         SearchToolsEx = fnCallback(strToolsDir & "/" & strDir)
+         SearchToolsEx = fnCallback(strToolsDir & "/" & strDir, varUser)
          if SearchToolsEx <> "" then
             exit function
@@ -412,6 +412,6 @@
 
 '' Search under g_strPathDev for a tool, target arch first.
-function SearchTargetTools(strTool, strVerPrefix, ByRef fnCallback)
-   SearchTargetTools = SearchToolsEx(strTool, strVerPrefix, fnCallback, _
+function SearchTargetTools(strTool, strVerPrefix, ByRef fnCallback, ByRef varUser)
+   SearchTargetTools = SearchToolsEx(strTool, strVerPrefix, fnCallback, varUser, _
                                      Array(g_strPathDev & "/win." & g_strTargetArch & "/" & strTool, _
                                            g_strPathDev & "/win.x86/" & strTool, _
@@ -420,6 +420,6 @@
 
 '' Search under g_strPathDev for a tool, host arch first.
-function SearchHostTools(strTool, strVerPrefix, ByRef fnCallback)
-   SearchHostTools = SearchToolsEx(strTool, strVerPrefix, fnCallback, _
+function SearchHostTools(strTool, strVerPrefix, ByRef fnCallback, ByRef varUser)
+   SearchHostTools = SearchToolsEx(strTool, strVerPrefix, fnCallback, varUser, _
                                    Array(g_strPathDev & "/win." & g_strHostArch & "/" & strTool, _
                                          g_strPathDev & "/win.x86/" & strTool, _
@@ -428,6 +428,6 @@
 
 '' Search under g_strPathDev for a tool, common dir first.
-function SearchCommonTools(strTool, strVerPrefix, ByRef fnCallback)
-   SearchCommonTools = SearchToolsEx(strTool, strVerPrefix, fnCallback, _
+function SearchCommonTools(strTool, strVerPrefix, ByRef fnCallback, ByRef varUser)
+   SearchCommonTools = SearchToolsEx(strTool, strVerPrefix, fnCallback, varUser, _
                                      Array(g_strPathDev & "/common/" & strTool, _
                                            g_strPathDev & "/win." & g_strHostArch & "/" & strTool, _
@@ -1345,12 +1345,17 @@
 '
 sub CheckForYasm(strOptYasm)
-   dim strPathYasm
+   dim strPathYasm, strVersion
    PrintHdr "yasm"
 
-   strPathYasm = CheckForYasmSub(strOptYasm)
-   if strPathYasm = ""                                then strPathYasm = CheckForYasmSub(PathStripFilename(strOptYasm))
-   if strPathYasm = "" and g_blnInternalFirst = true  then strPathYasm = SearchHostTools("yasm", "v", GetRef("CheckForYasmSub"))
-   if strPathYasm = ""                                then strPathYasm = CheckForYasmSub(PathStripFilename(Which("yasm.exe")))
-   if strPathYasm = "" and g_blnInternalFirst = false then strPathYasm = SearchHostTools("yasm", "v", GetRef("CheckForYasmSub"))
+   strVersion = ""
+   strPathYasm = CheckForYasmSub(strOptYasm, strVersion)
+   if strPathYasm = "" then strPathYasm = CheckForYasmSub(PathStripFilename(strOptYasm), strVersion)
+   if strPathYasm = "" and g_blnInternalFirst = true then
+      strPathYasm = SearchHostTools("yasm", "v", GetRef("CheckForYasmSub"), strVersion)
+   end if
+   if strPathYasm = "" then strPathYasm = CheckForYasmSub(PathStripFilename(Which("yasm.exe")), strVersion)
+   if strPathYasm = "" and g_blnInternalFirst = false then
+      strPathYasm = SearchHostTools("yasm", "v", GetRef("CheckForYasmSub"), strVersion)
+   end if
 
    if strPathYasm = "" then
@@ -1359,13 +1364,28 @@
    else
       CfgPrintAssign "PATH_TOOL_YASM", strPathYasm
-      PrintResult "yasm", strPathYasm
-   end if
-end sub
-
-function CheckForYasmSub(strPathYasm)
+      PrintResult "yasm v" & strVersion, strPathYasm
+   end if
+end sub
+
+function CheckForYasmSub(strPathYasm, ByRef strVersion)
    CheckForYasmSub = ""
    if strPathYasm <> "" then
       if LogFileExists(strPathYasm, "yasm.exe") then
-         CheckForYasmSub = UnixSlashes(PathAbs(strPathYasm))
+         dim strOutput
+         if Shell("""" & DosSlashes(strPathYasm & "\yasm.exe") & """ --version", True, strOutput) = 0 then
+            dim strPreamble : strPreamble = "yasm"
+            dim strVer      : strVer      = Trim(StrGetFirstLine(strOutput))
+            if StrComp(Left(strVer, Len(strPreamble)), strPreamble, vbTextCompare) = 0 then
+               strVersion = StrGetFirstWord(Trim(Mid(strVer, Len(strPreamble) + 1)))
+               if StrVersionCompare(strVersion, "1.3.0") >= 0 and strVersion <> "" then
+                  LogPrint "Found yasm version: " & strVer
+                  CheckForYasmSub = UnixSlashes(PathAbs(strPathYasm))
+               else
+                  LogPrint "yasm version is older than 1.3.0: " & strVersion
+               end if
+            else
+               LogPrint "Not yasm: " & strVer
+            end if
+         end if
       end if
    end if
@@ -1377,19 +1397,23 @@
 '
 sub CheckForNasm(strOptNasm)
-   dim strPathNasm
+   dim strPathNasm, strVersion
    PrintHdr "nasm"
 
-   strPathNasm = CheckForNasmSub(strOptNasm)
-   if strPathNasm = "" then strPathNasm = CheckForNasmSub(PathStripFilename(strOptNasm))
-   if strPathNasm = "" and g_blnInternalFirst = true  then strPathNasm = SearchHostTools("nasm", "v", GetRef("CheckForNasmSub"))
-   if strPathNasm = "" then strPathNasm = CheckForNasmSub(LogRegGetString("HKLM\SOFTWARE\nasm\"))
-   if strPathNasm = "" then strPathNasm = CheckForNasmSub(LogRegGetString("HKCU\SOFTWARE\nasm\"))
+   strPathNasm = CheckForNasmSub(strOptNasm, strVersion)
+   if strPathNasm = "" then strPathNasm = CheckForNasmSub(PathStripFilename(strOptNasm), strVersion)
+   if strPathNasm = "" and g_blnInternalFirst = true then
+      strPathNasm = SearchHostTools("nasm", "v", GetRef("CheckForNasmSub"), strVersion)
+   end if
+   if strPathNasm = "" then strPathNasm = CheckForNasmSub(LogRegGetString("HKLM\SOFTWARE\nasm\"), strVersion)
+   if strPathNasm = "" then strPathNasm = CheckForNasmSub(LogRegGetString("HKCU\SOFTWARE\nasm\"), strVersion)
    if strPathNasm = "" then
       for each strCandidate in CollectFromProgramItemLinks(GetRef("NasmProgramItemCallback"), strPathNasm)
-         strPathNasm = CheckForNasmSub(strCandidate)
+         strPathNasm = CheckForNasmSub(strCandidate, strVersion)
       next
    end if
-   if strPathNasm = "" then strPathNasm = CheckForNasmSub(PathStripFilename(Which("nasm.exe")))
-   if strPathNasm = "" and g_blnInternalFirst = false then strPathNasm = SearchHostTools("nasm", "v", GetRef("CheckForNasmSub"))
+   if strPathNasm = "" then strPathNasm = CheckForNasmSub(PathStripFilename(Which("nasm.exe")), strVersion)
+   if strPathNasm = "" and g_blnInternalFirst = false then
+      strPathNasm = SearchHostTools("nasm", "v", GetRef("CheckForNasmSub"), strVersion)
+   end if
 
    if strPathNasm = "" then
@@ -1397,5 +1421,5 @@
    else
       CfgPrintAssign "PATH_TOOL_NASM", strPathNasm
-      PrintResult "nasm", strPathNasm
+      PrintResult "nasm v" & strVersion, strPathNasm
    end if
 end sub
@@ -1413,9 +1437,24 @@
 end function
 
-function CheckForNasmSub(strPathNasm)
+function CheckForNasmSub(strPathNasm, ByRef strVersion)
    CheckForNasmSub = ""
    if strPathNasm <> "" then
       if LogFileExists(strPathNasm, "nasm.exe") then
-         CheckForNasmSub = UnixSlashes(PathAbs(strPathNasm))
+         dim strOutput
+         if Shell("""" & DosSlashes(strPathNasm & "\nasm.exe") & """ -version", True, strOutput) = 0 then
+            dim strPreamble : strPreamble = "NASM version"
+            dim strVer      : strVer      = Trim(StrGetFirstLine(strOutput))
+            if StrComp(Left(strVer, Len(strPreamble)), strPreamble, vbTextCompare) = 0 then
+               strVersion = StrGetFirstWord(Trim(Mid(strVer, Len(strPreamble) + 1)))
+               if StrVersionCompare(strVersion, "2.12.0") >= 0 and strVersion <> "" then
+                  LogPrint "Found nasm version: " & strVersion
+                  CheckForNasmSub = UnixSlashes(PathAbs(strPathNasm))
+               else
+                  LogPrint "nasm version is older than 2.12.0: " & strVersion
+               end if
+            else
+               LogPrint "Not nasm: " & strVer
+            end if
+         end if
       end if
    end if
@@ -1427,20 +1466,20 @@
 '
 sub CheckForOpenWatcom(strOptOpenWatcom)
-   dim strPathOW, strCandidate
+   dim strPathOW, strCandidate, strVersion
    PrintHdr "OpenWatcom"
 
-   strPathOW = CheckForOpenWatcomSub(strOptOpenWatcom)
+   strPathOW = CheckForOpenWatcomSub(strOptOpenWatcom, strVersion)
    if strPathOW = "" and g_blnInternalFirst = true then
-      strPathOW = SearchCommonTools("openwatcom", "v", GetRef("CheckForOpenWatcomSub"))
-   end if
-   if strPathOW = "" then strPathOW = CheckForOpenWatcomSub(EnvGet("WATCOM"))
-   if strPathOW = "" then strPathOW = CheckForOpenWatcomSub(PathParent(PathStripFilename(Which("wcc386.exe"))))
+      strPathOW = SearchCommonTools("openwatcom", "v", GetRef("CheckForOpenWatcomSub"), strVersion)
+   end if
    if strPathOW = "" then
       for each strCandidate in CollectFromProgramItemLinks(GetRef("OpenWatcomProgramItemCallback"), strPathOW)
-         if strPathOW = "" then strPathOW = CheckForOpenWatcomSub(strCandidate)
+         if strPathOW = "" then strPathOW = CheckForOpenWatcomSub(strCandidate, strVersion)
       next
    end if
+   if strPathOW = "" then strPathOW = CheckForOpenWatcomSub(EnvGet("WATCOM"), strVersion)
+   if strPathOW = "" then strPathOW = CheckForOpenWatcomSub(PathParent(PathStripFilename(Which("wcc386.exe"))), strVersion)
    if strPathOW = "" and g_blnInternalFirst = false then
-      strPathOW = SearchCommonTools("openwatcom", "v", GetRef("CheckForOpenWatcomSub"))
+      strPathOW = SearchCommonTools("openwatcom", "v", GetRef("CheckForOpenWatcomSub"), strVersion)
    end if
 
@@ -1453,5 +1492,8 @@
    CfgPrintAssign "VBOX_WITH_OPEN_WATCOM", "1"
    CfgPrintAssign "PATH_TOOL_OPENWATCOM", strPathOW
-   PrintResult "OpenWatcom", strPathOW
+   PrintResult "OpenWatcom v" & strVersion, strPathOW
+   if StrVersionCompare(strVersion, "2.0") >= 0 then
+      MsgWarning "We only test building with OpenWatcom 1.9."
+   end if
 end sub
 
@@ -1468,5 +1510,5 @@
 end function
 
-function CheckForOpenWatcomSub(strPathOW)
+function CheckForOpenWatcomSub(strPathOW, ByRef strVersion)
    CheckForOpenWatcomSub = ""
    if strPathOW <> "" then
@@ -1485,6 +1527,21 @@
           and LogFileExists(strPathOW, "h/stdarg.h") _
          then
-            '' @todo check the version!
-            CheckForOpenWatcomSub = UnixSlashes(PathAbs(strPathOW))
+            ' Some wcl/wcl386 option parsing quirk allows us to specify /whatever
+            ' and just get the logo text and exit code 0.  We use /y as it's a valid option.
+            dim strOutput
+            if Shell("""" & DosSlashes(strPathOW & "\binnt\wcl.exe") & """ /y", True, strOutput) = 0 then
+               dim strPreamble : strPreamble = "Open Watcom C/C++16 Compile and Link Utility Version"
+               strOutput = StrGetFirstLine(strOutput)
+               if StrStartsWithI(strOutput, strPreamble) then
+                  strVersion = StrGetFirstWord(Trim(Mid(strOutput, Len(strPreamble) + 1)))
+                  if StrVersionCompare(strVersion, "1.9") >= 0 then
+                     CheckForOpenWatcomSub = UnixSlashes(PathAbs(strPathOW))
+                  else
+                     LogPrint "OpenWatcom version id older than 1.9: " & strVersion
+                  end if
+               else
+                  LogPrint "Not OpenWatcom: " & strOutput
+               end if
+            end if
          end if
       end if
Index: /trunk/tools/win/vbscript/helpers.vbs
===================================================================
--- /trunk/tools/win/vbscript/helpers.vbs	(revision 85822)
+++ /trunk/tools/win/vbscript/helpers.vbs	(revision 85823)
@@ -566,4 +566,65 @@
 
 
+''
+' Returns the first list of the given string.
+function StrGetFirstLine(str)
+   dim off
+   off = InStr(1, str, Chr(10))
+   if off <= 0 then off = InStr(1, str, Chr(13))
+   if off > 0 then
+      StrGetFirstLine = Mid(str, 1, off)
+   else
+      StrGetFirstLine = str
+   end if
+end function
+
+
+''
+' Returns the first word in the given string.
+'
+' Only recognizes space, tab, newline and carriage return as word separators.
+'
+function StrGetFirstWord(str)
+   dim strSep, offWord, offEnd, offEnd2, strSeparators
+   strSeparators = " " & Chr(9) & Chr(10) & Chr(13)
+
+   ' Skip leading separators.
+   for offWord = 1 to Len(str)
+      if InStr(1, strSeparators, Mid(str, offWord, 1)) < 1 then exit for
+   next
+
+   ' Find the end.
+   offEnd = Len(str) + 1
+   for offSep = 1 to Len(strSeparators)
+      offEnd2 = InStr(offWord, str, Mid(strSeparators, offSep, 1))
+      if offEnd2 > 0 and offEnd2 < offEnd then offEnd = offEnd2
+   next
+
+   StrGetFirstWord = Mid(str, offWord, offEnd - offWord)
+end function
+
+
+''
+' Checks if the string starts with the given prefix (case sensitive).
+function StrStartsWith(str, strPrefix)
+   if len(str) >= Len(strPrefix) then
+      StrStartsWith = (StrComp(Left(str, Len(strPrefix)), strPrefix, vbBinaryCompare) = 0)
+   else
+      StrStartsWith = false
+   end if
+end function
+
+
+''
+' Checks if the string starts with the given prefix, case insenstive edition.
+function StrStartsWithI(str, strPrefix)
+   if len(str) >= Len(strPrefix) then
+      StrStartsWithI = (StrComp(Left(str, Len(strPrefix)), strPrefix, vbTextCompare) = 0)
+   else
+      StrStartsWithI = false
+   end if
+end function
+
+
 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
 '  Helpers: Arrays                                                                                                               '
@@ -1051,4 +1112,5 @@
       if CharIsDigit(Mid(str, i, 1)) <> False then MsgFatal "SelfTest failed: CharIsDigit("&Mid(str, i, 1)&")"
    next
+
    if StrVersionCompare("1234", "1234") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #1"
    if StrVersionCompare("1", "1") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #2"
@@ -1064,4 +1126,12 @@
    if StrVersionCompare("v1.2.4", "v1.23.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #12"
    if StrVersionCompare("v10.0.17163", "v10.00.18363") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #13"
-end sub
-
+   if StrVersionCompare("n 2.15.0", "2.12.0") <= 0 then MsgFatal "SelfTest failed: StrVersionCompare #14"
+
+   if StrGetFirstWord("1") <> "1" then MsgFatal "SelfTest: StrGetFirstWord #1"
+   if StrGetFirstWord(" 1 ") <> "1" then MsgFatal "SelfTest: StrGetFirstWord #2"
+   if StrGetFirstWord(" 1  2 ") <> "1" then MsgFatal "SelfTest: StrGetFirstWord #3"
+   if StrGetFirstWord("1 2") <> "1" then MsgFatal "SelfTest: StrGetFirstWord #4"
+   if StrGetFirstWord("1234 5") <> "1234" then MsgFatal "SelfTest: StrGetFirstWord #5"
+   if StrGetFirstWord("  ") <> "" then MsgFatal "SelfTest: StrGetFirstWord #6"
+end sub
+
