public static Object parseExtension(String optionName, String extension, CompilerSpec cspec,
			boolean provideDummy) throws SAXException, XmlParseException, SleighException {
		ErrorHandler errHandler = getErrorHandler("extensions");
		XmlPullParser parser =
			XmlPullParserFactory.create(extension, optionName, errHandler, false);
		String elName = parser.peek().getName();
		if (elName.endsWith("prototype")) {
			PrototypeModel model;
			if (parser.peek().getName().equals("resolveprototype")) {
				PrototypeModelMerged mergemodel = new PrototypeModelMerged();
				ArrayList<PrototypeModel> curModels =
					new ArrayList<>(cspec.getCallingConventions().length);
				for (PrototypeModel curModel : cspec.getCallingConventions()) {
					curModels.add(curModel);
				}
				try {
					mergemodel.restoreXml(parser, curModels);
					model = mergemodel;
				}
				catch (XmlParseException ex) {
					if (!provideDummy) {
						throw ex;
					}
					// XML failed to parse, associate default model as a placeholder
					model = new PrototypeModelError(getFormalName(optionName),
						cspec.getDefaultCallingConvention());
				}
			}
			else {
				model = new PrototypeModel();
				try {
					model.restoreXml(parser, cspec);
				}
				catch (XmlParseException ex) {
					if (!provideDummy) {
						throw ex;
					}
					// XML failed to parse, associate default model as a placeholder
					model = new PrototypeModelError(getFormalName(optionName),
						cspec.getDefaultCallingConvention());
				}
			}
			return model;
		}
		else if (elName.equals("callfixup")) {
			String nm = parser.peek().getAttribute("name");
			PcodeInjectLibrary injectLibrary = cspec.getPcodeInjectLibrary();
			InjectPayload payload =
				injectLibrary.allocateInject(optionName, nm, InjectPayload.CALLFIXUP_TYPE);
			if (!(payload instanceof InjectPayloadSleigh)) {
				throw new XmlParseException("Cannot use attached name: " + nm);
			}
			try {
				payload.restoreXml(parser, (SleighLanguage) cspec.getLanguage());
				injectLibrary.parseInject(payload);		// Try to parse the pcode body
			}
			catch (XmlParseException ex) {
				if (!provideDummy) {
					throw ex;
				}
				// The XML parse itself failed, provide a generic placeholder
				payload = new InjectPayloadCallfixupError(cspec.getLanguage().getAddressFactory(),
					getFormalName(optionName));
			}
			catch (SleighException ex) {
				if (!provideDummy) {
					throw ex;
				}
				// The pcode body failed to parse, payload metadata, but provide dummy p-code
				payload = new InjectPayloadCallfixupError(cspec.getLanguage().getAddressFactory(),
					(InjectPayloadCallfixup) payload);
			}
			return payload;
		}
		else if (elName.equals("callotherfixup")) {
			String nm = parser.peek().getAttribute("name");
			PcodeInjectLibrary injectLibrary = cspec.getPcodeInjectLibrary();
			InjectPayload payload =
				injectLibrary.allocateInject(optionName, nm, InjectPayload.CALLOTHERFIXUP_TYPE);
			if (!(payload instanceof InjectPayloadSleigh)) {
				throw new XmlParseException("Cannot use attached name: " + nm);
			}
			try {
				payload.restoreXml(parser, (SleighLanguage) cspec.getLanguage());
				injectLibrary.parseInject(payload);
			}
			catch (XmlParseException ex) {
				if (!provideDummy) {
					throw ex;
				}
				// The XML parse itself failed, provide a generic placeholder
				payload = new InjectPayloadCallotherError(cspec.getLanguage().getAddressFactory(),
					getFormalName(optionName));
			}
			catch (SleighException ex) {
				// The p-code parse failed, keep the metadata, but provide dummy p-code
				payload = new InjectPayloadCallotherError(cspec.getLanguage().getAddressFactory(),
					(InjectPayloadCallother) payload);
			}
			return payload;
		}
		throw new XmlParseException("Unknown compiler spec extension: " + elName);
	}
Parse an XML string and build the corresponding compiler spec extension object.
Currently this can either be a
<ul>
  <li>PrototypeModel</li>
  <li>InjectPayload</li>
</ul>

For InjectPayloadCallfixup or InjectPayloadCallother, the p-code {@code <body>} tag
is also parsed, and the caller can control whether any parse errors
cause an exception or whether a dummy payload is provided instead.
@param optionName is the option name the extension is attached to
@param extension is the XML document as a String
@param cspec is the compiler spec the new extension is for
@param provideDummy if true, provide a dummy payload if necessary
@return the extension object
@throws SAXException is there are XML format errors
@throws XmlParseException if the XML document is badly formed
@throws SleighException if internal p-code does not parse
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/SpecExtension.java