void read(XmlPullParser parser, boolean overwriteConflicts, boolean ignoreStackFrames,
			TaskMonitor monitor) throws AddressFormatException, CancelledException {
		final XmlElement element = parser.start("FUNCTIONS");
		AddressSet functions = new AddressSet();

		DataTypeManager dataManager = listing.getDataTypeManager();
		BuiltInDataTypeManager builtInMgr = BuiltInDataTypeManager.getDataTypeManager();

		try {
			dtParser = new DtParser(dataManager);

			while (parser.peek().isStart()) {
				monitor.checkCancelled();

				final XmlElement functionElement = parser.start("FUNCTION");

				String entryPointStr = functionElement.getAttribute("ENTRY_POINT");
				if (entryPointStr == null) {
					throw new RuntimeException("No entry point provided.");
				}
				Address entryPoint = XmlProgramUtilities.parseAddress(factory, entryPointStr);
				if (entryPoint == null) {
					throw new AddressFormatException(
						"Incompatible Function Entry Point Address: " + entryPointStr);
				}

				try {

					SymbolPath namespacePath = null;
					String name = functionElement.getAttribute("NAME");
					if (name != null) {
						SymbolPath symbolPath = new SymbolPath(name);
						name = symbolPath.getName();
						namespacePath = symbolPath.getParent();
					}

					AddressSet body = new AddressSet(entryPoint, entryPoint);

					if (functionElement.hasAttribute("LIBRARY_FUNCTION")) {
						boolean isLibFunc = XmlUtilities
								.parseBoolean(functionElement.getAttribute("LIBRARY_FUNCTION"));
						if (isLibFunc) {
							BookmarkManager bm = program.getBookmarkManager();
							BookmarkType bt = bm.getBookmarkType("IMPORTED");
							if (bt == null) {
								Icon icon = new GIcon("icon.base.util.xml.functions.bookmark");
								bt = bm.defineType("IMPORTED", icon, Palette.DARK_GRAY, 0);
							}
							bm.setBookmark(entryPoint, "IMPORTED", LIB_BOOKMARK_CATEGORY,
								"Library function");
						}
					}

					DataType returnType = readReturnType(parser, name);
					readAddressRange(parser, body);
					CreateFunctionCmd cmd =
						new CreateFunctionCmd(null, entryPoint, body, SourceType.USER_DEFINED);
					if (!cmd.applyTo(program)) {
						Msg.error(this, "Failed to create function at " + entryPoint + ": " +
							cmd.getStatusMsg());
						parser.discardSubTree(functionElement);
						continue;
					}

					Function func = cmd.getFunction();
					if (name != null && !SymbolUtilities.isReservedDynamicLabelName(name,
						program.getAddressFactory())) {
						try {
							Symbol symbol = func.getSymbol();
							Namespace namespace = NamespaceUtils.getFunctionNamespaceAt(program,
								namespacePath, entryPoint);
							if (namespace == null) {
								namespace = program.getGlobalNamespace();
							}
							symbol.setNameAndNamespace(name, namespace, SourceType.USER_DEFINED);
						}
						catch (DuplicateNameException e) {//name may already be set if symbols were loaded...
						}
					}

					String regularComment = getElementText(parser, "REGULAR_CMT");
					func.setComment(regularComment);
					String repeatableComment = getElementText(parser, "REPEATABLE_CMT");
					func.setRepeatableComment(repeatableComment);
					String typeInfoComment = getElementText(parser, "TYPEINFO_CMT");
					List<Variable> stackParams = new ArrayList<>();
					List<Variable> stackVariables = new ArrayList<>();
					if (!ignoreStackFrames) {
						readStackFrame(parser, func, overwriteConflicts, stackVariables,
							stackParams);
					}
					else {
						while (parser.peek().isStart() &&
							parser.peek().getName().equals("STACK_FRAME")) {
							parser.discardSubTree("STACK_FRAME");
						}
					}
					List<Variable> registerParams = new ArrayList<>();
					readRegisterVars(parser, func, registerParams);

					if (typeInfoComment == null) {
						if (returnType != null) {
							func.setReturnType(returnType, SourceType.IMPORTED);
						}

						// Always set to custom storage to preserve all storage specified in XML
						func.setCustomVariableStorage(true);

						try {
							List<Variable> allParams = new ArrayList<>();
							allParams.addAll(registerParams);
							allParams.addAll(stackParams);

							func.replaceParameters(allParams, FunctionUpdateType.CUSTOM_STORAGE,
								true, SourceType.IMPORTED);
						}
						catch (DuplicateNameException e) {
							log.appendMsg("Could not set name of a parameter in function: " +
								funcDesc(func) + ": " + e.getMessage());
						}
						catch (InvalidInputException iie) {
							log.appendMsg("Bad parameter definition in function: " +
								funcDesc(func) + ": " + iie.getMessage());
						}
					}
					else {
						tryToParseTypeInfoComment(monitor, func, typeInfoComment);
					}
					addLocalVars(func, stackVariables, overwriteConflicts);

					functions.addRange(entryPoint, entryPoint);
					parser.end(functionElement);
				}
				catch (Exception e) {
					parser.discardSubTree(functionElement);
					log.appendException(e);
				}
			}
		}
		finally {
			builtInMgr.close();
			dtParser = null;
		}
		parser.end(element);
		FunctionPurgeAnalysisCmd purgeAnalysisCmd = new FunctionPurgeAnalysisCmd(functions);
		purgeAnalysisCmd.applyTo(program, monitor);
		FunctionStackAnalysisCmd stackAnalysisCmd = new FunctionStackAnalysisCmd(functions, true);
		stackAnalysisCmd.applyTo(program, monitor);
	}
Parses a list of {@link Function function} definitions from xml and creates then, adding them to the current
{@link Program program}.
<p>
Information from a TYPEINFO_COMMENT is used in preference to information from RETURN_TYPE and STACK_FRAME/STACK_VARs that
are tagged as parameters.
<p>
DTD for the FUNCTION element:
<pre><code>
&lt;!ELEMENT FUNCTION (RETURN_TYPE?, ADDRESS_RANGE*, REGULAR_CMT?, REPEATABLE_CMT?, TYPEINFO_CMT?, STACK_FRAME?, REGISTER_VAR*)&gt;
</code></pre>

@param parser the parser
@param overwriteConflicts true to overwrite any conflicts
@param ignoreStackFrames true to ignore stack frames
@param monitor the task monitor
@throws AddressFormatException if any address is not parsable 
@throws CancelledException if the operation is cancelled through the monitor
Ghidra/Features/Base/src/main/java/ghidra/app/util/xml/FunctionsXmlMgr.java