Commits

davep  committed c7faa21 Merge

merge

  • Participants
  • Parent commits a577ec5, fa5c36b

Comments (0)

Files changed (194)

 syntax: glob
 
+
 # WinMerge temp files
 *.bak
 # Compiled python bytecode
 bb1075286b3b147b1dae2e3d6b2d56f04ff03f35 2.6.6-beta1
 5e349dbe9cc84ea5795af8aeb6d473a0af9d4953 2.6.8-start
 beafa8a9bd1d1b670b7523d865204dc4a4b38eef DRTVWR-55_2.6.8-beta1
+bb9932a7a5fd00edf52d95f354e3b37ae6a942db DRTVWR-156
 beafa8a9bd1d1b670b7523d865204dc4a4b38eef 2.6.8-beta1
 11d5d8080e67c3955914caf98f2eb116af30e55a 2.6.9-start
 e67da2c6e3125966dd49eef98b36317afac1fcfe 2.6.9-start
 09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1
 e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start
 502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start
+2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155
 6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
 6866d9df6efbd441c66451debd376d21211de39c 2.7.5-release
 e1ed60913230dd64269a7f7fc52cbc6004f6d52c DRTVWR-71_2.8.0-beta1
 c623bbc854b6f7ee1b33a3718f76715046aa2937 viewer-release-candidate
 675668bd24d3bea570814f71762a2a806f7e1b8d viewer-release-candidate
 675668bd24d3bea570814f71762a2a806f7e1b8d 3.3.2-release
+675668bd24d3bea570814f71762a2a806f7e1b8d viewer-release-candidate
+600f3b3920d94de805ac6dc8bb6def9c069dd360 DRTVWR-162
+24a7281bef42bd4430ceb25db8b195449c2c7de3 DRTVWR-153
+15e90b52dc0297921b022b90d10d797436b8a1bd viewer-release-candidate
+6414ecdabc5d89515b08d1f872cf923ed3a5523a DRTVWR-148
+1b7f311b5a5dbfbed3dcbb4ed44afa20f89cad4c DRTVWR-144
+1b7f311b5a5dbfbed3dcbb4ed44afa20f89cad4c 3.3.3-beta1
+5910f8063a7e1ddddf504c2f35ca831cc5e8f469 DRTVWR-160
+1b7f311b5a5dbfbed3dcbb4ed44afa20f89cad4c 3.3.3-beta1
+f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 3.3.3-beta1
+1b7f311b5a5dbfbed3dcbb4ed44afa20f89cad4c DRTVWR-144
+f0a174c2adb4bc39b16722a61d7eeb4f2a1d4843 DRTVWR-144
+2d6c0634b11e6f3df11002b8510a72a0433da00a DRTVWR-164
+80b5e5e9775966d3839331ffa7a16a60f9d7c930 DRTVWR-165
+fdcc08a4f20ae9bb060f4693c8980d216534efdf 3.3.3-beta2
+af5f3e43e6e4424b1da19d9e16f6b853a7b822ed DRTVWR-169
+4b3c68199a86cabaa5d9466d7b0f7e141e901d7a 3.3.3-beta3
+6428242e124b523813bfaf4c45b3d422f0298c81 3.3.3-release
 vir-project-1.viewer_channel = "Second Life Release"
 vir-project-1.login_channel = "Second Life Release"
 
+# ========================================
+# THX-1138 / Runway projects
+# ========================================
+viewer-thx1138-runway-shared.viewer_channel = "Project Viewer - THX-1138 Runway"
+viewer-thx1138-runway-shared.login_channel = "Project Viewer - THX-1138 Runway"
+viewer-thx1138-runway-shared.viewer_grid = uma
+viewer-thx1138-runway-shared.build_debug_release_separately = true
+viewer-thx1138-runway-shared.build_CYGWIN_Debug = false
+viewer-thx1138-runway-shared.build_viewer_update_version_manager = false
+
+viewer-thx1138.viewer_channel = "Project Viewer - THX-1138"
+viewer-thx1138.login_channel = "Project Viewer - THX-1138"
+viewer-thx1138.viewer_grid = uma
+viewer-thx1138.build_debug_release_separately = true
+viewer-thx1138.build_CYGWIN_Debug = false
+viewer-thx1138.build_viewer_update_version_manager = false
+
+runway-merge.viewer_channel = "Project Viewer - Runway Merge"
+runway-merge.login_channel = "Project Viewer - Runway Merge"
+runway-merge.viewer_grid = agni
+runway-merge.build_debug_release_separately = true
+runway-merge.build_CYGWIN_Debug = false
+runway-merge.build_viewer_update_version_manager = false
+
+runway.viewer_channel = "Project Viewer - Runway"
+runway.login_channel = "Project Viewer - Runway"
+runway.viewer_grid = agni
+runway.build_debug_release_separately = true
+runway.build_CYGWIN_Debug = false
+runway.build_viewer_update_version_manager = false
+
 # eof

File autobuild.xml

             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>9868bfa0b6954e4884c49c6f30068c80</string>
+              <string>2dfcd809e747f714b3fe0bf82a175812</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-darwin-20110217.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/259951/arch/Darwin/installer/apr_suite-1.4.5-darwin-20120618.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>ff62946c518a247c86e1066c1e9a5855</string>
+              <string>f38c966a430012dc157fdc104f23a59b</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-linux-20110309.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/259951/arch/Linux/installer/apr_suite-1.4.5-linux-20120618.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>73785c200a5b4ef74a1230b028bb680d</string>
+              <string>4a9d040582342699c58c886c5ccd2caf</string>
               <key>url</key>
-              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/apr_suite-1.4.2-windows-20110217.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-apr/rev/259951/arch/CYGWIN/installer/apr_suite-1.4.5-windows-20120618.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>

File doc/contributions.txt

 	CTS-411
 	STORM-546
 	VWR-24509
-    STORM-1684
 	SH-2477
 	STORM-1684
+	STORM-1819
 Tony Kembia
 Torben Trautman
 TouchaHoney Perhaps

File indra/CMakeLists.txt

   add_subdirectory(${LIBS_OPEN_PREFIX}llcrashlogger)
   add_subdirectory(${LIBS_OPEN_PREFIX}llplugin)
   add_subdirectory(${LIBS_OPEN_PREFIX}llui)
-  add_subdirectory(${LIBS_OPEN_PREFIX}llxuixml)
   add_subdirectory(${LIBS_OPEN_PREFIX}viewer_components)
 
   # Legacy C++ tests. Build always, run if LL_TESTS is true.

