From e30d3b21a84142963e5f217125d6930589910343 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Tue, 25 Jun 2019 20:16:13 -0400 Subject: Update site --- .../bjc.everge/ControlledString$Control.html | 1 + docs/jacoco-ut/bjc.everge/ControlledString.html | 1 + .../bjc.everge/ControlledString.java.html | 178 +++++ docs/jacoco-ut/bjc.everge/Everge$InputStatus.html | 1 + docs/jacoco-ut/bjc.everge/Everge.html | 1 + docs/jacoco-ut/bjc.everge/Everge.java.html | 436 +++++++++++ docs/jacoco-ut/bjc.everge/IntHolder.html | 1 + docs/jacoco-ut/bjc.everge/IntHolder.java.html | 67 ++ docs/jacoco-ut/bjc.everge/ReplError.html | 1 + docs/jacoco-ut/bjc.everge/ReplError.java.html | 87 +++ docs/jacoco-ut/bjc.everge/ReplOpts.html | 1 + docs/jacoco-ut/bjc.everge/ReplOpts.java.html | 71 ++ docs/jacoco-ut/bjc.everge/ReplPair.html | 1 + docs/jacoco-ut/bjc.everge/ReplPair.java.html | 815 +++++++++++++++++++++ docs/jacoco-ut/bjc.everge/ReplParseException.html | 1 + .../bjc.everge/ReplParseException.java.html | 59 ++ docs/jacoco-ut/bjc.everge/ReplSet.html | 1 + docs/jacoco-ut/bjc.everge/ReplSet.java.html | 97 +++ docs/jacoco-ut/bjc.everge/StageStatus.html | 1 + docs/jacoco-ut/bjc.everge/StageStatus.java.html | 22 + docs/jacoco-ut/bjc.everge/StringUtils.html | 1 + docs/jacoco-ut/bjc.everge/StringUtils.java.html | 194 +++++ docs/jacoco-ut/bjc.everge/index.html | 1 + docs/jacoco-ut/bjc.everge/index.source.html | 1 + 24 files changed, 2040 insertions(+) create mode 100644 docs/jacoco-ut/bjc.everge/ControlledString$Control.html create mode 100644 docs/jacoco-ut/bjc.everge/ControlledString.html create mode 100644 docs/jacoco-ut/bjc.everge/ControlledString.java.html create mode 100644 docs/jacoco-ut/bjc.everge/Everge$InputStatus.html create mode 100644 docs/jacoco-ut/bjc.everge/Everge.html create mode 100644 docs/jacoco-ut/bjc.everge/Everge.java.html create mode 100644 docs/jacoco-ut/bjc.everge/IntHolder.html create mode 100644 docs/jacoco-ut/bjc.everge/IntHolder.java.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplError.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplError.java.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplOpts.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplOpts.java.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplPair.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplPair.java.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplParseException.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplParseException.java.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplSet.html create mode 100644 docs/jacoco-ut/bjc.everge/ReplSet.java.html create mode 100644 docs/jacoco-ut/bjc.everge/StageStatus.html create mode 100644 docs/jacoco-ut/bjc.everge/StageStatus.java.html create mode 100644 docs/jacoco-ut/bjc.everge/StringUtils.html create mode 100644 docs/jacoco-ut/bjc.everge/StringUtils.java.html create mode 100644 docs/jacoco-ut/bjc.everge/index.html create mode 100644 docs/jacoco-ut/bjc.everge/index.source.html (limited to 'docs/jacoco-ut/bjc.everge') diff --git a/docs/jacoco-ut/bjc.everge/ControlledString$Control.html b/docs/jacoco-ut/bjc.everge/ControlledString$Control.html new file mode 100644 index 0000000..e93afa5 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ControlledString$Control.html @@ -0,0 +1 @@ +ControlledString.Control

ControlledString.Control

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total18 of 180%0 of 0n/a339933
ControlledString.Control(String, String[])90%n/a114411
ControlledString.Control(String)60%n/a113311
ControlledString.Control()30%n/a112211
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ControlledString.html b/docs/jacoco-ut/bjc.everge/ControlledString.html new file mode 100644 index 0000000..70da0b2 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ControlledString.html @@ -0,0 +1 @@ +ControlledString

ControlledString

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total159 of 1590%14 of 140%1212353555
parse(String, String, String, String, String)1260%120%77232311
ControlledString(String)100%n/a114411
ControlledString(String, ControlledString.Control[])80%n/a114411
hasControls()80%20%221111
ControlledString()70%n/a113311
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ControlledString.java.html b/docs/jacoco-ut/bjc.everge/ControlledString.java.html new file mode 100644 index 0000000..2f928e8 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ControlledString.java.html @@ -0,0 +1,178 @@ +ControlledString.java

ControlledString.java

