diff --git a/PNMain.cpp b/PNMain.cpp
index e00ff885080dc07407dcd03c810c2ac69f18c3c6..33d9c1e5f76581086c4c5768085051d8adefd71b 100644
--- a/PNMain.cpp
+++ b/PNMain.cpp
@@ -46,8 +46,12 @@
 
 #include "globals.h"
 
+// yaml includes
+#include <yaml-cpp/yaml.h>
+
 using namespace std;
 using namespace IRDB_SDK;
+// using namespace YAML;
 // using namespace MEDS_Annotation;
 
 #define ALLOF(a) begin(a),end(a)
@@ -248,6 +252,165 @@ std::string getStepName(void) const override
         return "p1transform";
 }
 
+// Read specified SLX transformation parameters, including per-function overrides,
+//  from specification file SLX.yaml and override the values that came from command-line
+//  args, which were obtained from parseArgs() below.
+void parseYAML(void)
+{
+	bool FileExists = false;
+	if (FILE *YAMLFile = fopen("SLX.yaml", "r"))
+	{
+		FileExists = (0 == fclose(YAMLFile));
+	}
+
+	if (!FileExists)
+	{
+		cout << "File SLX.yaml does not exist." << endl;
+		return;
+	}
+
+	YAML::Node basenode = YAML::LoadFile("SLX.yaml");
+	if (basenode.IsNull()) 
+	{
+		cout << "ERROR: Failure to load file SLX.yaml" << endl;
+		return;
+	}
+
+	// Get the global defaults YAML node.
+	YAML::Node globalnode = basenode["global_policy"];
+	if (globalnode.IsNull())
+	{
+		cout << "WARNING: No global_policy YAML node found" << endl;
+	}
+	else
+	{
+		// Override parseArgs()-obtained values; log differences.
+		YAML::Node randomseednode = globalnode["random_seed"];
+		if (!randomseednode.IsNull())
+		{
+			string randomseedvalstr = randomseednode.as<std::string>();
+			if (0 != randomseedvalstr.compare("<randomly selected value>"))
+			{
+				// A particular non-random value is specified so that runs
+				//  can be duplicated.
+				int new_seed_value = stoi(randomseedvalstr, nullptr, 10);
+				int old_seed_value = pn_options->getRandomSeed();
+				if (new_seed_value != old_seed_value) 
+				{
+					cout << "YAML: Changing random seed from " << old_seed_value << " to " << new_seed_value << endl;
+					pn_options->setRandomSeed(new_seed_value);
+				}
+			}
+		}
+
+		YAML::Node minstacknode = globalnode["min_stack_padding"];
+		if (!minstacknode.IsNull())
+		{
+			string minstackvalstr = minstacknode.as<std::string>();
+			if (0 != minstackvalstr.compare(""))
+			{
+				// A particular minimum stack padding is specified.
+				int new_minpad_value = stoi(minstackvalstr, nullptr, 10);
+				int old_minpad_value = pn_options->getMinStackPadding();
+				if (new_minpad_value != old_minpad_value)
+				{
+					cout << "YAML: Changing min stack padding from " << old_minpad_value << " to " << new_minpad_value << endl;
+					pn_options->setMinStackPadding(new_minpad_value);
+				}
+			}
+		}
+
+		YAML::Node maxstacknode = globalnode["max_stack_padding"];
+		if (!maxstacknode.IsNull())
+		{
+			string maxstackvalstr = maxstacknode.as<std::string>();
+			if (0 != maxstackvalstr.compare(""))
+			{
+				// A particular maximum stack padding is specified.
+				int new_maxpad_value = stoi(maxstackvalstr, nullptr, 10);
+				int old_maxpad_value = pn_options->getMaxStackPadding();
+				if (new_maxpad_value != old_maxpad_value)
+				{
+					cout << "YAML: Changing max stack padding from " << old_maxpad_value << " to " << new_maxpad_value << endl;
+					pn_options->setMaxStackPadding(new_maxpad_value);
+				}
+			}
+		}
+
+		YAML::Node recminstacknode = globalnode["recursive_min_stack_padding"];
+		if (!recminstacknode.IsNull())
+		{
+			string recminstackvalstr = recminstacknode.as<std::string>();
+			if (0 != recminstackvalstr.compare(""))
+			{
+				// A particular minimum stack padding for recursive functions is specified.
+				int new_recminpad_value = stoi(recminstackvalstr, nullptr, 10);
+				int old_recminpad_value = pn_options->getRecursiveMinStackPadding();
+				if (new_recminpad_value != old_recminpad_value)
+				{
+					cout << "YAML: Changing recursive min stack padding from " << old_recminpad_value << " to " << new_recminpad_value << endl;
+					pn_options->setRecursiveMinStackPadding(new_recminpad_value);
+				}
+			}
+		}
+
+		YAML::Node recmaxstacknode = globalnode["recursive_max_stack_padding"];
+		if (!recmaxstacknode.IsNull())
+		{
+			string recmaxstackvalstr = recmaxstacknode.as<std::string>();
+			if (0 != recmaxstackvalstr.compare(""))
+			{
+				// A particular maximum stack padding for recursive functions is specified.
+				int new_recmaxpad_value = stoi(recmaxstackvalstr, nullptr, 10);
+				int old_recmaxpad_value = pn_options->getRecursiveMaxStackPadding();
+				if (new_recmaxpad_value != old_recmaxpad_value)
+				{
+					cout << "YAML: Changing recursive max stack padding from " << old_recmaxpad_value << " to " << new_recmaxpad_value << endl;
+					pn_options->setRecursiveMaxStackPadding(new_recmaxpad_value);
+				}
+			}
+		}
+
+#if 0	// auto_initialize is for the initialize_stack transform; never merged into p1transform.
+		YAML::Node autoinitnode = globalnode["auto_initialize"];
+		if (!autoinitnode.IsNull())
+		{
+			string autoinitvalstr = autoinitnode.as<std::string>();
+			if (0 != autoinitvalstr.compare(""))
+			{
+				// A particular auto_initialize canary value is specified.
+				int new_autoinit_value = stoi(autoinitvalstr, nullptr, 10);
+				int old_autoinit_value = pn_options->getCanaryValue();
+				if (new_autoinit_value != old_autoinit_value)
+				{
+					cout << "YAML: Changing auto_init canary value from " << old_autoinit_value << " to " << new_autoinit_value << endl;
+					pn_options->setCanaryValue(new_autoinit_value);
+				}
+			}
+		}
+#endif
+
+#if 0	// canary types of float, top, and bottom do not seem to exist yet
+		YAML::Node canarytypenode = globalnode["canary_type"];
+		if (!canarytypenode.IsNull())
+		{
+			string canarytypevalstr = canarytypenode.as<std::string>();
+			if (0 != canarytypevalstr.compare(""))
+			{
+				// A particular auto_initialize canary value is specified.
+				int new_autoinit_value = stoi(autoinitvalstr, nullptr, 10);
+				int old_autoinit_value = pn_options->getCanaryValue();
+				if (new_autoinit_value != old_autoinit_value)
+				{
+					cout << "YAML: Changing auto_init canary value from " << old_autoinit_value << " to " << new_autoinit_value << endl;
+					pn_options->setCanaryValue(new_autoinit_value);
+				}
+			}
+		}	
+#endif
+	}
+	return;
+} // end of parseYAML()
 
 int parseArgs(const vector<string> step_args)
 {
@@ -491,6 +654,9 @@ int parseArgs(const vector<string> step_args)
 	assert(pn_options->getMaxStackPadding() >= pn_options->getMinStackPadding());
 	assert(pn_options->getRecursiveMaxStackPadding() >= pn_options->getRecursiveMinStackPadding());
 
+	// Override values using YAML specification file.
+	this->parseYAML();
+
 	cout << "min_stack_padding: " << pn_options->getMinStackPadding() << endl;
 	cout << "max_stack_padding: " << pn_options->getMaxStackPadding() << endl;
 	cout << "recursive_min_stack_padding: " << pn_options->getRecursiveMinStackPadding() << endl;
diff --git a/SConscript b/SConscript
index 5038bcc9fe04e15a864a25317c003df403294016..5c70f53d18a611081523cbfb4124e25c0fc5c892 100644
--- a/SConscript
+++ b/SConscript
@@ -8,6 +8,7 @@ LIBS= " irdb-cfg irdb-transform irdb-core EXEIO "
 
 cpppath='''
         $IRDB_SDK/include
+        $P1_HOME/third_party/yaml-cpp/include
 	$PEASOUP_HOME/irdb-libs/libEXEIO/include
         '''
 
@@ -16,9 +17,22 @@ myenv.Append(LIBPATH=Split(libpath))
 myenv.Append(CPPPATH=Split(cpppath))
 
 
+yamlcpp_files=Glob("third_party/yaml-cpp/src/*.cpp")
 
+p1_files=Glob( Dir('.').srcnode().abspath+"/*.cpp" )
+
+p2_files="P1_utility.cpp PNTransformDriver.cpp PNStackLayout.cpp \
+PNRange.cpp Range.cpp OffsetInference.cpp DirectOffsetInference.cpp \
+ScaledOffsetInference.cpp P1Inference.cpp PNRegularExpressions.cpp \
+PNMain.cpp StackLayout.cpp General_Utility.cpp \
+AnnotationBoundaryGenerator.cpp PrecedenceBoundaryInference.cpp \
+PNIrdbManager.cpp EhUpdater.cpp"
+
+all_files=p1_files+yamlcpp_files
+
+# Does not work; cannot concatenate a string and a Glob.
+# all_files=p2_files+yamlcpp_files
 
-all_files="P1_utility.cpp PNTransformDriver.cpp PNStackLayout.cpp PNRange.cpp Range.cpp OffsetInference.cpp DirectOffsetInference.cpp ScaledOffsetInference.cpp P1Inference.cpp PNRegularExpressions.cpp PNMain.cpp StackLayout.cpp General_Utility.cpp AnnotationBoundaryGenerator.cpp PrecedenceBoundaryInference.cpp PNIrdbManager.cpp EhUpdater.cpp"
 
 p1=myenv.SharedLibrary("p1transform.so", Split(all_files), LIBS=Split(LIBS))
 install=myenv.Install("$P1_HOME/plugins_install/", p1)
diff --git a/integertransformdriver.cpp b/integertransformdriver.cpp
deleted file mode 100644
index e1cf735178a41d57f093db27779590f6cc456bb3..0000000000000000000000000000000000000000
--- a/integertransformdriver.cpp
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 - University of Virginia 
- *
- * This file may be used and modified for non-commercial purposes as long as 
- * all copyright, permission, and nonwarranty notices are preserved.  
- * Redistribution is prohibited without prior written consent from the University 
- * of Virginia.
- *
- * Please contact the authors for restrictions applying to commercial use.
- *
- * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Author: University of Virginia
- * e-mail: jwd@virginia.com
- * URL   : http://www.cs.virginia.edu/
- *
- */
-
-#include <stdlib.h>
-#include <fstream>
-#include <irdb-core>
-#include <getopt.h>
-#include <libgen.h>
-
-#include "MEDS_AnnotationParser.hpp"
-#include "transformutils.h"
-#include "integertransform.hpp"
-#include "integertransform32.hpp"
-#include "integertransform64.hpp"
-#include "pointercheck64.hpp"
-
-// current convention
-#define BINARY_NAME "a.ncexe"
-#define ANNOTATION_SUFFIX ".infoannot"
-#define SHARED_OBJECTS_DIR "shared_objects"
-
-using namespace std;
-using namespace libTransform;
-
-bool saturating_arithmetic = false;
-bool path_manip_detected = false; // deprecated
-bool instrument_idioms = false;
-bool warning_only = false;
-bool check_pointers = false;
-
-void usage()
-{
-	cerr << "Usage: integertransformdriver.exe <variant_id> <filtered_functions> <integer.warning.addresses> [--saturate] [--instrument-idioms] [--check-pointers] [--warning]"<<endl;
-}
-
-int parse_args(int p_argc, char* p_argv[])
-{
-	int option = 0;
-	char options[] = "s:i:w:c";
-	struct option long_options[] = {
-		{"saturate", no_argument, NULL, 's'},
-		{"instrument-idioms", no_argument, NULL, 'i'},
-		{"warning", no_argument, NULL, 'w'},
-		{"check-pointers", no_argument, NULL, 'c'},
-		{NULL, no_argument, NULL, '\0'},         // end-of-array marker
-	};
-
-	while ((option = getopt_long(
-		p_argc,
-		p_argv,
-		options,
-		long_options,
-		NULL)) != -1)
-	{
-		switch (option)
-		{
-			case 's':
-			{
-				saturating_arithmetic = true;
-				printf("saturating arithmetic enabled\n");
-				break;
-			}
-			case 'i':
-			{
-				printf("instrument idioms enabled\n");
-				instrument_idioms = true;
-				break;
-			}
-			case 'w':
-			{
-				printf("warning only mode\n");
-				warning_only = true;
-				break;
-			}
-			case 'c':
-			{
-				printf("check pointers mode\n");
-				check_pointers = true;
-				break;
-			}
-			default:
-				return 1;
-		}
-	}
-	return 0;
-}
-
-std::set<VirtualOffset> getInstructionWarnings(char *warningFilePath)
-{
-	std::set<VirtualOffset> warnings;
-	ifstream warningsFile;
-
-	warningsFile.open(warningFilePath);
-
-	if (warningsFile.is_open())
-	{
-		while (!warningsFile.eof())
-		{
-			string address;
-			getline(warningsFile, address);
-
-			if (!address.empty())
-			{
-				VirtualOffset vo(address);
-				warnings.insert(vo);
-
-				cerr << "Detected warning address at: 0x" << hex << vo.getOffset() << endl;
-			}
-		}
-	}
-
-	warningsFile.close();
-
-	cerr << "Detected a total of " << warnings.size() << " benign addresses" << endl;
-	return warnings;
-}
-
-int main(int argc, char **argv)
-{
-	if(argc < 4)
-	{
-		usage();
-		exit(1);
-	}
-
-	string programName(argv[0]);
-	int variantID = atoi(argv[1]);
-	set<string> filteredFunctions = getFunctionList(argv[2]);
-	char *integerWarnings = argv[3];
-
-	parse_args(argc, argv);
-
-	VariantID_t *pidp=NULL;
-
-	/* setup the interface to the sql server */
-	pqxxDB_t pqxx_interface;
-	BaseObj_t::setInterface(&pqxx_interface);
-
-	pidp=new VariantID_t(variantID);
-	assert(pidp->isRegistered()==true);
-
-	bool one_success = false;
-	for(set<File_t*>::iterator it=pidp->getFiles().begin();
-	    it!=pidp->getFiles().end();
-		++it)
-	{
-		File_t* this_file = *it;
-		FileIR_t *firp = new FileIR_t(*pidp, this_file);
-		char *fileBasename = basename((char*)this_file->getURL().c_str());
-
-		assert(firp && pidp);
-
-		try 
-		{
-			string annotationFilename;
-			// need to map filename to integer annotation file produced by STARS
-			// this should be retrieved from the IRDB but for now, we use files to store annotations
-			// convention from within the peasoup subdirectory is:
-			//      a.ncexe.infoannot
-			//      shared_objects/<shared-lib-filename>.infoannot
-			if (strcmp(fileBasename, BINARY_NAME) == 0)
-				annotationFilename = string(BINARY_NAME) + string(ANNOTATION_SUFFIX);
-			else
-				annotationFilename = string(SHARED_OBJECTS_DIR) + "/" + fileBasename + ANNOTATION_SUFFIX;
-
-			cerr << "annotation file: " << annotationFilename << endl;
-
-			// parse MEDS integer annotations
-			ifstream annotationFile(annotationFilename.c_str(), ifstream::in);
-			if (!annotationFile.is_open())
-			{
-				cerr << "annotation file not found: " << annotationFilename.c_str() << endl;
-				continue;
-			}
-
-			MEDS_AnnotationParser annotationParser(annotationFile);
-
-			// this is now wrong as we're instrumenting shared libraries
-			// we need to display file IDs along with the PC to distinguish between various libs
-			std::set<VirtualOffset> warnings = getInstructionWarnings(integerWarnings); // keep track of instructions that should be instrumented as warnings (upon detection, print diagnostic & continue)
-
-			MEDS_Annotations_t annotations = annotationParser.getAnnotations();
-
-			cout << "integer transform driver: found " << annotations.size() << " annotations" << endl;
-
-			// do the transformation
-
-			libTransform::IntegerTransform *intxform = NULL;
-			if(firp->getArchitectureBitWidth()==64)
-			{
-				if (check_pointers)
-				{
-					intxform = new PointerCheck64(pidp, firp, &annotations, &filteredFunctions, &warnings);
-					intxform->setInstrumentIdioms(true);
-				}
-				else
-					intxform = new IntegerTransform64(pidp, firp, &annotations, &filteredFunctions, &warnings);
-			}
-			else
-			{
-				intxform = new IntegerTransform32(pidp, firp, &annotations, &filteredFunctions, &warnings);
-			}
-
-			intxform->setSaturatingArithmetic(saturating_arithmetic);
-			intxform->setPathManipulationDetected(path_manip_detected);
-			intxform->setInstrumentIdioms(instrument_idioms);
-			intxform->setWarningsOnly(warning_only);
-
-			int exitcode = intxform->execute();
-
-			if (exitcode == 0)
-			{
-				one_success = true;
-				firp->writeToDB();
-				intxform->logStats();
-				delete firp;
-			}
-		}
-		catch (DatabaseError_t pnide)
-		{
-			cerr << programName << ": Unexpected database error: " << pnide << "file url: " << this_file->getURL() << endl;
-		}
-		catch (...)
-		{
-			cerr << programName << ": Unexpected error file url: " << this_file->getURL() << endl;
-		}
-	} // end file iterator
-
-	// if any integer transforms for any files succeeded, we commit
-	if (one_success)
-		pqxx_interface.Commit();
-
-	return 0;
-}
diff --git a/nulltransform.cpp b/nulltransform.cpp
deleted file mode 100644
index b1951aecd6b3b5c4c69b4113edf28ff085962223..0000000000000000000000000000000000000000
--- a/nulltransform.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 - University of Virginia 
- *
- * This file may be used and modified for non-commercial purposes as long as 
- * all copyright, permission, and nonwarranty notices are preserved.  
- * Redistribution is prohibited without prior written consent from the University 
- * of Virginia.
- *
- * Please contact the authors for restrictions applying to commercial use.
- *
- * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Author: University of Virginia
- * e-mail: jwd@virginia.com
- * URL   : http://www.cs.virginia.edu/
- *
- */
-
-#include <iostream>
-#include "targ-config.h"
-
-#include "elfio/elfio.hpp"
-#include "elfio/elfio_dump.hpp"
-
-#include "null_transform.h"
-
-
-int main(int argc, char **argv)
-{
-  if (argc < 3)
-  {
-    std::cerr << "usage: " << argv[0] << " <elfFile> <annotationFile> [<spriFile>]" << std::endl;
-    return 1;
-  }
-
-  std::cout << "Reading elf file:" << argv[1] << std::endl;
-  std::cout << "Reading MEDS annotation file:" << argv[2] << std::endl;
-
-  NullTransform *nullTransform;
-
-  if (argc == 3)
-    nullTransform = new NullTransform(argv[1], argv[2], (char*)"spri.out");
-  else
-    nullTransform = new NullTransform(argv[1], argv[2], argv[3]);
-
-  nullTransform->rewrite();
-
-  vector<wahoo::Function*> ncf = nullTransform->getNonCandidateFunctions();
-  vector<wahoo::Function*> cf = nullTransform->getCandidateFunctions();
-  vector<wahoo::Function*> af = nullTransform->getAllFunctions();
-
-  std::cout << "#functions: " << af.size() << std::endl;
-  std::cout << "#candidate functions: " << cf.size() << std::endl;
-  std::cout << "#non-candidate functions: " << ncf.size() << std::endl;
-}
diff --git a/transformutils.cpp b/transformutils.cpp
deleted file mode 100644
index bfab574def792f06ceb16698ea8ba988f147ad0a..0000000000000000000000000000000000000000
--- a/transformutils.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2013, 2014 - University of Virginia 
- *
- * This file may be used and modified for non-commercial purposes as long as 
- * all copyright, permission, and nonwarranty notices are preserved.  
- * Redistribution is prohibited without prior written consent from the University 
- * of Virginia.
- *
- * Please contact the authors for restrictions applying to commercial use.
- *
- * THIS SOURCE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Author: University of Virginia
- * e-mail: jwd@virginia.com
- * URL   : http://www.cs.virginia.edu/
- *
- */
-
-#include <iostream>
-#include <fstream>
-#include <string>
-
-#include "transformutils.h"
-
-using namespace std;
-
-set<string> getFunctionList(char *p_filename)
-{
-	set<string> functionList;
-
-	ifstream candidateFile;
-	candidateFile.open(p_filename);
-
-	if(candidateFile.is_open())
-	{
-		while(!candidateFile.eof())
-		{
-			string functionName;
-			getline(candidateFile, functionName);
-
-			functionList.insert(functionName);
-		}
-
-		candidateFile.close();
-	}
-
-	return functionList;
-}
-