File indra/cmake/LLTestCommand.cmake

   FOREACH(dir ${LD_LIBRARY_PATH})
     LIST(APPEND value "-l${dir}")
   ENDFOREACH(dir)
+  # Enough different tests want to be able to find CMake's PYTHON_EXECUTABLE
+  # that we should just pop it into the environment for everybody.
+  LIST(APPEND value "-DPYTHON=${PYTHON_EXECUTABLE}")
   LIST(APPEND value ${ARGN})
   SET(${OUTVAR} ${value})
 ##IF(LL_TEST_VERBOSE)

File indra/cmake/run_build_test.py

 
 import os
 import sys
+import signal
 import subprocess
 
 def main(command, libpath=[], vars={}):
     sys.stdout.flush()
     return subprocess.call(command)
 
+# swiped from vita, sigh, seems like a Bad Idea to introduce dependency
+def translate_rc(rc):
+    """
+    Accept an rc encoded as for subprocess.Popen.returncode:
+    None means still running
+    int >= 0 means terminated voluntarily with specified rc
+    int <  0 means terminated by signal (-rc)
+
+    Return a string explaining the outcome. In case of a signal, try to
+    name the corresponding symbol from the 'signal' module.
+    """
+    if rc is None:
+        return "still running"
+    
+    if rc >= 0:
+        return "terminated with rc %s" % rc
+
+    # Negative rc means the child was terminated by signal -rc.
+    rc = -rc
+    for attr in dir(signal):
+        if attr.startswith('SIG') and getattr(signal, attr) == rc:
+            strc = attr
+            break
+    else:
+        strc = str(rc)
+    return "terminated by signal %s" % strc
+
 if __name__ == "__main__":
     from optparse import OptionParser
     parser = OptionParser(usage="usage: %prog [options] command args...")
               vars=dict([(pair.split('=', 1) + [""])[:2] for pair in opts.vars]))
     if rc not in (None, 0):
         print >>sys.stderr, "Failure running: %s" % " ".join(args)
-        print >>sys.stderr, "Error: %s" % rc
+        print >>sys.stderr, "Error %s: %s" % (rc, translate_rc(rc))
     sys.exit((rc < 0) and 255 or rc)

File indra/integration_tests/llimage_libtest/llimage_libtest.cpp

 " -o, --output <file1 .. file2> OR <type>\n"
 "        List of image files to create (assumes same order as for input files)\n"
 "        OR 3 letters file type extension to convert each input file into.\n"
+" -load, --load_size <n>\n"
+"        Portion of the input file to load, in bytes."
+"        If (load == 0), it will load the whole file."
+"        If (load == -1), it will load the size relevant to reach the requested discard level (see -d)."
+"        Only valid for j2c images. Default is 0 (load whole file).\n"
 " -r, --region <x0, y0, x1, y1>\n"
 "        Crop region applied to the input files in pixels.\n"
 "        Only used for j2c images. Default is no region cropping.\n"
 	// Print out some statistical data on the image
 	std::cout << "Image stats for : " << filename << ", extension : " << image->getExtension() << std::endl;
 
-	std::cout << "    with : " << (int)(image->getWidth())       << ", height : " << (int)(image->getHeight())       << std::endl;
-	std::cout << "    comp : " << (int)(image->getComponents())  << ", levels : " << (int)(image->getDiscardLevel()) << std::endl;
-	std::cout << "    head : " << (int)(image->calcHeaderSize()) << ",   data : " << (int)(image->getDataSize())     << std::endl;
+	std::cout << "    with : " << (int)(image->getWidth())       << ", height : " << (int)(image->getHeight())   << std::endl;
+	std::cout << "    comp : " << (int)(image->getComponents())  << ", levels : " << (int)(image->getLevels())   << std::endl;
+	std::cout << "    head : " << (int)(image->calcHeaderSize()) << ",   data : " << (int)(image->getDataSize()) << std::endl;
 
 	return;
 }
 
 // Load an image from file and return a raw (decompressed) instance of its data
-LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, bool output_stats)
+LLPointer<LLImageRaw> load_image(const std::string &src_filename, int discard_level, int* region, int load_size, bool output_stats)
 {
 	LLPointer<LLImageFormatted> image = create_image(src_filename);
 	
-	// This just loads the image file stream into a buffer. No decoding done.
-	if (!image->load(src_filename))
+	// We support partial loading only for j2c images
+	if (image->getCodec() == IMG_CODEC_J2C)
 	{
-		return NULL;
+		// Load the header
+		if (!image->load(src_filename, 600))
+		{
+			return NULL;
+		}
+		S32 h = ((LLImageJ2C*)(image.get()))->calcHeaderSize();
+		S32 d = (load_size > 0 ? ((LLImageJ2C*)(image.get()))->calcDiscardLevelBytes(load_size) : 0);
+		S8  r = ((LLImageJ2C*)(image.get()))->getRawDiscardLevel();
+		std::cout << "Merov debug : header = " << h << ", load_size = " << load_size << ", discard level = " << d << ", raw discard level = " << r << std::endl;
+		for (d = 0; d < MAX_DISCARD_LEVEL; d++)
+		{
+			S32 data_size = ((LLImageJ2C*)(image.get()))->calcDataSize(d);
+			std::cout << "Merov debug : discard_level = " << d << ", data_size = " << data_size << std::endl;
+		}
+		if (load_size < 0)
+		{
+			load_size = (discard_level != -1 ? ((LLImageJ2C*)(image.get()))->calcDataSize(discard_level) : 0);
+		}
+		// Load the requested byte range
+		if (!image->load(src_filename, load_size))
+		{
+			return NULL;
+		}
+	}
+	else 
+	{
+		// This just loads the image file stream into a buffer. No decoding done.
+		if (!image->load(src_filename))
+		{
+			return NULL;
+		}
 	}
 	
 	if(	(image->getComponents() != 3) && (image->getComponents() != 4) )
 	bool image_stats = false;
 	int* region = NULL;
 	int discard_level = -1;
+	int load_size = 0;
 	int precincts_size = -1;
 	int blocks_size = -1;
 	int levels = 0;
 				discard_level = llclamp(discard_level,0,5);
 			}
 		}
