private boolean analyzeProgram(String fileAbsolutePath, Program program) {

		analysisTimedOut = false;

		AutoAnalysisManager mgr = AutoAnalysisManager.getAnalysisManager(program);
		mgr.initializeOptions();

		GhidraState scriptState = null;
		HeadlessContinuationOption scriptStatus = HeadlessContinuationOption.CONTINUE;

		boolean abortProcessing = false;
		boolean deleteProgram = false;

		if (!options.preScripts.isEmpty()) {
			// create one state, in case each script might want to modify it to pass information
			scriptState = getInitialProgramState(program);

			scriptStatus = runScriptsList(options.preScripts, options.preScriptFileMap, scriptState,
				scriptStatus);
		}

		switch (scriptStatus) {
			case ABORT_AND_DELETE:
				abortProcessing = true;
				deleteProgram = true;
				break;

			case CONTINUE_THEN_DELETE:
				abortProcessing = false;
				deleteProgram = true;
				break;

			case ABORT:
				abortProcessing = true;
				deleteProgram = false;
				break;

			default:
				// do nothing
		}

		if (abortProcessing) {
			Msg.info(this, "Processing aborted as a result of pre-script.");
			return !deleteProgram;
		}

		int txId = program.startTransaction("Analysis");
		try {
			if (options.analyze) {
				Msg.info(this, "ANALYZING all memory and code: " + fileAbsolutePath);
				mgr.initializeOptions();

				// Note: Want to analyze regardless of whether we have already analyzed or not
				// (user could have changed options).
				mgr.reAnalyzeAll(null);

				if (options.perFileTimeout == -1) {
					mgr.startAnalysis(TaskMonitor.DUMMY); // kick start

					Msg.info(this, "REPORT: Analysis succeeded for file: " + fileAbsolutePath);
					GhidraProgramUtilities.markProgramAnalyzed(program);
				}
				else {
					HeadlessTimedTaskMonitor timerMonitor =
						new HeadlessTimedTaskMonitor(options.perFileTimeout);
					mgr.startAnalysis(timerMonitor);

					if (timerMonitor.isCancelled()) {
						Msg.error(this, "REPORT: Analysis timed out at " + options.perFileTimeout +
							" seconds. Processing not completed for file: " + fileAbsolutePath);

						// If no further scripts, just return the current program disposition
						if (options.postScripts.isEmpty()) {
							return !deleteProgram;
						}

						analysisTimedOut = true;
					}
					else {
						// If timeout didn't already happen at this point, cancel the monitor
						timerMonitor.cancel();

						Msg.info(this, "REPORT: Analysis succeeded for file: " + fileAbsolutePath);
						GhidraProgramUtilities.markProgramAnalyzed(program);
					}
				}
			}
		}
		finally {
			program.endTransaction(txId, true);
		}

		if (!options.postScripts.isEmpty()) {

			if (scriptState == null) {
				scriptState = getInitialProgramState(program);
			}

			scriptStatus = runScriptsList(options.postScripts, options.postScriptFileMap,
				scriptState, scriptStatus);

			switch (scriptStatus) {
				case ABORT_AND_DELETE:
					abortProcessing = true;
					deleteProgram = true;
					break;

				case CONTINUE_THEN_DELETE:
					abortProcessing = false;
					deleteProgram = true;
					break;

				case ABORT:
					abortProcessing = true;
					// If deleteProgram is already true, don't change it to false
					// (basically, leave as-is)
					break;

				default:
					// Do nothing, assume want to carry over options from before

			}

			if (abortProcessing) {
				Msg.info(this, "Processing aborted as a result of post-script.");
			}
			else if (options.analyze && !options.postScripts.isEmpty()) {
				Msg.info(this, "ANALYZING changes made by post scripts: " + fileAbsolutePath);
				txId = program.startTransaction("Post-Analysis");
				try {
					mgr.startAnalysis(TaskMonitor.DUMMY); // kick start
				}
				finally {
					program.endTransaction(txId, true);
				}
				Msg.info(this, "REPORT: Post-analysis succeeded for file: " + fileAbsolutePath);
			}

		}

		return !deleteProgram;
	}
{@literal Run prescripts -> analysis -> postscripts (any of these steps is optional).}
@param fileAbsolutePath Path of the file to analyze.
@param program The program to analyze.
@return true if the program file should be kept.  If analysis or scripts have marked
			the program as temporary changes should not be saved.  Returns false in
			these cases:
		- One of the scripts sets the Headless Continuation Option to "ABORT_AND_DELETE" or
			"CONTINUE_THEN_DELETE".
Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/HeadlessAnalyzer.java