package bjc.everge;
+
+/**
+ * Represents a string with a set of control flags attached to it.
+ *
+ * @author Ben Culkin
+ */
+public class ControlledString {
+	/**
+	 * Represents a single control (a key-values pair)
+	 *
+	 * @author Ben Culkin
+	 */
+	public static class Control {
+		/**
+		 * The name of the control.
+		 */
+		public String name;
+
+		/**
+		 * The arguments to the control.
+		 */
+		public String[] args;
+
+		/**
+		 * Create a new blank control.
+		 */
+		public Control() {
+
+		}
+
+		/**
+		 * Create a new argless control.
+		 *
+		 * @param nam
+		 * 	The name of the control.
+		 */
+		public Control(String nam) {
+			name = nam;
+		}
+
+		/**
+		 * Create a new control.
+		 *
+		 * @param nam
+		 * 	The name of the control.
+		 * @param ars
+		 * 	The arguments of the control.
+		 */
+		public Control(String nam, String... ars) {
+			name = nam;
+			args = ars;
+		}
+	}
+
+	/**
+	 * The string the controls apply to.
+	 */
+	public String strang;
+
+	/**
+	 * The controls that apply to the string.
+	 */
+	public Control[] controls;
+
+	/**
+	 * Create a new blank controlled string.
+	 */
+	public ControlledString() {
+		controls = new Control[0];
+	}
+
+	/**
+	 * Create a new controlled string without any controls.
+	 *
+	 * @param strung
+	 * 	The string to use.
+	 */
+	public ControlledString(String strung) {
+		strang = strung;
+
+		controls = new Control[0];
+	}
+
+	/**
+	 * Create a new controlled string.
+	 *
+	 * @param strung
+	 * 	The string to use.
+	 * @param controls
+	 * 	The controls that apply to the string.
+	 */
+	public ControlledString(String strung, Control... controls) {
+		strang = strung;
+
+		controls = controls;
+	}
+
+	/**
+	 * Check if the string has controls.
+	 *
+	 * @return Whether or not the string has controls.
+	 */
+	public boolean hasControls() {
+		return controls.length > 0;
+	}
+
+	/**
+	 * Parse a controlled string from a regular string.
+	 *
+	 * The controls must be parsed from the beginning of the string, and are indicated by occurances
+	 * of contInd that bracket them from the string. The individual controls are delimited by
+	 * instances of contSep, with arguments to them being separated by occurances of contArg.
+	 *
+	 * Each of those separators (which must be regular strings, not regexes or anything) may be
+	 * escaped by preceeding them with a copy of contEsc.
+	 *
+	 * @param lne
+	 * 	The string to parse frmo.
+	 * @param contInd
+	 * 	The indicator for whether or not there are controls.
+	 * @param contSep
+	 * 	The separator of individual controls.
+	 * @param contArg
+	 * 	The separator of control arguments.
+	 * @param contEsc
+	 * 	The escape string for each of the separators/indicators.
+	 *
+	 * @return A parsed control string.
+	 */
+	public static ControlledString parse(String lne, String contInd, String contSep,
+			String contArg, String contEsc) {
+		if (!lne.startsWith(contInd)) {
+			return new ControlledString(lne);
+		}
+
+		String tmp = lne.substring(2);
+
+		String[] bits = StringUtils.escapeSplit(contEsc, contInd, lne);
+
+		if (bits.length < 2) {
+			String msg = "Did not find control terminator (%s) where it should be";
+			msg = String.format(msg, contInd);
+
+			throw new IllegalArgumentException(msg);
+		}
+
+		ControlledString cs = new ControlledString(bits[0]);
+
+		bits = StringUtils.escapeSplit(contEsc, contSep, bits[1]);
+
+		cs.controls = new Control[bits.length];
+
+		for (int i = 0; i < bits.length; i++) {
+			String bit = bits[i];
+
+			String[] bots = StringUtils.escapeSplit(contEsc, contArg, bit);
+
+			Control cont = new Control(bots[0]);
+
+			if (cont.name.length() > 1) {
+				cont.name = cont.name.toUpperCase();
+			}
+
+			if (bots.length > 1) {
+				cont.args = new String[bots.length - 1];
+				for (int j = 1; j < bots.length; j++) {
+					cont.args[j - 1] = bots[j];
+				}
+			}
+
+			cs.controls[i] = cont;
+		}
+
+		return cs;
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/Everge$InputStatus.html b/docs/jacoco-ut/bjc.everge/Everge$InputStatus.html new file mode 100644 index 0000000..3595e45 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/Everge$InputStatus.html @@ -0,0 +1 @@ +Everge.InputStatus

Everge.InputStatus

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total0 of 34100%0 of 0n/a010401
static {...}34100%n/a010401
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/Everge.html b/docs/jacoco-ut/bjc.everge/Everge.html new file mode 100644 index 0000000..d9253fe --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/Everge.html @@ -0,0 +1 @@ +Everge

Everge

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total534 of 85337%54 of 8334%415512419928
processArgs(List, String[])34211224%331226%25298811601
processInputFile(List, String)1334023%11321%78223301
processArgs(String[])280%40%337711
processInputFile(String)151346%3125%233701
main(String[])90%n/a113311
loadQueue(String[])77691%21083%2711301
Everge()41100%n/a0101101
processString(String)37100%1375%130901
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/Everge.java.html b/docs/jacoco-ut/bjc.everge/Everge.java.html new file mode 100644 index 0000000..8416daa --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/Everge.java.html @@ -0,0 +1,436 @@ +Everge.java

Everge.java

package bjc.everge;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+
+import java.nio.charset.Charset;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Scanner;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * Everge front-end application.
+ *
+ * @author Ben Culkin
+ */
+public class Everge {
+	/**
+	 * Details how we handle our input.
+	 */
+	public static enum InputStatus {
+		/**
+		 * Process the input as a single string.
+		 */
+		ALL,
+		/**
+		 * Process the input line-by-line.
+		 */
+		LINE,
+		/**
+		 * Process the input, splitting it around occurances of a regex.
+		 */
+		REGEX;
+	}
+
+	// Options for doing repl-pairs
+	private ReplOpts ropts = new ReplOpts();
+
+	// Loaded repl-pairs
+	private List<ReplPair> lrp = new ArrayList<>();
+
+	// Input status
+	private InputStatus inputStat = InputStatus.ALL;
+
+	// Are we processing CLI args? (haven't seen a -- yet)
+	private boolean doingArgs = true;
+
+	// Should an NL be printed after each replace?
+	private boolean printNL = true;
+
+	// Verbosity level
+	private int verbosity = 0;
+
+	// The pattern to use for REGEX input mode
+	private String pattern;
+
+	// The queue of arguments to process
+	private Deque<String> argQue = new LinkedList<>();
+
+	// Used to prevent inter-mixing argument alterations with input processing.
+	private ReadWriteLock argLock = new ReentrantReadWriteLock();
+
+	// Input/output streams
+	public PrintStream outStream = System.out;
+	public PrintStream errStream = System.err;
+
+	/**
+	 * Main method for front end,
+	 *
+	 * @param args
+	 * 		The CLI arguments.
+	 */
+	public static void main(String[] args) {
+		Everge evg = new Everge();
+
+		evg.processArgs(args);
+	}
+
+	/**
+	 * Process one or more command line arguments.
+	 *
+	 * @param args
+	 * 		The arguments to process.
+	 * @return Whether we processed succesfully or not.
+	 */
+	public boolean processArgs(String... args) {
+		List<String> errs = new ArrayList<>();
+
+		boolean stat = processArgs(errs, args);
+		if (!stat) {
+			for (String err : errs) {
+				errStream.println(err);
+			}
+		}
+
+		return stat;
+	}
+
+	/**
+	 * Process one or more command line arguments.
+	 *
+	 * @param args
+	 * 		The arguments to process.
+	 * @param errs
+	 * 		The list to stash errors in.
+	 * @return Whether we processed succesfully or not.
+	 */
+	public boolean processArgs(List<String> errs, String... args) {
+		argLock.writeLock().lock();
+
+		boolean retStat = true;
+
+		try {
+			loadQueue(args);
+
+			// Process CLI args
+			while(argQue.size() > 0) {
+				String arg = argQue.pop();
+
+				if (arg.equals("--")) {
+					doingArgs = false;
+					continue;
+				}
+
+				// Process an argument
+				if (doingArgs && arg.startsWith("-")) {
+					String argName = arg;
+					String argBody = "";
+
+					// Process arguments to arguments 
+					int idx = arg.indexOf("=");
+					if (idx != -1) {
+						argName = arg.substring(0, idx);
+						argBody = arg.substring(idx + 1);
+					}
+
+					switch (argName) {
+					case "-n":
+					case "--newline":
+						printNL = true;
+						break;
+					case "-N":
+					case "--no-newline":
+						printNL = false;
+						break;
+					case "-v":
+					case "--verbose":
+						verbosity += 1;
+						break;
+					case "-q":
+					case "--quiet":
+						verbosity -= 1;
+						break;
+					case "--verbosity":
+						if (argQue.size() < 1) {
+							errs.add("[ERROR] No parameter to --verbosity");
+							retStat = false;
+							break;
+						}
+						argBody = argQue.pop();
+						break;
+					case "-V":
+						try {
+							verbosity = Integer.parseInt(argBody);
+						} catch (NumberFormatException nfex) {
+							String msg = String.format("[ERROR] Invalid verbosity: '%s' is not an integer",
+									argBody);
+							errs.add(msg);
+							retStat = false;
+						}
+						break;
+					case "--pattern":
+						if (argQue.size() < 1) {
+							errs.add("[ERROR] No parameter to --pattern");
+							retStat = false;
+							break;
+						}
+						argBody = argQue.pop();
+					case "-p":
+						try {
+							pattern = argBody;
+
+							Pattern.compile(argBody);
+						} catch (PatternSyntaxException psex) {
+							String msg = String.format("[ERROR] Pattern '%s' is invalid: %s",
+									pattern, psex.getMessage());
+							errs.add(msg);
+							retStat = false;
+						}
+						break;
+					case "--file":
+						if (argQue.size() < 1) {
+							errs.add("[ERROR] No argument to --file");
+							retStat = false;
+							break;
+						}
+						argBody = argQue.pop();
+					case "-f":
+						try (FileInputStream fis = new FileInputStream(argBody);
+								Scanner scn = new Scanner(fis)) {
+							List<ReplError> ferrs = new ArrayList<>();
+
+							lrp = ReplPair.readList(lrp, scn, ferrs, ropts);
+
+							if (ferrs.size() > 0) {
+								StringBuilder sb = new StringBuilder();
+								
+								String errString = "an error";
+								if (ferrs.size() > 1) errString = String.format("%d errors");
+
+								{
+									String msg = String.format(
+											"[ERROR] Encountered errors parsing data file'%s'\n",
+											argBody);
+									sb.append(msg);
+								}
+
+								for (ReplError err : ferrs) {
+									sb.append(String.format("\t%s\n", err));
+								}
+
+								errs.add(sb.toString());
+								retStat = false;
+							}
+						} catch (FileNotFoundException fnfex) {
+							String msg = String.format("[ERROR] Could not open data file '%s' for input",
+									argBody);
+							errs.add(msg);
+							retStat = false;
+						} catch (IOException ioex) {
+							String msg = String.format("[ERROR] Unknown I/O error reading data file '%s': %s",
+									argBody, ioex.getMessage());
+							errs.add(msg);
+							retStat = false;
+						}
+						break;
+					case "--arg-file":
+						if (argQue.size() < 1) {
+							errs.add("[ERROR] No argument to --arg-file");
+							break;
+						}
+						argBody = argQue.pop();
+					case "-F":
+						try (FileInputStream fis = new FileInputStream(argBody);
+								Scanner scn = new Scanner(fis)) {
+							List<String> sl = new ArrayList<>();
+
+							while (scn.hasNextLine()) {
+								String ln = scn.nextLine().trim();
+
+								if (ln.equals(""))      continue;
+								if (ln.startsWith("#")) continue;
+
+								sl.add(ln);
+							}
+
+							processArgs(sl.toArray(new String[0]));
+						} catch (FileNotFoundException fnfex) {
+							String msg = String.format("[ERROR] Could not open argument file '%s' for input", argBody);
+							errs.add(msg);
+							retStat = false;
+						} catch (IOException ioex) {
+							String msg = String.format("[ERROR] Unknown I/O error reading input file '%s': %s",
+									argBody, ioex.getMessage());
+							errs.add(msg);
+							retStat = false;
+						}
+						break;
+					default:
+						{
+							String msg = String.format("[ERROR] Unrecognised CLI argument name '%s'\n", argName);
+							errs.add(msg);
+							retStat = false;
+						}
+					}
+				} else {
+					// Strip off an escaped initial dash
+					if (arg.startsWith("\\-")) arg = arg.substring(1);
+
+					processInputFile(arg);
+				}
+			}
+		} finally {
+			argLock.writeLock().unlock();
+		}
+
+		return retStat;
+	}
+
+	/**
+	 * Process a input file.
+	 *
+	 * @param fle
+	 * 		Input file to process.
+	 * @return Whether we processed succesfully or not.
+	 */
+	public boolean processInputFile(String fle) {
+		List<String> errs = new ArrayList<>();
+
+		boolean stat = processInputFile(errs, fle);
+		if (!stat) {
+			for (String err : errs) {
+				errStream.println(err);
+			}
+		}
+
+		return stat;
+	}
+
+	/**
+	 * Process a input file.
+	 *
+	 * @param fle
+	 * 		Input file to process.
+	 * @param errs
+	 * 		List to accumulate errors in.
+	 * @return Whether we processed succesfully or not.
+	 */
+	public boolean processInputFile(List<String> errs, String fle) {
+		argLock.readLock().lock();
+
+		// Read in and do replacements on a file
+		try {
+			if (verbosity > 2) {
+				errStream.printf("[TRACE] Reading file (%s) in mode (%s)\n", fle, inputStat);
+			}
+
+			if (inputStat == InputStatus.ALL) {
+				Path pth = Paths.get(fle);
+
+				if (!Files.isReadable(pth)) {
+					String msg = String.format("[ERROR] File '%s' is not readable\n", fle);
+					errs.add(msg);
+					return false;
+				} else {
+					byte[] inp = Files.readAllBytes(pth);
+
+					String strang = new String(inp, Charset.forName("UTF-8"));
+
+					processString(strang);
+				}
+			} else if (inputStat == InputStatus.LINE) {
+				try (FileInputStream fis = new FileInputStream(fle); Scanner scn = new Scanner(fis)) {
+					while(scn.hasNextLine()) {
+						processString(scn.nextLine());
+					}
+				}
+			} else if (inputStat == InputStatus.REGEX) {
+				try (FileInputStream fis = new FileInputStream(fle); Scanner scn = new Scanner(fis)) {
+					scn.useDelimiter(pattern);
+
+					while(scn.hasNext()) {
+						processString(scn.next());
+					}
+				}
+			} else {
+				String msg = String.format("[INTERNAL-ERROR] Input status '%s' is not yet implemented\n",
+						inputStat);
+				errs.add(msg);
+				return false;
+			}
+		} catch (IOException ioex) {
+			String msg = String.format("[ERROR] Unknown I/O related error for file '%s'\n\tError was %s",
+					fle, ioex.getMessage());
+			errs.add(msg);
+			return false;
+		} finally {
+			argLock.readLock().unlock();
+		}
+
+		return true;
+	}
+
+	/**
+	 * Process an input string.
+	 *
+	 * @param inp
+	 * 		The input string to process.
+	 */
+	public void processString(String inp) {
+		argLock.readLock().lock();
+
+		try {
+			String strang = inp;
+
+			for (ReplPair rp : lrp) {
+				strang = rp.apply(strang);
+			}
+
+			outStream.print(strang);
+			if (printNL) outStream.println();
+		} finally {
+			argLock.readLock().unlock();
+		}
+	}
+
+	// Load arguments into the argument queue.
+	private void loadQueue(String... args) {
+		boolean doArgs = true;
+		for (String arg : args) {
+			if (arg.equals("--")) doArgs = false;
+
+			// Handle things like -nNv correctly
+			if (doArgs) {
+				if (arg.startsWith("-") && !arg.startsWith("--")) {
+					char[] car = arg.substring(1).toCharArray();
+					for (char c : car) {
+						String argstr = String.format("-%c", c);
+						argQue.add(argstr);
+					}
+				} else {
+					argQue.add(arg);
+				}
+			} else {
+				argQue.add(arg);
+			}
+		}
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/IntHolder.html b/docs/jacoco-ut/bjc.everge/IntHolder.html new file mode 100644 index 0000000..7ef6a96 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/IntHolder.html @@ -0,0 +1 @@ +IntHolder

IntHolder

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total10 of 3268%0 of 0n/a2651226
IntHolder(int)60%n/a113311
set(int)40%n/a112211
incr(int)9100%n/a010201
IntHolder()6100%n/a010301
incr()4100%n/a010101
get()3100%n/a010101
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/IntHolder.java.html b/docs/jacoco-ut/bjc.everge/IntHolder.java.html new file mode 100644 index 0000000..746a71a --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/IntHolder.java.html @@ -0,0 +1,67 @@ +IntHolder.java

IntHolder.java

package bjc.everge;
+
+/**
+ * Utility class for ints by ref.
+ *
+ * @author Ben Culkin
+ */
+public class IntHolder {
+	/**
+	 * The int value.
+	 */
+	public int val;
+
+	/**
+	 * Create a new int-holder set to 0.
+	 */
+	public IntHolder() {
+		val = 0;
+	}
+
+	/**
+	 * Create a new int-holder set to a value.
+	 *
+	 * @param i
+	 * 		The value to set the int to.
+	 */
+	public IntHolder(int i) {
+		val = i;
+	}
+
+	/**
+	 * Increment the value by one, and return it.
+	 *
+	 * @return The value of the holder.
+	 */
+	public int incr() {
+		return incr(1);
+	}
+
+	/**
+	 * Increment the value by an amount and return it.
+	 *
+	 * @param i
+	 * 		The amount to increment by.
+	 *
+	 * @return The value of the holder.
+	 */
+	public int incr(int i) {
+		val += 1;
+
+		return val;
+	}
+
+	/**
+	 * Get the value.
+	 *
+	 * @return The value.
+	 */
+	public int get() {
+		return val;
+	}
+
+	public void set(int i) {
+		val = i;
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplError.html b/docs/jacoco-ut/bjc.everge/ReplError.html new file mode 100644 index 0000000..7b798b3 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplError.html @@ -0,0 +1 @@ +ReplError

ReplError

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total72 of 13245%7 of 812%6971825
toString()500%40%334411
toPrintString(String)183666%3125%232501
toPrintString()40%n/a111111
ReplError(int, int, String, String)15100%n/a010601
ReplError(IntHolder, IntHolder, String, String)9100%n/a010201
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplError.java.html b/docs/jacoco-ut/bjc.everge/ReplError.java.html new file mode 100644 index 0000000..e2d44dc --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplError.java.html @@ -0,0 +1,87 @@ +ReplError.java

ReplError.java

package bjc.everge;
+
+/**
+ * Represents an error encountered parsing ReplPairs
+ *
+ * @author Ben Culkin
+ */
+public class ReplError {
+	/**
+	 * The line the error occured on.
+	 */
+	public int line;
+	/**
+	 * The number of pairs we have processed so far.
+	 */
+	public int numPairs;
+
+	/**
+	 * The text of the line we errored on.
+	 */
+	public String txt;
+	/**
+	 * The message of the error.
+	 */
+	public String msg;
+
+	/**
+	 * Create a new ReplPair parse error.
+	 *
+	 * @param lne
+	 * 	The line the error occured on.
+	 * @param nPairs
+	 * 	The number of pairs processed up to this point.
+	 * @param msg
+	 * 	The message detailing the error.
+	 * @param txt
+	 * 	The text that caused the error.
+	 */
+	public ReplError(IntHolder lne, IntHolder nPairs, String msg, String txt) {
+		this(lne.get(), nPairs.get(), msg, txt);
+	}
+
+	/**
+	 * Create a new ReplPair parse error.
+	 *
+	 * @param lne
+	 * 	The line the error occured on.
+	 * @param nPairs
+	 * 	The number of pairs processed up to this point.
+	 * @param msg
+	 * 	The message detailing the error.
+	 * @param txt
+	 * 	The text that caused the error.
+	 */
+	public ReplError(int lne, int nPairs, String msg, String txt) {
+		line = lne;
+		numPairs = nPairs;
+
+		this.txt = txt;
+		this.msg = msg;
+	}
+
+	@Override
+	public String toString() {
+		String errString;
+		if      (txt == null)    errString = "No associated line";
+		else if (txt.equals("")) errString = "Text of line was empty";
+		else                     errString = "Text of line was: " + txt;
+
+		return String.format("line %d, pair %d:%s\n\t%s", line, numPairs, msg, errString);
+	}
+
+	public String toPrintString() {
+		return toPrintString("");
+	}
+
+	public String toPrintString(String hdr) {
+		String errString;
+		if      (txt == null)    errString = "No associated line";
+		else if (txt.equals("")) errString = "Text of line was empty";
+		else                     errString = "Text of line was: " + txt;
+
+		return String.format("[ERROR] line %d, pair %d: %s\n%s\tContext: %s",
+				line, numPairs, msg, hdr, errString);
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplOpts.html b/docs/jacoco-ut/bjc.everge/ReplOpts.html new file mode 100644 index 0000000..ff2c6e2 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplOpts.html @@ -0,0 +1 @@ +ReplOpts

ReplOpts

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total66 of 9631%18 of 180%1011112112
equals(Object)660%180%1010111111
ReplOpts()30100%n/a0101001
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplOpts.java.html b/docs/jacoco-ut/bjc.everge/ReplOpts.java.html new file mode 100644 index 0000000..1194cd3 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplOpts.java.html @@ -0,0 +1,71 @@ +ReplOpts.java

ReplOpts.java

package bjc.everge;
+
+import java.io.PrintStream;
+
+/**
+ * Options for processing ReplPairs.
+ *
+ * @author Ben Culkin.
+ */
+public class ReplOpts {
+	/**
+	 * The default priority.
+	 */
+	public int defPrior = 0;
+
+	/**
+	 * The default stage.
+	 */
+	public int defStage = 0;
+
+	/**
+	 * Whether to process multi-line defns.
+	 */
+	public boolean defMulti = false;
+
+	/**
+	 * Default status.
+	 */
+	public StageStatus defStatus = StageStatus.BOTH;
+
+	/**
+	 * Enable debug info.
+	 */
+	public boolean isDebug = true;
+
+	/**
+	 * Enable trace info.
+	 */
+	public boolean isTrace = false;
+
+	/**
+	 * Enable performance info.
+	 */
+	public boolean isPerf = false;
+
+	public PrintStream outStream = System.out;
+	public PrintStream errStream = System.err;
+
+	@Override
+	public boolean equals(Object o) {
+		if (o == null) return false;
+
+		if (!getClass().equals(o.getClass())) return false;
+
+		ReplOpts ro = (ReplOpts)o;
+
+		if (isPerf != ro.isPerf) return false;
+
+		if (isDebug != ro.isDebug) return false;
+		if (isTrace != ro.isTrace) return false;
+
+		if (defPrior != ro.defPrior) return false;
+		if (defStage != ro.defStage) return false;
+		if (defMulti != ro.defMulti) return false;
+
+		if (defStatus != ro.defStatus) return false;
+
+		return true;
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplPair.html b/docs/jacoco-ut/bjc.everge/ReplPair.html new file mode 100644 index 0000000..f4c8951 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplPair.html @@ -0,0 +1 @@ +ReplPair

ReplPair

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total800 of 1,62250%87 of 18653%73123138336217
readList(List, Scanner, List, ReplOpts)28237056%315162%25433612501
readGlobal(String, Scanner, List, ReplOpts, IntHolder, IntHolder)1869132%181240%1724436901
getControls(String, List, ReplOpts, IntHolder, IntHolder, String)1350%120%77252511
readName(String, Scanner, List, ReplPair, ReplOpts, IntHolder, IntHolder)13111045%111354%1017306001
readMultiLine(String, Scanner, ReplOpts, List, String, IntHolder)378469%81260%61122001
equals(Object)123675%6650%670801
toString()103376%1150%120301
ReplPair(String, String, String)70%n/a112211
readList(List, Scanner)20100%2100%020501
ReplPair(String, String, int, String)18100%n/a010701
compareTo(ReplPair)17100%2100%020201
readList(Scanner)8100%n/a010201
readList(List, Scanner, List)8100%n/a010101
ReplPair()7100%n/a010201
ReplPair(String, String, int)7100%n/a010201
apply(String)7100%n/a010101
ReplPair(String, String)6100%n/a010201
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplPair.java.html b/docs/jacoco-ut/bjc.everge/ReplPair.java.html new file mode 100644 index 0000000..7cfa2b5 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplPair.java.html @@ -0,0 +1,815 @@ +ReplPair.java

ReplPair.java

package bjc.everge;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import java.util.function.UnaryOperator;
+
+import bjc.everge.ControlledString.Control;
+
+/**
+ * String pairs for replacements.
+ *
+ * @author Ben Culkin
+ */
+public class ReplPair implements Comparable<ReplPair>, UnaryOperator<String> {
+	// Line number we read this pair from
+	private int lno;
+
+	// Stage this pair is in
+	private int stage;
+
+	// Status of this pair with regards to doing staging stuff
+	private StageStatus stat = StageStatus.BOTH;
+
+	/**
+	 * The priority for this replacement.
+	 */
+	public int priority;
+
+	/**
+	 * The name of this replacement.
+	 *
+	 * Defaults to the 'find' string.
+	 */
+	public String name;
+
+	/**
+	 * The string to look for.
+	 */
+	public String find;
+
+	/**
+	 * The string to replace it with.
+	 */
+	public String replace;
+
+	/**
+	 * Create a new blank replacement pair.
+	 */
+	public ReplPair() {
+		this("", "", 1, null);
+	}
+
+	/**
+	 * Create a new replacement pair with a priority of 1.
+	 *
+	 * @param f
+	 * 	The string to find.
+	 * @param r
+	 * 	The string to replace.
+	 */
+	public ReplPair(String f, String r) {
+		this(f, r, 1);
+	}
+
+	/**
+	 * Create a new named replacement pair with a priority of 1.
+	 *
+	 * @param f
+	 * 	The string to find.
+	 * @param r
+	 * 	The string to replace.
+	 * @param n
+	 * 	The name of the replacement pair.
+	 */
+	public ReplPair(String f, String r, String n) {
+		this(f, r, 1, n);
+	}
+
+	/**
+	 * Create a new replacement pair with a set priority.
+	 *
+	 * @param f
+	 * 	The string to find.
+	 * @param r
+	 * 	The string to replace.
+	 * @param p
+	 * 	The priority for the replacement.
+	 */
+	public ReplPair(String f, String r, int p) {
+		this(f, r, p, f);
+	}
+
+	/**
+	 * Create a new replacement pair with a set priority and name.
+	 *
+	 * @param f
+	 * 	The string to find.
+	 * @param r
+	 * 	The string to replace.
+	 * @param n
+	 * 	The name of the replacement pair.
+	 * @param p
+	 * 	The priority for the replacement.
+	 */
+	public ReplPair(String f, String r, int p, String n) {
+		find    = f;
+		replace = r;
+
+		name = n;
+
+		priority = p;
+	}
+
+	/**
+	 * Read a list of replacement pairs from an input source.
+	 *
+	 * @param scn
+	 * 	The source to read the replacements from.
+	 * @return
+	 * 	The list of replacements.
+	 */
+	public static List<ReplPair> readList(Scanner scn) {
+		List<ReplPair> lst = new ArrayList<>();
+
+		return readList(lst, scn);
+	}
+
+	/**
+	 * Read a list of replacement pairs from an input source, adding them to
+	 * an existing list.
+	 *
+	 * @param detals
+	 * 	The list to add the replacements to.
+	 * @param scn
+	 * 	The source to read the replacements from.
+	 * @return
+	 * 	The list of replacements.
+	 */
+	public static List<ReplPair> readList(List<ReplPair> detals, Scanner scn) {
+		List<ReplError> errList = new ArrayList<>();
+
+		List<ReplPair> rplPar = readList(detals, scn, errList);
+
+		if (errList.size() != 0) {
+			throw new ReplParseException("", errList);
+		}
+
+		return rplPar;
+	}
+
+	/**
+	 * Read a list of replacement pairs from an input source, adding them to
+	 * an existing list.
+	 *
+	 * @param detals
+	 * 	The list to add the replacements to.
+	 * @param scn
+	 * 	The source to read the replacements from.
+	 * @param errs
+	 * 	The list to stick errors in.
+	 * @return
+	 * 	The list of replacements.
+	 */
+	public static List<ReplPair> readList(List<ReplPair> detals, Scanner scn, List<ReplError> errs) {
+		return readList(detals, scn, errs, new ReplOpts());
+	}
+
+	/**
+	 * Read a list of replacement pairs from an input source, adding them to
+	 * an existing list.
+	 *
+	 * @param detals
+	 * 	The list to add the replacements to.
+	 * @param scn
+	 * 	The source to read the replacements from.
+	 * @param errs
+	 * 	The list to stick errors in.
+	 * @param ropts
+	 * 	The options to use when reading the pairs.
+	 * @return
+	 * 	The list of replacements.
+	 */
+	public static List<ReplPair> readList(List<ReplPair> detals, Scanner scn,
+			List<ReplError> errs, ReplOpts ropts) {
+		IntHolder lno = new IntHolder();
+		IntHolder pno = new IntHolder();
+
+		List<List<ReplPair>> stages = new ArrayList<>();
+		stages.add(new ArrayList<ReplPair>());
+
+		// For every line in the source...
+		while (scn.hasNextLine()) {
+			String name = scn.nextLine().trim();
+			lno.incr();
+
+			// If its commented or blank, skip it
+			if (name.equals(""))      continue;
+			if (name.startsWith("#")) continue;
+
+			// Global control. Process it.
+			if (name.startsWith("|//")) {
+				readGlobal(name, scn, errs, ropts, lno, pno);
+
+				continue;
+			}
+
+			ReplPair rp = new ReplPair();
+
+			rp.priority = ropts.defPrior;
+			rp.stat     = ropts.defStatus;
+			rp.lno      = lno.get();
+			rp.stage    = ropts.defStage;
+
+			boolean isMulti = ropts.defMulti;
+
+			{
+				String tmpName = readName(name, scn, errs, rp, ropts, lno, pno);
+				if (tmpName == null) continue;
+				name = tmpName;
+			}
+
+			rp.find = name;
+			if (rp.name == null) rp.name = name;
+
+			// We started to process the pair, mark it as being
+			// started
+			pno.incr();
+			String body = null;
+
+			// Read in the next uncommented line
+			do {
+				if (!scn.hasNextLine()) break; 
+
+				body = scn.nextLine().trim();
+				lno.incr();
+			} while (body.startsWith("#"));
+
+			if (body == null) {
+				String msg = 
+					"Ran out of input looking for replacement body for raw name '" + name + "'";
+
+				errs.add(new ReplError(lno, pno, msg, null));
+				break;
+			}
+
+			isMulti = ropts.defMulti;
+
+			// Body has attached controls, process them.
+			if (body.startsWith("//")) {
+				body = body.substring(2);
+
+				String[] bodyBits = StringUtils.escapeSplit("|", "//", body);
+				if (bodyBits.length < 2) {
+					String msg = "Did not find control terminator (//) in body where it should be";
+
+					errs.add(new ReplError(lno, pno, msg, body));
+					continue;
+				}
+
+				String contBody = bodyBits[0];
+				String actBody  = bodyBits[1];
+
+				// Split out each control
+				String[] bits = StringUtils.escapeSplit("|", ";", actBody);
+
+				for (String bit : bits) {
+					String bitHead = bit.toUpperCase();
+					String bitBody = bit;
+
+					String[] bots = StringUtils.escapeSplit("|", "/", bit);
+					if (bots.length > 1) {
+						bitHead = bots[0].toUpperCase();
+						bitBody = bots[1];
+					}
+
+					switch (bitHead) {
+					case "MULTITRUE":
+					case "MULTIT":
+					case "MT":
+						isMulti = true;
+						break;
+					case "MULTIFALSE":
+					case "MULTIF":
+					case "MF":
+						isMulti = false;
+						break;
+					case "MULTI":
+					case "M":
+						isMulti = Boolean.parseBoolean(bitBody);
+						break;
+					default: 
+						errs.add(new ReplError(lno, pno, String.format("Invalid control name '%s'", bitHead), body));
+						break;
+					}
+				}
+
+				body = actBody;
+			}
+
+			if (isMulti) {
+				String tmp = readMultiLine(body, scn, ropts, errs, "body", lno);
+				if (tmp == null) continue;
+				body = tmp;
+			}
+
+			rp.replace = body;
+
+			List<ReplPair> stageList = null;
+			if (rp.stage == 0 || stages.size() < (rp.stage - 1)) {
+				stageList = stages.get(rp.stage);
+
+				if (stageList == null) {
+					stageList = new ArrayList<>();
+
+					stages.add(rp.stage, stageList);
+				}
+			} else {
+				for (int i = stages.size(); i <= rp.stage; i++) {
+					stages.add(new ArrayList<>());
+				}
+
+				stageList = stages.get(rp.stage);
+			}
+
+			if (ropts.isTrace) {
+				ropts.errStream.printf("\t[DEBUG] Stage %d: Added %s\n\t\tContents: %s\n",
+						rp.stage, rp, stageList);
+			}
+
+			stageList.add(rp);
+		}
+
+		// Special-case one-stage processing.
+		if (stages.size() == 1) {
+			if (ropts.isTrace) ropts.errStream.printf("\t[DEBUG] Executing single-stage bypass\n");
+
+			for (ReplPair rp : stages.iterator().next()) {
+				if (rp.stat == StageStatus.INTERNAL) {
+					if (ropts.isTrace) ropts.errStream.printf("\t[DEBUG] Excluding internal RP %s\n", rp);
+
+					continue;
+				}
+
+				detals.add(rp);
+			}
+
+			detals.sort(null);
+
+			return detals;
+		}
+
+		// Handle stages
+		List<ReplPair> tmpList = new ArrayList<>();
+		tmpList.addAll(detals);
+
+		if (ropts.isTrace) ropts.errStream.printf("\t[DEBUG] Stages: %s\n", stages);
+
+		int procStg = 0;
+		for (List<ReplPair> stageList : stages) {
+			procStg += 1;
+			List<ReplPair> curStage = new ArrayList<>();
+
+			if (ropts.isTrace) ropts.errStream.printf("\t[DEBUG] Staging stage %d of %d: %s\n",
+					procStg, stageList.size(), stageList);
+
+			for (ReplPair rp : stageList) {
+				// Process through every pair in the previous
+				// stages
+				for (ReplPair curPar : tmpList) {
+					String tmp = rp.replace.replaceAll(curPar.find, curPar.replace);
+
+					if (ropts.isTrace && !rp.replace.equals(tmp)) {
+						ropts.errStream.printf("\t[DEBUG] Staged '%s' -> '%s'\t%s\n",
+							rp.replace, tmp, curPar);
+					}
+
+					rp.replace = tmp;
+				}
+
+				// If we're external; add straight to the output
+				if (rp.stat == StageStatus.EXTERNAL) {
+					if (ropts.isTrace) {
+						ropts.errStream.printf("\t[DEBUG] Skipped external for staging: %s\n",
+								rp);
+					}
+
+					detals.add(rp);
+				} else {
+					if (ropts.isTrace) {
+						ropts.errStream.printf("\t[DEBUG] Added to stage %d: %s\n\t\tContents: %s\n",
+								procStg, rp, curStage);
+					}
+
+					curStage.add(rp);
+				}
+			}
+			
+			tmpList.addAll(curStage);
+			tmpList.sort(null);
+		}
+
+		// Copy over to output, excluding internals
+		for (ReplPair rp : tmpList) {
+			if (rp.stat == StageStatus.INTERNAL) {
+				if (ropts.isTrace) ropts.errStream.printf("\t[DEBUG] Excluded internal: %s\n", rp);
+
+				continue;
+			}
+
+			detals.add(rp);
+		}
+
+		detals.sort(null);
+
+		if (ropts.isTrace) {
+			ropts.errStream.printf("\t[DEBUG] Final output: %s\n", detals);
+		}
+
+		return detals;
+	}
+
+	private static String readMultiLine(String lead, Scanner src, ReplOpts ropts,
+			List<ReplError> errs, String typ, IntHolder lno) {
+		String tmp = lead;
+
+		if (ropts.isTrace && tmp.endsWith("\\")) 
+			ropts.errStream.printf("\t[TRACE] Starting multi-line parse for %s '%s'\n", typ, tmp);
+
+		boolean didMulti = tmp.endsWith("\\");
+		while (tmp.endsWith("\\")) {
+			boolean incNL = tmp.endsWith("|\\");
+
+			if (!src.hasNextLine()) break;
+
+			String nxt = src.nextLine().trim();
+			lno.incr();
+
+			if (nxt.startsWith("#")) continue;
+
+			String nlStr = incNL ? "\n" : "";
+
+			if (tmp.endsWith("\\")) {
+				if (incNL) {
+					tmp = tmp.substring(0, tmp.length() - 2);
+				} else {
+					tmp = tmp.substring(0, tmp.length() - 1);
+				}
+			}
+
+			tmp = String.format("%s%s%s", tmp, nlStr, nxt);
+		}
+
+		if (ropts.isTrace && didMulti)
+			ropts.errStream.printf("\t[TRACE] Finished multi-line parse for %s:\n%s\n.\n",
+					typ, tmp);
+
+		return tmp;
+	}
+
+	@Override
+	public String apply(String inp) {
+		return inp.replaceAll(find, replace);
+	}
+
+	@Override
+	public String toString() {
+		String nameStr = "";
+
+		if (!find.equals(name)) nameStr = String.format("(%s)", name);
+
+		return String.format("%ss/%s/%s/p(%d)", nameStr, find, replace, priority);
+	}
+
+	@Override
+	public int compareTo(ReplPair rp) {
+		if (this.priority == rp.priority) return this.lno - rp.lno;
+
+		return rp.priority - this.priority;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (o == null) return false;
+
+		if (!getClass().equals(o.getClass())) return false;
+
+		ReplPair ro = (ReplPair)o;
+
+		if (!find.equals(ro.find)) return false;
+		// lno is not a field we consider for equality
+		if (!name.equals(ro.name)) return false;
+		if (priority != ro.priority) return false;
+		if (!replace.equals(ro.name)) return false;
+		// stat is not a field we consider for equality
+
+		return true;
+	}
+
+	private static String readName(String nam, Scanner scn, List<ReplError> errs,
+			ReplPair rp, ReplOpts ropts, IntHolder lno, IntHolder pno) {
+		String name = nam;
+
+		boolean isMulti = ropts.defMulti;
+
+		// Name has attached controls, process them.
+		if (name.startsWith("//")) {
+			name = name.substring(2);
+
+			String[] nameBits = StringUtils.escapeSplit("|", "//", name);
+
+			if (nameBits.length < 2) {
+				String msg = "Did not find control terminator (//) in name where it should be";
+
+				errs.add(new ReplError(lno, pno, msg, name));
+				return null;
+			}
+
+			String contName = nameBits[0];
+			String actName  = nameBits[1];
+
+			// Split out each control
+			String[] bits = StringUtils.escapeSplit("|", ";", contName);
+
+			for (String bit : bits) {
+				String bitHead = bit.toUpperCase();
+				String bitBody = bit;
+
+				String[] bots = StringUtils.escapeSplit("|", "/", bit);
+
+				if (bots.length > 1) {
+					bitHead = bots[0].toUpperCase();
+					bitBody = bots[1];
+				}
+
+				switch (bitHead) {
+				case "NAME":
+				case "N":
+					rp.name = bitBody;
+					break;
+				case "PRIORITY":
+				case "PRIOR":
+				case "P":
+					try {
+						rp.priority = Integer.parseInt(bitBody);
+					} catch (NumberFormatException nfex) {
+						String errMsg = String.format("'%s' is not a valid priority (must be an integer)", bitBody);
+						errs.add(new ReplError(lno, pno, errMsg, name));
+					}
+					break;
+				case "STAGE":
+				case "S":
+					try {
+						int tmpStage = Integer.parseInt(bitBody);
+						if (tmpStage < 0) {
+							String errMsg = String.format("'%s' is not a valid stage (must be a positive integer)", bitBody);
+							errs.add(new ReplError(lno, pno, errMsg, name));
+
+							break;
+						}
+						rp.stage = tmpStage;
+					} catch (NumberFormatException nfex) {
+						String errMsg = String.format("'%s' is not a valid stage (must be a positive integer)", bitBody);
+						errs.add(new ReplError(lno, pno, errMsg, name));
+					}
+					break;
+				case "MULTITRUE":
+				case "MULTIT":
+				case "MT":
+					isMulti = true;
+					break;
+				case "MULTIFALSE":
+				case "MULTIF":
+				case "MF":
+					isMulti = false;
+					break;
+				case "MULTI":
+				case "M":
+					isMulti = Boolean.parseBoolean(bitBody);
+					break;
+				case "INTERNAL":
+				case "INT":
+				case "I":
+					rp.stat = StageStatus.INTERNAL;
+					break;
+				case "EXTERNAL":
+				case "EXT":
+				case "E":
+					rp.stat = StageStatus.EXTERNAL;
+					break;
+				case "BOTH":
+				case "B":
+					rp.stat = StageStatus.BOTH;
+					break;
+				default: 
+					{
+						ReplError erd = new ReplError(lno, pno,
+								String.format("Unknown control name '%s' for name '%s'",
+									bitHead, name), name);
+
+						errs.add(erd);
+					}
+					break;
+				}
+
+				name = actName;
+			}
+
+			// Multi-line name with a trailer
+			if (isMulti) {
+				String tmp = readMultiLine(name, scn, ropts, errs, "name", lno);
+				if (tmp == null) return null;
+				name = tmp;
+			}
+		}
+
+		return name;
+	}
+
+	private static void readGlobal(String nam, Scanner scn, List<ReplError> errs,
+			ReplOpts ropts, IntHolder lno, IntHolder pno) {
+		String name = nam.substring(3);
+
+		// Split out each control
+		String[] bits = StringUtils.escapeSplit("|", ";", name);
+		if (ropts.isTrace) {
+			ropts.errStream.printf("\t[TRACE] Split control bits are: \n");
+			for (String bit : bits) {
+				ropts.errStream.printf("%s, ", bit);
+			}
+			ropts.errStream.println();
+		}
+		for (String bit : bits) {
+			String bitHead = bit.toUpperCase();
+			String bitBody = bit;
+
+			String[] bots = StringUtils.escapeSplit("|", "/", bit);
+			if (bots.length > 1) {
+				bitHead = bots[0];
+				bitBody = bots[1];
+			}
+
+			switch (bitHead) {
+			case "PRIORITY":
+			case "PRIOR":
+			case "P":
+				try {
+					int tmp = Integer.parseInt(bitBody);
+					ropts.defPrior = tmp;
+				} catch (NumberFormatException nfex) {
+					String errMsg = String.format("'%s' is not a valid priority (must be an integer)",
+							bitBody);
+
+					errs.add(new ReplError(lno, pno, errMsg, name));
+				}
+				break;
+			case "STAGE":
+			case "S":
+				try {
+					int tmpStage = Integer.parseInt(bitBody);
+
+					if (tmpStage < 0) {
+						String errMsg = String.format("'%s' is not a valid stage (must be a positive integer)",
+								bitBody);
+
+						errs.add(new ReplError(lno, pno, errMsg, name));
+						break;
+					}
+					ropts.defStage = tmpStage;
+				} catch (NumberFormatException nfex) {
+					String errMsg = String.format("'%s' is not a valid stage (must be a positive integer)",
+							bitBody);
+
+					errs.add(new ReplError(lno, pno, errMsg, name));
+				}
+				break;
+			case "MULTITRUE":
+			case "MULTIT":
+			case "MT":
+				ropts.defMulti = true;
+				break;
+			case "MULTIFALSE":
+			case "MULTIF":
+			case "MF":
+				ropts.defMulti = false;
+				break;
+			case "MULTI":
+			case "M":
+				ropts.defMulti = Boolean.parseBoolean(bitBody);
+				break;
+			case "INTERNAL":
+			case "INT":
+			case "I":
+				ropts.defStatus = StageStatus.INTERNAL;
+				break;
+			case "EXTERNAL":
+			case "EXT":
+			case "E":
+				ropts.defStatus = StageStatus.EXTERNAL;
+				break;
+			case "BOTH":
+			case "B":
+				ropts.defStatus = StageStatus.BOTH;
+				break;
+			case "DEBUGTRUE":
+			case "DEBUGT":
+			case "DT":
+				ropts.isDebug = true;
+				break;
+			case "DEBUGFALSE":
+			case "DEBUGF":
+			case "DF":
+				ropts.isDebug = false;
+				break;
+			case "DEBUG":
+			case "D":
+				ropts.isDebug = Boolean.parseBoolean(bitBody);
+				break;
+			case "TRACETRUE":
+			case "TRACET":
+			case "TT":
+				ropts.isTrace = true;
+				break;
+			case "TRACEFALSE":
+			case "TRACEF":
+			case "TF":
+				ropts.isTrace = false;
+				break;
+			case "TRACE":
+			case "T":
+				ropts.isTrace = Boolean.parseBoolean(bitBody);
+				break;
+			case "PERFTRUE":
+			case "PERFT":
+			case "PRFT":
+				ropts.isPerf = true;
+				break;
+			case "PERFFALSE":
+			case "PERFF":
+			case "PRFF":
+				ropts.isPerf = false;
+				break;
+			case "PERF":
+			case "PRF":
+				ropts.isPerf = Boolean.parseBoolean(bitBody);
+				break;
+			default: 
+				{
+					String msg = String.format("Invalid global control name '%s'", bitHead);
+					ReplError err = new ReplError(lno, pno, msg, name);
+					errs.add(err);
+				}
+				break;
+			}
+
+			if (ropts.isTrace) 
+				ropts.errStream.printf("\t[TRACE] Processed global control '%s':'%s'\n", 
+						bitHead, bitBody);
+		}
+
+		return;
+	}
+	
+	private static ControlledString getControls(String lne, List<ReplError> errs,
+			ReplOpts ropts, IntHolder lno, IntHolder pno, String type) {
+		if (!lne.startsWith("//")) {
+			return new ControlledString(lne);
+		}
+
+		String tmp = lne.substring(2);
+
+		String[] bits = StringUtils.escapeSplit("|", "//", lne);
+
+		if (bits.length < 2) {
+			String msg = "Did not find control terminator (//) in %s where it should be";
+			msg = String.format(msg, type);
+
+			ReplError re = new ReplError(lno, pno, msg, lne);
+			errs.add(re);
+
+			return null;
+		}
+
+		ControlledString cs = new ControlledString(bits[0]);
+
+		bits = StringUtils.escapeSplit("|", ";", bits[1]);
+
+		cs.controls = new Control[bits.length];
+
+		for (int i = 0; i < bits.length; i++) {
+			String bit = bits[i];
+
+			String[] bots = StringUtils.escapeSplit("|", "/", bit);
+
+			Control cont = new Control(bots[0]);
+
+			if (cont.name.length() > 1) {
+				cont.name = cont.name.toUpperCase();
+			}
+			
+			if (bots.length > 1) {
+				cont.args = new String[bots.length - 1];
+				for (int j = 1; j < bots.length; j++) {
+					cont.args[j - 1] = bots[j];
+				}
+			}
+
+			cs.controls[i] = cont;
+		}
+
+		return cs;
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplParseException.html b/docs/jacoco-ut/bjc.everge/ReplParseException.html new file mode 100644 index 0000000..db90db6 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplParseException.html @@ -0,0 +1 @@ +ReplParseException

ReplParseException

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total59 of 12853%6 of 1250%710112724
toString()280%20%224411
toPrintString()246272%4660%4651801
ReplParseException(String)70%n/a112211
ReplParseException(String, List)7100%n/a010301
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplParseException.java.html b/docs/jacoco-ut/bjc.everge/ReplParseException.java.html new file mode 100644 index 0000000..322ba21 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplParseException.java.html @@ -0,0 +1,59 @@ +ReplParseException.java

ReplParseException.java

package bjc.everge;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ReplParseException extends RuntimeException {
+	public List<ReplError> errs;
+
+	public ReplParseException(String msg) {
+		this(msg, new ArrayList<>());
+	}
+
+	public ReplParseException(String msg, List<ReplError> errs) {
+		super(msg);
+
+		this.errs = errs;
+	}
+
+	@Override
+	public String toString() {
+		String errString;
+		if (errs.size() == 0) errString = "An error";
+		else                  errString = "Errors";
+
+		return String.format("%s occured parsing replacement pairs: %s\n%s",
+				errString, getMessage(), errs);
+	}
+
+	public String toPrintString() {
+		StringBuilder errString = new StringBuilder("[ERROR] ");
+
+		if (errs.size() == 0) {
+			errString.append("No specific errors");
+		} else if (errs.size() == 1) {
+			errString.append("An error");
+		} else {
+			errString.append(errs.size());
+			errString.append(" errors");
+		}
+
+		errString.append(" occured parsing replacement pairs:");
+		if (!getMessage().equals("")) {
+			errString.append(" ");
+			errString.append(getMessage());
+		}
+
+		if (errs.size() > 0) {
+			errString.append("\n\t");
+
+			for (ReplError err : errs) {
+				errString.append(err.toPrintString("\t"));
+				errString.append("\n\t");
+			}
+		}
+
+		return errString.toString().trim();
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplSet.html b/docs/jacoco-ut/bjc.everge/ReplSet.html new file mode 100644 index 0000000..1edd220 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplSet.html @@ -0,0 +1 @@ +ReplSet

ReplSet

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total105 of 1050%6 of 60%99242466
addPairs(ReplPair[])260%20%224411
fromFile(String)240%n/a114411
addPairs(List)210%20%225511
apply(String)200%20%225511
ReplSet()80%n/a113311
ReplSet(List)60%n/a113311
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/ReplSet.java.html b/docs/jacoco-ut/bjc.everge/ReplSet.java.html new file mode 100644 index 0000000..f2f59a6 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/ReplSet.java.html @@ -0,0 +1,97 @@ +ReplSet.java

ReplSet.java

package bjc.everge;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * A set of ReplPairs, kept together for easy use
+ *
+ * @author Ben Culkin
+ */
+public class ReplSet {
+	// The list of pairs
+	private List<ReplPair> parList;
+
+	/**
+	 * Create a new blank set of pairs.
+	 */
+	public ReplSet() {
+		parList = new ArrayList<>();
+	}
+
+	/**
+	 * Create a new set of pairs using an existing list of pairs.
+	 *
+	 * Changes to the list of pairs will carry across to the ReplSet, so be careful about that.
+	 *
+	 * @param lst
+	 * 		The list of pairs to use.
+	 */
+	public ReplSet(List<ReplPair> lst) {
+		parList = lst;
+	}
+
+	public static ReplSet fromFile(String fName) throws IOException {
+		ReplSet rs = new ReplSet();
+
+		try (FileInputStream fis = new FileInputStream(fName); Scanner scn = new Scanner(fis)) {
+			rs.parList = ReplPair.readList(scn);
+		}
+
+		return rs;
+	}
+
+	/**
+	 * Adds more pairs to the ReplSet.
+	 *
+	 * @param pars
+	 * 	The pairs to add to the ReplSet.
+	 */
+	public void addPairs(List<ReplPair> pars) {
+		for (ReplPair par : pars) {
+			parList.add(par);
+		}
+
+		// Resort the pairs into priority order
+		parList.sort(null);
+	}
+
+	/**
+	 * Adds more pairs to the ReplSet.
+	 *
+	 * @param pars
+	 * 	The pairs to add to the ReplSet.
+	 */
+	public void addPairs(ReplPair... pars) {
+		for (ReplPair par : pars) {
+			parList.add(par);
+		}
+
+		// Resort the pairs into priority order
+		parList.sort(null);
+	}
+
+	/**
+	 * Apply the ReplSet to a string.
+	 *
+	 * @param val
+	 * 		The string to apply the ReplSet to.
+	 *
+	 * @return The result of applying the ReplSet.
+	 */
+	public String apply(String val) {
+		String ret = val;
+
+		for (ReplPair par : parList) {
+			ret = par.apply(ret);
+		}
+
+		return ret;
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/StageStatus.html b/docs/jacoco-ut/bjc.everge/StageStatus.html new file mode 100644 index 0000000..743ca89 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/StageStatus.html @@ -0,0 +1 @@ +StageStatus

StageStatus

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total0 of 34100%0 of 0n/a010401
static {...}34100%n/a010401
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/StageStatus.java.html b/docs/jacoco-ut/bjc.everge/StageStatus.java.html new file mode 100644 index 0000000..343fd08 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/StageStatus.java.html @@ -0,0 +1,22 @@ +StageStatus.java

StageStatus.java

package bjc.everge;
+
+/**
+ * Possible statuses of pairs with respect to exporting.
+ * @author Ben Culkin
+ */
+public enum StageStatus {
+	/**
+	 * Only use for staging pairs; don't export.
+	 */
+	INTERNAL,
+	/**
+	 * Don't use for staging pairs; do export.
+	 */
+	EXTERNAL,
+	/**
+	 * Use for staging pairs; do export.
+	 */
+	BOTH;
+}
+
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/StringUtils.html b/docs/jacoco-ut/bjc.everge/StringUtils.html new file mode 100644 index 0000000..e21d36f --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/StringUtils.html @@ -0,0 +1 @@ +StringUtils

StringUtils

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethods
Total190 of 46058%17 of 5468%1630248013
escapeSplit(String, String, String)18726758%173768%1528237801
StringUtils()0%n/a111111
static {...}100%n/a010101
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/StringUtils.java.html b/docs/jacoco-ut/bjc.everge/StringUtils.java.html new file mode 100644 index 0000000..f1f94d2 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/StringUtils.java.html @@ -0,0 +1,194 @@ +StringUtils.java

StringUtils.java

package bjc.everge;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+
+import java.util.regex.Pattern;
+
+/**
+ * Utility methods for strings.
+ *
+ * @author Ben Culkin.
+ */
+public class StringUtils {
+	public static boolean isDebug = false;
+
+	/**
+	 * Split a string on every occurance of a string not preceeded by an escape.
+	 *
+	 * @param escape
+	 * 		The escape that stops splitting.
+	 * @param splat
+	 * 		The string to split on. If this starts with the escape sequence, things will work
+	 * 		poorly.
+	 * @param inp
+	 * 		The string to split.
+	 * @return The string split as specified above.
+	 */
+	public static String[] escapeSplit(String escape, String splat, String inp) {
+
+		/*
+		 * Special case some stuffs.
+		 */
+		if (inp == null || inp.equals("")) {
+			// No input
+			return new String[] {inp};
+		}
+
+		if (!inp.contains(splat)) {
+			// Input does not contain any delimiters
+			return new String[] {inp};
+		}
+
+		if (escape == null || escape.equals("")) {
+			// No escape, so we can just split normally
+			return inp.split(Pattern.quote(splat));
+		}
+
+		List<String> ret = new ArrayList<>();
+
+		String wrk = inp;
+		int sidx = wrk.indexOf(splat);
+		int eidx = wrk.indexOf(escape);
+
+		boolean hadEscape = false;
+
+		while (sidx != -1 || eidx != -1) {
+			if (eidx > 0 && eidx < sidx) {
+				if (isDebug) System.err.printf("[TRACE] Considering escape\n");
+
+				/*
+				 * We potentially have an escaped sequence:
+				 * 	- either an escaped split
+				 * 	- or an escaped escape
+				 */
+				// Check for an escaped split
+				if (wrk.regionMatches(eidx + escape.length(), splat, 0, splat.length())) {
+					// Skip over it
+					int ofst = eidx + splat.length();
+
+					// Slice out the escape
+					{
+						String s1 = wrk.substring(0, eidx);
+						String s2 = wrk.substring(eidx + escape.length());
+
+						String s3 = wrk.substring(eidx, eidx + escape.length());
+
+						if (isDebug) {
+							System.err.printf("[TRACE] Skip esc. split (%s)/(%s); (%s)\n",
+									s1, s2, s3);
+						}
+
+						wrk = s1 + s2;
+					}
+
+					sidx = wrk.indexOf(splat,  ofst);
+					eidx = wrk.indexOf(escape, ofst);
+
+					if (isDebug) {
+						System.err.printf("[TRACE] After esc. split (%s) %d/%d\n",
+								wrk, sidx, eidx);
+					}
+
+					hadEscape = false;
+					continue;
+				}
+
+				// Check for an escaped escape
+				if (wrk.regionMatches(eidx + escape.length(), escape, 0, escape.length())) {
+					// Skip over it
+					int ofst = eidx + escape.length();
+
+					// Slice out the escape
+					{
+						String s1 = wrk.substring(0, eidx);
+						String s2 = wrk.substring(eidx + escape.length());
+
+						String s3 = wrk.substring(eidx, eidx + escape.length());
+						if (isDebug) {
+							System.err.printf("[TRACE] Skip esc. escape (%s)/(%s); (%s)\n",
+								s1, s2, s3);
+						}
+
+						wrk = s1 + s2;
+					}
+
+					sidx = wrk.indexOf(splat,  ofst);
+					eidx = wrk.indexOf(escape, ofst);
+
+					if (isDebug) {
+						System.err.printf("[TRACE] After esc. escape (%s)/(%s) %d/%d\n",
+								wrk, wrk.substring(ofst), sidx, eidx);
+					}
+
+					hadEscape = true;
+					continue;
+				}
+			}
+
+			boolean hasEscape = false;
+
+			{
+				boolean tmp = wrk.regionMatches(sidx - escape.length(), escape, 0, escape.length());
+
+				hasEscape = hadEscape ? false : tmp;
+			}
+
+			while (sidx != -1 && hasEscape) {
+				int oidx = wrk.indexOf(splat, sidx + escape.length());
+
+				if (isDebug) {
+					String s1 = wrk.substring(0, sidx);
+					String s2 = wrk.substring(sidx, sidx + escape.length());
+					String s3 = wrk.substring(sidx + escape.length());
+				}
+
+				if (oidx == -1) break;
+
+				{
+					String s1 = wrk.substring(0, oidx);
+					String s2 = wrk.substring(oidx + escape.length());
+
+					wrk = s1 + s2;
+				}
+
+				sidx = oidx;
+
+				hasEscape = wrk.regionMatches(sidx - escape.length(), escape, 0, escape.length());
+			}
+
+			if (sidx == -1) {
+				break;
+			}
+
+			String tmp = wrk.substring(0, sidx);
+
+			if (isDebug) {
+				System.err.printf("[TRACE] Adding (%s) to returned splits; (%s)\n",
+					tmp, wrk.substring(sidx));
+			}
+
+			ret.add(tmp);
+			if (!tmp.equals("") && wrk.endsWith(tmp)) {
+				wrk = "";
+			} else {
+				if (wrk.indexOf(splat, sidx) != -1) {
+					wrk = wrk.substring(sidx + splat.length());
+				} else {
+					wrk = wrk.substring(sidx);
+				}
+			}
+
+			sidx = wrk.indexOf(splat);
+			eidx = wrk.indexOf(escape);
+
+			hadEscape = false;
+		}
+
+		if (!wrk.equals("")) ret.add(wrk);
+
+		return ret.toArray(new String[0]);
+	}
+}
+
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/index.html b/docs/jacoco-ut/bjc.everge/index.html new file mode 100644 index 0000000..c22add6 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/index.html @@ -0,0 +1 @@ +bjc.everge

bjc.everge

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethodsMissedClasses
Total2,013 of 3,67345%209 of 38145%1792703887692661312
ReplPair80082250%879953%7312313833621701
Everge53431937%542934%41551241992801
StringUtils19027058%173768%163024801301
ControlledString1590%140%121235355511
ReplSet1050%60%9924246611
ReplError726045%712%697182501
ReplOpts663031%180%101111211201
ReplParseException596953%6650%71011272401
ControlledString.Control180%n/a33993311
IntHolder2268%n/a265122601
Everge.InputStatus34100%n/a01040101
StageStatus34100%n/a01040101
\ No newline at end of file diff --git a/docs/jacoco-ut/bjc.everge/index.source.html b/docs/jacoco-ut/bjc.everge/index.source.html new file mode 100644 index 0000000..0b57023 --- /dev/null +++ b/docs/jacoco-ut/bjc.everge/index.source.html @@ -0,0 +1 @@ +bjc.everge

bjc.everge

ElementMissed InstructionsCov.Missed BranchesCov.MissedCxtyMissedLinesMissedMethodsMissedClasses
Total2,013 of 3,67345%209 of 38145%1792703887692661312
ReplPair.java80082250%879953%7312313833621701
Everge.java53435339%542934%41561242032902
StringUtils.java19027058%173768%163024801301
ControlledString.java1770%140%151544448822
ReplSet.java1050%60%9924246611
ReplError.java726045%712%697182501
ReplOpts.java663031%180%101111211201
ReplParseException.java596953%6650%71011272401
IntHolder.java2268%n/a265122601
StageStatus.java34100%n/a01040101
\ No newline at end of file -- cgit v1.2.3