+		else if (!strcmp(argv[arg], "--load_size") || !strcmp(argv[arg], "-load"))
+		{
+			std::string value_str;
+			if ((arg + 1) < argc)
+			{
+				value_str = argv[arg+1];
+			}
+			if (((arg + 1) >= argc) || (value_str[0] == '-'))
+			{
+				std::cout << "No valid --load_size argument given, load_size ignored" << std::endl;
+			}
+			else
+			{
+				load_size = atoi(value_str.c_str());
+			}
+		}
 		else if (!strcmp(argv[arg], "--precincts") || !strcmp(argv[arg], "-p"))
 		{
 			std::string value_str;
 	for (; in_file != in_end; ++in_file, ++out_file)
 	{
 		// Load file
-		LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, image_stats);
+		LLPointer<LLImageRaw> raw_image = load_image(*in_file, discard_level, region, load_size, image_stats);
 		if (!raw_image)
 		{
 			std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl;

File indra/integration_tests/llui_libtest/CMakeLists.txt

 include(LLUI)
 include(LLVFS)        # ugh, needed for LLDir
 include(LLXML)
-include(LLXUIXML)
 include(Linking)
 # include(Tut)
 
     ${LLVFS_INCLUDE_DIRS}
     ${LLWINDOW_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
-    ${LLXUIXML_INCLUDE_DIRS}
     )
 
 set(llui_libtest_SOURCE_FILES

File indra/lib/python/indra/util/llmanifest.py

 import errno
 import subprocess
 
+class ManifestError(RuntimeError):
+    """Use an exception more specific than generic Python RuntimeError"""
+    pass
+
+class MissingError(ManifestError):
+    """You specified a file that doesn't exist"""
+    pass
+
 def path_ancestors(path):
     drive, path = os.path.splitdrive(os.path.normpath(path))
     result = []
             arg['description'] % nd)
 
 def main():
+##  import itertools
+##  print ' '.join((("'%s'" % item) if ' ' in item else item)
+##                 for item in itertools.chain([sys.executable], sys.argv))
     option_names = [arg['name'] + '=' for arg in ARGUMENTS]
     option_names.append('help')
     options, remainder = getopt.getopt(sys.argv[1:], "", option_names)
         child.stdout.close()
         status = child.wait()
         if status:
-            raise RuntimeError(
+            raise ManifestError(
                 "Command %s returned non-zero status (%s) \noutput:\n%s"
                 % (command, status, output) )
         return output
           a) verify that you really have created it
           b) schedule it for cleanup"""
         if not os.path.exists(path):
-            raise RuntimeError, "Should be something at path " + path
+            raise ManifestError, "Should be something at path " + path
         self.created_paths.append(path)
 
     def put_in_file(self, contents, dst):
             except (IOError, os.error), why:
                 errors.append((srcname, dstname, why))
         if errors:
-            raise RuntimeError, errors
+            raise ManifestError, errors
 
 
     def cmakedirs(self, path):
 
     def check_file_exists(self, path):
         if not os.path.exists(path) and not os.path.islink(path):
-            raise RuntimeError("Path %s doesn't exist" % (
-                os.path.normpath(os.path.join(os.getcwd(), path)),))
+            raise MissingError("Path %s doesn't exist" % (os.path.abspath(path),))
 
 
-    wildcard_pattern = re.compile('\*')
+    wildcard_pattern = re.compile(r'\*')
     def expand_globs(self, src, dst):
         src_list = glob.glob(src)
         src_re, d_template = self.wildcard_regex(src.replace('\\', '/'),
         sys.stdout.write("Processing %s => %s ... " % (src, dst))
         sys.stdout.flush()
         if src == None:
-            raise RuntimeError("No source file, dst is " + dst)
+            raise ManifestError("No source file, dst is " + dst)
         if dst == None:
             dst = src
         dst = os.path.join(self.get_dst_prefix(), dst)
                 else:
                     count += self.process_file(src, dst)
             return count
-        try:
-            count = try_path(os.path.join(self.get_src_prefix(), src))
-        except RuntimeError:
+
+        for pfx in self.get_src_prefix(), self.get_artwork_prefix(), self.get_build_prefix():
             try:
-                count = try_path(os.path.join(self.get_artwork_prefix(), src))
-            except RuntimeError:
-                count = try_path(os.path.join(self.get_build_prefix(), src))
+                count = try_path(os.path.join(pfx, src))
+            except MissingError:
+                # If src isn't a wildcard, and if that file doesn't exist in
+                # this pfx, try next pfx.
+                count = 0
+                continue
+
+            # Here try_path() didn't raise MissingError. Did it process any files?
+            if count:
+                break
+            # Even though try_path() didn't raise MissingError, it returned 0
+            # files. src is probably a wildcard meant for some other pfx. Loop
+            # back to try the next.
+
         print "%d files" % count
 
     def do(self, *actions):

File indra/linux_updater/CMakeLists.txt

 include(LLCommon)
 include(LLVFS)
 include(LLXML)
-include(LLXUIXML)
+include(LLUI)
 include(Linking)
 
 include_directories(
     ${LLCOMMON_INCLUDE_DIRS}
     ${LLVFS_INCLUDE_DIRS}
     ${LLXML_INCLUDE_DIRS}
-    ${LLXUIXML_INCLUDE_DIRS}
+    ${LLUI_INCLUDE_DIRS}
     ${CURL_INCLUDE_DIRS}
     ${CARES_INCLUDE_DIRS}
     ${OPENSSL_INCLUDE_DIRS}
     ${CRYPTO_LIBRARIES}
     ${UI_LIBRARIES}
     ${LLXML_LIBRARIES}
-    ${LLXUIXML_LIBRARIES}
+    ${LLUI_LIBRARIES}
     ${LLVFS_LIBRARIES}
     ${LLCOMMON_LIBRARIES}
     )

File indra/linux_updater/linux_updater.cpp

-/** 
+/**
  * @file linux_updater.cpp
  * @author Kyle Ambroff <ambroff@lindenlab.com>, Tofu Linden
  * @brief Viewer update program for unix platforms that support GTK+
  * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 #include "llfile.h"
 #include "lldir.h"
 #include "lldiriterator.h"
+
+/*==========================================================================*|
+// IQA-490: Use of LLTrans -- by this program at least -- appears to be buggy.
+// With it, the 3.3.2 beta 1 linux-updater.bin crashes; without it seems stable.
 #include "llxmlnode.h"
 #include "lltrans.h"
+|*==========================================================================*/
+
+static class LLTrans
+{
+public:
+	LLTrans();
+	static std::string getString(const std::string& key);
+
+private:
+	std::string _getString(const std::string& key) const;
+
+	typedef std::map<std::string, std::string> MessageMap;
+	MessageMap mMessages;
+} sLLTransInstance;
 
 #include <curl/curl.h>
+#include <map>
+#include <boost/foreach.hpp>
 
 extern "C" {
 #include <gtk/gtk.h>
 bool translate_init(std::string comma_delim_path_list,
 		    std::string base_xml_name)
 {
+	return true;
+/*==========================================================================*|
 	init_default_trans_args();
 
 	// extract paths string vector from comma-delimited flat string
 		LLTrans::parseStrings(root, default_trans_args);
 		return true;
 	}
+|*==========================================================================*/
 }
 
 
 				GTK_WIN_POS_CENTER_ALWAYS);
 
 	gtk_container_set_border_width(GTK_CONTAINER(app_state->window), 12);
-	g_signal_connect(G_OBJECT(app_state->window), "delete-event", 
+	g_signal_connect(G_OBJECT(app_state->window), "delete-event",
 			 G_CALLBACK(on_window_closed), app_state);
 
 	vbox = gtk_vbox_new(FALSE, 6);
 
 	summary_label = gtk_label_new(NULL);
 	gtk_label_set_use_markup(GTK_LABEL(summary_label), TRUE);
-	gtk_label_set_markup(GTK_LABEL(summary_label), 
+	gtk_label_set_markup(GTK_LABEL(summary_label),
 			     label_ostr.str().c_str());
 	gtk_misc_set_alignment(GTK_MISC(summary_label), 0, 0.5);
 	gtk_box_pack_start(GTK_BOX(vbox), summary_label, FALSE, FALSE, 0);
 
 	// set up progress bar, and update it roughly every 1/10 of a second
 	app_state->progress_bar = gtk_progress_bar_new();
-	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar), 
+	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(app_state->progress_bar),
 				  LLTrans::getString("UpdaterProgressBarTextWithEllipses").c_str());
-	gtk_box_pack_start(GTK_BOX(vbox), 
+	gtk_box_pack_start(GTK_BOX(vbox),
 			   app_state->progress_bar, FALSE, TRUE, 0);
 	app_state->progress_update_timeout_id = g_timeout_add
 		(UPDATE_PROGRESS_TIMEOUT, progress_update_timeout, app_state);
 				g_error_free(error);
 				throw 0;
 			}
-			
+
 			if(tmp_local_filename != NULL)
 			{
 				app_state->file = tmp_local_filename;
 			curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, TRUE);
 			curl_easy_setopt(curl, CURLOPT_WRITEDATA, package_file);
 			curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
-			curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, 
+			curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION,
 							 &download_progress_cb);
 			curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, app_state);
 
 
 			if (result)
 			{
-				llerrs << "Failed to download update: " 
-					   << app_state->url 
+				llerrs << "Failed to download update: "
+					   << app_state->url
 					   << llendl;
 
 				gdk_threads_enter();
 				throw 0;
 			}
 		}
-		
+
 		// now pulse the progres bar back and forth while the package is
 		// being unpacked
 		gdk_threads_enter();
 
 			gdk_threads_enter();
 			display_error(app_state->window,
-				      LLTrans::getString("UpdaterFailInstallTitle"),
-				      LLTrans::getString("UpdaterFailUpdateDescriptive"));
+						  LLTrans::getString("UpdaterFailInstallTitle"),
+						  LLTrans::getString("UpdaterFailUpdateDescriptive"));
 			//"Failed to update " + app_state->app_name,
 			gdk_threads_leave();
 			throw 0;
 
 			gdk_threads_enter();
 			display_error(app_state->window,
-				      LLTrans::getString("UpdaterFailStartTitle"),
-				      LLTrans::getString("UpdaterFailUpdateDescriptive"));
+						  LLTrans::getString("UpdaterFailStartTitle"),
+						  LLTrans::getString("UpdaterFailUpdateDescriptive"));
 			gdk_threads_leave();
 			throw 0;
 		}
 
 	// restore SIGCHLD handler
 	sigaction(SIGCHLD, &sigchld_backup, NULL);
-	
+
 	return rtn;
 }
 
 			{
 				char *src_string_copy = g_strdup(filename.c_str());
 				char *dst_string_copy = g_strdup(newname.c_str());
-				char* argv[] = 
+				char* argv[] =
 					{
 						sudo_cmd,
 						mv_cmd,
 				if (!less_anal_gspawnsync(argv, &stderr_output,
 							  &child_exit_status, &spawn_error))
 				{
-					llwarns << "Failed to spawn child process: " 
-						<< spawn_error->message 
+					llwarns << "Failed to spawn child process: "
+						<< spawn_error->message
 						<< llendl;
 				}
 				else if (child_exit_status)
 				{
 					// everything looks good, clear the error code
 					rtncode = 0;
-				}				
+				}
 
 				g_free(src_string_copy);
 				g_free(dst_string_copy);
 	}
 	llinfos << "Found tar command: " << tar_cmd << llendl;
 
-	// Unpack the tarball in a temporary place first, then move it to 
+	// Unpack the tarball in a temporary place first, then move it to
 	// its final destination
 	std::string tmp_dest_dir = gDirUtilp->getTempFilename();
 	if (LLFile::mkdir(tmp_dest_dir, 0744))
 	if (!less_anal_gspawnsync(argv, &stderr_output,
 				  &child_exit_status, &untar_error))
 	{
-		llwarns << "Failed to spawn child process: " 
-			<< untar_error->message 
+		llwarns << "Failed to spawn child process: "
+			<< untar_error->message
 			<< llendl;
 		return FALSE;
 	}
 
 		if (rename_with_sudo_fallback(destination, backup_dir))
 		{
-			llwarns << "Failed to move directory: '" 
-				<< destination << "' -> '" << backup_dir 
+			llwarns << "Failed to move directory: '"
+				<< destination << "' -> '" << backup_dir
 				<< llendl;
 			return FALSE;
 		}
 	if (rename_with_sudo_fallback(tmp_dest_dir, destination))
 	{
 		llwarns << "Failed to move installation to the destination: "
-			<< destination 
+			<< destination
 			<< llendl;
 		return FALSE;
 	}
 
 	if (!success)
 	{
-		llwarns << "Failed to launch viewer: " << error->message 
+		llwarns << "Failed to launch viewer: " << error->message
 			<< llendl;
 	}
 
 		}
 	}
 
-	if (app_state->app_name.empty() 
-	    || (app_state->url.empty() && app_state->file.empty())  
+	if (app_state->app_name.empty()
+	    || (app_state->url.empty() && app_state->file.empty())
 	    || app_state->dest_dir.empty())
 	{
 		show_usage_and_exit();
 		(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
 	std::string old_log_file = gDirUtilp->getExpandedFilename
 		(LL_PATH_LOGS, "updater.log.old");
-	std::string log_file = 
+	std::string log_file =
 		gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "updater.log");
 	LLFile::rename(log_file, old_log_file);
 	LLError::logToFile(log_file);
 	return success ? 0 : 1;
 }
 
+/*****************************************************************************
+*   Dummy LLTrans implementation (IQA-490)
+*****************************************************************************/
+static LLTrans sStaticStrings;
+
+// lookup
+std::string LLTrans::_getString(const std::string& key) const
+{
+	MessageMap::const_iterator found = mMessages.find(key);
+	if (found != mMessages.end())
+	{
+		return found->second;
+	}
+	LL_WARNS("linux_updater") << "No message for key '" << key
+							  << "' -- add to LLTrans::LLTrans() in linux_updater.cpp"
+							  << LL_ENDL;
+	return key;
+}
+
+// static lookup
+std::string LLTrans::getString(const std::string& key)
+{
+    return sLLTransInstance._getString(key);
+}
+
+// initialization
+LLTrans::LLTrans()
+{
+	typedef std::pair<const char*, const char*> Pair;
+	static const Pair data[] =
+	{
+		Pair("UpdaterFailDownloadTitle",
+			 "Failed to download update"),
+		Pair("UpdaterFailInstallTitle",
+			 "Failed to install update"),
+		Pair("UpdaterFailStartTitle",
+			 "Failed to start viewer"),
+		Pair("UpdaterFailUpdateDescriptive",
+			 "An error occurred while updating Second Life. "
+			 "Please download the latest version from www.secondlife.com."),
+		Pair("UpdaterNowInstalling",
+			 "Installing Second Life..."),
+		Pair("UpdaterNowUpdating",
+			 "Now updating Second Life..."),
+		Pair("UpdaterProgressBarText",
+			 "Downloading update"),
+		Pair("UpdaterProgressBarTextWithEllipses",
+			 "Downloading update..."),
+		Pair("UpdaterUpdatingDescriptive",
+			 "Your Second Life Viewer is being updated to the latest release. "
+			 "This may take some time, so please be patient."),
+		Pair("UpdaterWindowTitle",
+			 "Second Life Update")
+	};
+
+	BOOST_FOREACH(Pair pair, data)
+	{
+		mMessages[pair.first] = pair.second;
+	}
+}

File indra/llcommon/CMakeLists.txt

     llformat.cpp
     llframetimer.cpp
     llheartbeat.cpp
+    llinitparam.cpp
     llinstancetracker.cpp
+    llleap.cpp
+    llleaplistener.cpp
     llliveappconfig.cpp
     lllivefile.cpp
     lllog.cpp
     llmortician.cpp
     lloptioninterface.cpp
     llptrto.cpp 
-    llprocesslauncher.cpp
+    llprocess.cpp
     llprocessor.cpp
     llqueuedthread.cpp
     llrand.cpp
     llrefcount.cpp
     llrun.cpp
     llsd.cpp
+    llsdparam.cpp
     llsdserialize.cpp
     llsdserialize_xml.cpp
     llsdutil.cpp
     llsingleton.cpp
     llstat.cpp
     llstacktrace.cpp
+    llstreamqueue.cpp
     llstreamtools.cpp
     llstring.cpp
     llstringtable.cpp
     llheartbeat.h
     llhttpstatuscodes.h
     llindexedqueue.h
+    llinitparam.h
     llinstancetracker.h
     llkeythrottle.h
     lllazy.h
+    llleap.h
+    llleaplistener.h
     lllistenerwrapper.h
     lllinkedqueue.h
     llliveappconfig.h
     llpointer.h
     llpreprocessor.h
     llpriqueuemap.h
-    llprocesslauncher.h
+    llprocess.h
     llprocessor.h
     llptrskiplist.h
     llptrskipmap.h
     llqueuedthread.h
     llrand.h
     llrefcount.h
+    llregistry.h
     llrun.h
     llrefcount.h
     llsafehandle.h
     llsd.h
+    llsdparam.h
     llsdserialize.h
     llsdserialize_xml.h
     llsdutil.h
     llsingleton.h
     llskiplist.h
     llskipmap.h
+    llsortedvector.h
     llstack.h
     llstacktrace.h
     llstat.h
     llstatenums.h
     llstl.h
+    llstreamqueue.h
     llstreamtools.h
     llstrider.h
     llstring.h
     llthreadsafequeue.h
     lltimer.h
     lltreeiterators.h
+    lltypeinfolookup.h
     lluri.h
     lluuid.h
     lluuidhashmap.h
   LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}"
-                          "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/setpython.py")
+  LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")                          
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
 
   # *TODO - reenable these once tcmalloc libs no longer break the build.
   #ADD_BUILD_TEST(llallocator llcommon)

File indra/llcommon/llerror.cpp

 		g.invalidateCallSites();
 		s.tagLevelMap[tag_name] = level;
 	}
-}
 
-namespace {
 	LLError::ELevel decodeLevel(std::string name)
 	{
 		static LevelMap level_names;
 		
 		return i->second;
 	}
-	
+}
+
+namespace {
 	void setLevels(LevelMap& map, const LLSD& list, LLError::ELevel level)
 	{
 		LLSD::array_const_iterator i, end;

File indra/llcommon/llerrorcontrol.h

-/** 
+/**
  * @file llerrorcontrol.h
  * @date   December 2006
  * @brief error message system control
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 	This is the part of the LLError namespace that manages the messages
 	produced by the logging.  The logging support is defined in llerror.h.
 	Most files do not need to include this.
-	
+
 	These implementations are in llerror.cpp.
 */
 
 		Settings that control what is logged.
 		Setting a level means log messages at that level or above.
 	*/
-	
+
 	LL_COMMON_API void setPrintLocation(bool);
 	LL_COMMON_API void setDefaultLevel(LLError::ELevel);
 	LL_COMMON_API ELevel getDefaultLevel();
 	LL_COMMON_API void setClassLevel(const std::string& class_name, LLError::ELevel);
 	LL_COMMON_API void setFileLevel(const std::string& file_name, LLError::ELevel);
 	LL_COMMON_API void setTagLevel(const std::string& file_name, LLError::ELevel);
-	
+
+	LL_COMMON_API LLError::ELevel decodeLevel(std::string name);
 	LL_COMMON_API void configure(const LLSD&);
 		// the LLSD can configure all of the settings
 		// usually read automatically from the live errorlog.xml file
 		// (by, for example, setting a class level to LEVEL_NONE), will keep
 		// the that message from causing the fatal funciton to be invoked.
 
-    LL_COMMON_API FatalFunction getFatalFunction();
-        // Retrieve the previously-set FatalFunction
+	LL_COMMON_API FatalFunction getFatalFunction();
+		// Retrieve the previously-set FatalFunction
 
-    /// temporarily override the FatalFunction for the duration of a
-    /// particular scope, e.g. for unit tests
-    class LL_COMMON_API OverrideFatalFunction
-    {
-    public:
-        OverrideFatalFunction(const FatalFunction& func):
-            mPrev(getFatalFunction())
-        {
-            setFatalFunction(func);
-        }
-        ~OverrideFatalFunction()
-        {
-            setFatalFunction(mPrev);
-        }
+	/// temporarily override the FatalFunction for the duration of a
+	/// particular scope, e.g. for unit tests
+	class LL_COMMON_API OverrideFatalFunction
+	{
+	public:
+		OverrideFatalFunction(const FatalFunction& func):
+			mPrev(getFatalFunction())
+		{
+			setFatalFunction(func);
+		}
+		~OverrideFatalFunction()
+		{
+			setFatalFunction(mPrev);
+		}
 
-    private:
-        FatalFunction mPrev;
-    };
+	private:
+		FatalFunction mPrev;
+	};
 
 	typedef std::string (*TimeFunction)();
 	LL_COMMON_API std::string utcTime();
-	
+
 	LL_COMMON_API void setTimeFunction(TimeFunction);
 		// The function is use to return the current time, formatted for
 		// display by those error recorders that want the time included.
 		// An object that handles the actual output or error messages.
 	public:
 		virtual ~Recorder();
-		
+
 		virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;
 			// use the level for better display, not for filtering
-			
+
 		virtual bool wantsTime(); // default returns false
 			// override and return true if the recorder wants the time string
 			// included in the text of the message
 	};
-	
+
+	/**
+	 * @NOTE: addRecorder() conveys ownership to the underlying Settings
+	 * object -- when destroyed, it will @em delete the passed Recorder*!
+	 */
 	LL_COMMON_API void addRecorder(Recorder*);
+	/**
+	 * @NOTE: removeRecorder() reclaims ownership of the Recorder*: its
+	 * lifespan becomes the caller's problem.
+	 */
 	LL_COMMON_API void removeRecorder(Recorder*);
 		// each error message is passed to each recorder via recordMessage()
-	
+
 	LL_COMMON_API void logToFile(const std::string& filename);
 	LL_COMMON_API void logToFixedBuffer(LLLineBuffer*);
 		// Utilities to add recorders for logging to a file or a fixed buffer
 	class Settings;
 	LL_COMMON_API Settings* saveAndResetSettings();
 	LL_COMMON_API void restoreSettings(Settings *);
-		
+
 	LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
 	LL_COMMON_API int shouldLogCallCount();
-	
 };
 
 #endif // LL_LLERRORCONTROL_H

File indra/llcommon/llerrorthread.cpp

 #if !LL_WINDOWS
 	U32 last_sig_child_count = 0;
 #endif
-	while (1)
+	while (! (LLApp::isError() || LLApp::isStopped()))
 	{
-		if (LLApp::isError() || LLApp::isStopped())
-		{
-			// The application has stopped running, time to take action (maybe)
-			break;
-		}
 #if !LL_WINDOWS
 		// Check whether or not the main thread had a sig child we haven't handled.
 		U32 current_sig_child_count = LLApp::getSigChildCount();

File indra/llcommon/llfile.cpp

-/** 
+/**
  * @file llfile.cpp
  * @author Michael Schlachter
  * @date 2006-03-23
  * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2010, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
 
 #if LL_WINDOWS
 #include <windows.h>
+#include <stdlib.h>                 // Windows errno
+#else
+#include <errno.h>
 #endif
 
 #include "linden_common.h"
 #include "llfile.h"
 #include "llstring.h"
 #include "llerror.h"
+#include "stringize.h"
 
 using namespace std;
 
+static std::string empty;
+
+// Many of the methods below use OS-level functions that mess with errno. Wrap
+// variants of strerror() to report errors.
+
+#if LL_WINDOWS
+// On Windows, use strerror_s().
+std::string strerr(int errn)
+{
+	char buffer[256];
+	strerror_s(buffer, errn);       // infers sizeof(buffer) -- love it!
+	return buffer;
+}
+
+#else
+// On Posix we want to call strerror_r(), but alarmingly, there are two
+// different variants. The one that returns int always populates the passed
+// buffer (except in case of error), whereas the other one always returns a
+// valid char* but might or might not populate the passed buffer. How do we
+// know which one we're getting? Define adapters for each and let the compiler
+// select the applicable adapter.
+
+// strerror_r() returns char*
+std::string message_from(int /*orig_errno*/, const char* /*buffer*/, size_t /*bufflen*/,
+						 const char* strerror_ret)
+{
+	return strerror_ret;
+}
+
+// strerror_r() returns int
+std::string message_from(int orig_errno, const char* buffer, size_t bufflen,
+						 int strerror_ret)
+{
+	if (strerror_ret == 0)
+	{
+		return buffer;
+	}
+	// Here strerror_r() has set errno. Since strerror_r() has already failed,
+	// seems like a poor bet to call it again to diagnose its own error...
+	int stre_errno = errno;
+	if (stre_errno == ERANGE)
+	{
+		return STRINGIZE("strerror_r() can't explain errno " << orig_errno
+						 << " (" << bufflen << "-byte buffer too small)");
+	}
+	if (stre_errno == EINVAL)
+	{
+		return STRINGIZE("unknown errno " << orig_errno);
+	}
+	// Here we don't even understand the errno from strerror_r()!
+	return STRINGIZE("strerror_r() can't explain errno " << orig_errno
+					 << " (error " << stre_errno << ')');
+}
+
+std::string strerr(int errn)
+{
+	char buffer[256];
+	// Select message_from() function matching the strerror_r() we have on hand.
+	return message_from(errn, buffer, sizeof(buffer),
+						strerror_r(errn, buffer, sizeof(buffer)));
+}
+#endif	// ! LL_WINDOWS
+
+// On either system, shorthand call just infers global 'errno'.
+std::string strerr()
+{
+	return strerr(errno);
+}
+
+int warnif(const std::string& desc, const std::string& filename, int rc, int accept=0)
+{
+	if (rc < 0)
+	{
+		// Capture errno before we start emitting output
+		int errn = errno;
+		// For certain operations, a particular errno value might be
+		// acceptable -- e.g. stat() could permit ENOENT, mkdir() could permit
+		// EEXIST. Don't warn if caller explicitly says this errno is okay.
+		if (errn != accept)
+		{
+			LL_WARNS("LLFile") << "Couldn't " << desc << " '" << filename
+							   << "' (errno " << errn << "): " << strerr(errn) << LL_ENDL;
+		}
+#if 0 && LL_WINDOWS                 // turn on to debug file-locking problems
+		// If the problem is "Permission denied," maybe it's because another
+		// process has the file open. Try to find out.
+		if (errn == EACCES)         // *not* EPERM
+		{
+			// Only do any of this stuff (before LL_ENDL) if it will be logged.
+			LL_DEBUGS("LLFile") << empty;
+			const char* TEMP = getenv("TEMP");
+			if (! TEMP)
+			{
+				LL_CONT << "No $TEMP, not running 'handle'";
+			}
+			else
+			{
+				std::string tf(TEMP);
+				tf += "\\handle.tmp";
+				// http://technet.microsoft.com/en-us/sysinternals/bb896655
+				std::string cmd(STRINGIZE("handle \"" << filename
+										  // "openfiles /query /v | fgrep -i \"" << filename
+										  << "\" > \"" << tf << '"'));
+				LL_CONT << cmd;
+				if (system(cmd.c_str()) != 0)
+				{
+					LL_CONT << "\nDownload 'handle.exe' from http://technet.microsoft.com/en-us/sysinternals/bb896655";
+				}
+				else
+				{
+					std::ifstream inf(tf);
+					std::string line;
+					while (std::getline(inf, line))
+					{
+						LL_CONT << '\n' << line;
+					}
+				}
+				LLFile::remove(tf);
+			}
+			LL_CONT << LL_ENDL;
+		}
+#endif  // LL_WINDOWS hack to identify processes holding file open
+	}
+	return rc;
+}
+
 // static
 int	LLFile::mkdir(const std::string& dirname, int perms)
 {
-#if LL_WINDOWS	
+#if LL_WINDOWS
 	// permissions are ignored on Windows
 	std::string utf8dirname = dirname;
 	llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
-	return _wmkdir(utf16dirname.c_str());
+	int rc = _wmkdir(utf16dirname.c_str());
 #else
-	return ::mkdir(dirname.c_str(), (mode_t)perms);
+	int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
 #endif
+	// We often use mkdir() to ensure the existence of a directory that might
+	// already exist. Don't spam the log if it does.
+	return warnif("mkdir", dirname, rc, EEXIST);
 }
 
 // static
 int	LLFile::rmdir(const std::string& dirname)
 {
-#if LL_WINDOWS	
+#if LL_WINDOWS
 	// permissions are ignored on Windows
 	std::string utf8dirname = dirname;
 	llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
-	return _wrmdir(utf16dirname.c_str());
+	int rc = _wrmdir(utf16dirname.c_str());
 #else
-	return ::rmdir(dirname.c_str());
+	int rc = ::rmdir(dirname.c_str());
 #endif
+	return warnif("rmdir", dirname, rc);
 }
 
 // static
 #if	LL_WINDOWS
 	std::string utf8filename = filename;
 	llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
-	return _wremove(utf16filename.c_str());
+	int rc = _wremove(utf16filename.c_str());
 #else
-	return ::remove(filename.c_str());
+	int rc = ::remove(filename.c_str());
 #endif
+	return warnif("remove", filename, rc);
 }
 
 int	LLFile::rename(const std::string& filename, const std::string& newname)
 	std::string utf8newname = newname;
 	llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
 	llutf16string utf16newname = utf8str_to_utf16str(utf8newname);
-	return _wrename(utf16filename.c_str(),utf16newname.c_str());
+	int rc = _wrename(utf16filename.c_str(),utf16newname.c_str());
 #else
-	return ::rename(filename.c_str(),newname.c_str());
+	int rc = ::rename(filename.c_str(),newname.c_str());
 #endif
+	return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc);
 }
 
 int	LLFile::stat(const std::string& filename, llstat* filestatus)
 #if LL_WINDOWS
 	std::string utf8filename = filename;
 	llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
-	return _wstat(utf16filename.c_str(),filestatus);
+	int rc = _wstat(utf16filename.c_str(),filestatus);
 #else
-	return ::stat(filename.c_str(),filestatus);
+	int rc = ::stat(filename.c_str(),filestatus);
 #endif
+	// We use stat() to determine existence (see isfile(), isdir()).
+	// Don't spam the log if the subject pathname doesn't exist.
+	return warnif("stat", filename, rc, ENOENT);
 }
 
 bool LLFile::isdir(const std::string& filename)
 {
 	llstat st;
-	
+
 	return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
 }
 
 bool LLFile::isfile(const std::string& filename)
 {
 	llstat st;
-	
+
 	return stat(filename, &st) == 0 && S_ISREG(st.st_mode);
 }
 
 	ios_base::openmode _Mode,
 	int _Prot)
 {	// open a C stream with specified mode
-	
+
 	LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot);
 	if(filep == NULL)
 	{
 	return false;
 }
 llifstream::~llifstream()
-{	
+{
 	if (_ShouldClose)
 	{
 		close();
 
 void llofstream::open(const std::string& _Filename,	/* Flawfinder: ignore */
 	ios_base::openmode _Mode,
-	int _Prot)	
+	int _Prot)
 {	// open a C stream with specified mode
 
 	LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot);
 
 llofstream::llofstream(const std::string& _Filename,
 	std::ios_base::openmode _Mode,
-	int _Prot) 
+	int _Prot)
 		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false)
 {	// construct with named file and specified mode
 	open(_Filename, _Mode , _Prot);	/* Flawfinder: ignore */
 }
 
 llofstream::~llofstream()
-{	
+{
 	// destroy the object
 	if (_ShouldClose)
 	{

File indra/llcommon/llinitparam.cpp

+/** 
+ * @file llinitparam.cpp
+ * @brief parameter block abstraction for creating complex objects and 
+ * parsing construction parameters from xml and LLSD
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llinitparam.h"
+
+
+namespace LLInitParam
+{
+	//
+	// Param
+	//
+	Param::Param(BaseBlock* enclosing_block)
+	:	mIsProvided(false)
+	{
+		const U8* my_addr = reinterpret_cast<const U8*>(this);
+		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
+		mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr);
+	}
+
+	//
+	// ParamDescriptor
+	//
+	ParamDescriptor::ParamDescriptor(param_handle_t p, 
+									merge_func_t merge_func, 
+									deserialize_func_t deserialize_func, 
+									serialize_func_t serialize_func,
+									validation_func_t validation_func,
+									inspect_func_t inspect_func,
+									S32 min_count,
+									S32 max_count)
+	:	mParamHandle(p),
+		mMergeFunc(merge_func),
+		mDeserializeFunc(deserialize_func),
+		mSerializeFunc(serialize_func),
+		mValidationFunc(validation_func),
+		mInspectFunc(inspect_func),
+		mMinCount(min_count),
+		mMaxCount(max_count),
+		mUserData(NULL)
+	{}
+
+	ParamDescriptor::ParamDescriptor()
+	:	mParamHandle(0),
+		mMergeFunc(NULL),
+		mDeserializeFunc(NULL),
+		mSerializeFunc(NULL),
+		mValidationFunc(NULL),
+		mInspectFunc(NULL),
+		mMinCount(0),
+		mMaxCount(0),
+		mUserData(NULL)
+	{}
+
+	ParamDescriptor::~ParamDescriptor()
+	{
+		delete mUserData;
+	}
+
+	//
+	// Parser
+	//
+	Parser::~Parser()
+	{}
+
+	void Parser::parserWarning(const std::string& message)
+	{
+		if (mParseSilently) return;
+		llwarns << message << llendl;
+	}
+	
+	void Parser::parserError(const std::string& message)
+	{
+		if (mParseSilently) return;
+		llerrs << message << llendl;
+	}
+
+
+	//
+	// BlockDescriptor
+	//
+	void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data) 
+	{
+		mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
+		std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
+		std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
+		std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
+	}
+
+	BlockDescriptor::BlockDescriptor()
+	:	mMaxParamOffset(0),
+		mInitializationState(UNINITIALIZED),
+		mCurrentBlockPtr(NULL)
+	{}
+
+	// called by each derived class in least to most derived order
+	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
+	{
+		descriptor.mCurrentBlockPtr = this;
+		descriptor.mMaxParamOffset = block_size;
+
+		switch(descriptor.mInitializationState)
+		{
+		case BlockDescriptor::UNINITIALIZED:
+			// copy params from base class here
+			descriptor.aggregateBlockData(base_descriptor);
+
+			descriptor.mInitializationState = BlockDescriptor::INITIALIZING;
+			break;
+		case BlockDescriptor::INITIALIZING:
+			descriptor.mInitializationState = BlockDescriptor::INITIALIZED;
+			break;
+		case BlockDescriptor::INITIALIZED:
+			// nothing to do
+			break;
+		}
+	}
+
+	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const
+	{
+		const U8* param_address = reinterpret_cast<const U8*>(param);
+		const U8* baseblock_address = reinterpret_cast<const U8*>(this);
+		return (param_address - baseblock_address);
+	}
+
+	bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)
+	{
+		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true))
+		{
+			if (!silent)
+			{
+				p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str()));
+			}
+			return false;
+		}
+		return true;
+	}
+
+
+	bool BaseBlock::validateBlock(bool emit_errors) const
+	{
+		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+		for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
+		{
+			const Param* param = getParamFromHandle(it->first);
+			if (!it->second(param))
+			{
+				if (emit_errors)
+				{
+					llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
+				}
+				return false;
+			}
+		}
+		return true;
+	}
+
+	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
+	{
+		// named param is one like LLView::Params::follows
+		// unnamed param is like LLView::Params::rect - implicit
+		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+
+		for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); 
+			it != block_data.mUnnamedParams.end(); 
+			++it)
+		{
+			param_handle_t param_handle = (*it)->mParamHandle;
+			const Param* param = getParamFromHandle(param_handle);
+			ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
+			if (serialize_func)
+			{
+				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
+				// each param descriptor remembers its serial number
+				// so we can inspect the same param under different names
+				// and see that it has the same number
+				name_stack.push_back(std::make_pair("", true));
+				serialize_func(*param, parser, name_stack, diff_param);
+				name_stack.pop_back();
+			}
+		}
+
+		for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
+			it != block_data.mNamedParams.end();
+			++it)
+		{
+			param_handle_t param_handle = it->second->mParamHandle;
+			const Param* param = getParamFromHandle(param_handle);
+			ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
+			if (serialize_func && param->anyProvided())
+			{
+				// Ensure this param has not already been serialized
+				// Prevents <rect> from being serialized as its own tag.
+				bool duplicate = false;
+				for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); 
+					it2 != block_data.mUnnamedParams.end(); 
+					++it2)
+				{
+					if (param_handle == (*it2)->mParamHandle)
+					{
+						duplicate = true;
+						break;
+					}
+				}
+
+				//FIXME: for now, don't attempt to serialize values under synonyms, as current parsers
+				// don't know how to detect them
+				if (duplicate) 
+				{
+					continue;
+				}
+
+				name_stack.push_back(std::make_pair(it->first, !duplicate));
+				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
+				serialize_func(*param, parser, name_stack, diff_param);
+				name_stack.pop_back();
+			}
+		}
+	}
+
+	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const
+	{
+		// named param is one like LLView::Params::follows
+		// unnamed param is like LLView::Params::rect - implicit
+		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+
+		for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); 
+			it != block_data.mUnnamedParams.end(); 
+			++it)
+		{
+			param_handle_t param_handle = (*it)->mParamHandle;
+			const Param* param = getParamFromHandle(param_handle);
+			ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc;
+			if (inspect_func)
+			{
+				name_stack.push_back(std::make_pair("", true));
+				inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount);
+				name_stack.pop_back();
+			}
+		}
+
+		for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
+			it != block_data.mNamedParams.end();
+			++it)
+		{
+			param_handle_t param_handle = it->second->mParamHandle;
+			const Param* param = getParamFromHandle(param_handle);
+			ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
+			if (inspect_func)
+			{
+				// Ensure this param has not already been inspected
+				bool duplicate = false;
+				for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); 
+					it2 != block_data.mUnnamedParams.end(); 
+					++it2)
+				{
+					if (param_handle == (*it2)->mParamHandle)
+					{
+						duplicate = true;
+						break;
+					}
+				}
+
+				name_stack.push_back(std::make_pair(it->first, !duplicate));
+				inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
+				name_stack.pop_back();
+			}
+		}
+
+		return true;
+	}
+
+	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored)
+	{
+		BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+		bool names_left = name_stack_range.first != name_stack_range.second;
+
+		bool new_name = names_left
+						? name_stack_range.first->second
+						: true;
+
+		if (names_left)
+		{
+			const std::string& top_name = name_stack_range.first->first;
+
+			ParamDescriptor::deserialize_func_t deserialize_func = NULL;
+			Param* paramp = NULL;
+
+			BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
+			if (found_it != block_data.mNamedParams.end())
+			{
+				// find pointer to member parameter from offset table
+				paramp = getParamFromHandle(found_it->second->mParamHandle);
+				deserialize_func = found_it->second->mDeserializeFunc;
+					
+				Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);
+				++new_name_stack.first;
+				if (deserialize_func(*paramp, p, new_name_stack, new_name))
+				{
+					// value is no longer new, we know about it now