private String macroSub(String image, int pos, ArrayList<String> initialList) {
		int replaceCount = 0;

		StringBuffer buf = new StringBuffer(image);
		int lastReplPos = pos;

		boolean initialListSupplied = initialList != null;  // initial list passed in
		ArrayList<String> sublist = new ArrayList<String>();
		if (initialList != null) {
			sublist.addAll(initialList);
		}

		// don't replace an infinite number of times.  Fail safe for possible ininite loop
		while (pos < buf.length() && replaceCount < ARBITRARY_MAX_REPLACEMENTS) {
			// clear list of used macros when move past replacement area
			if (pos == lastReplPos) {
				sublist = new ArrayList<String>(); // ok to clear list of used macro names
				if (initialList != null) {
					sublist.addAll(initialList); // add back in initialList of nonreplacement names
				}
			}
			String defName = getDefineAt(buf, pos);
			if (shouldReplace(buf, defName, pos)) {
				// stop recursion on the same replacement string
				int replPos = replace(buf, defName, pos, sublist, initialListSupplied);

				if (replPos == -1) {
					// if no replacement string, move on
					pos++;
				}
				else {
					// replaced text, update the last place a replacement was made
					lastReplPos = replPos;
					replaceCount++;
				}
			}
			else {
				pos++;
			}
		}
		if (replaceCount >= ARBITRARY_MAX_REPLACEMENTS) {
			System.err.println(" replace " + image + " hit limit");
		}
		return buf.toString();
	}
return a string with all the macros substitute starting at pos in the input string.
@param image string to expand
@param pos position within string to start expanding
@return string with all substitutions applied
Ghidra/Features/Base/src/main/java/ghidra/app/util/cparser/CPP/DefineTable.java