private boolean analyzeFunction(Address entry, TaskMonitor monitor) throws CancelledException {
		Listing listing = program.getListing();
		Function f = listing.getFunctionAt(entry);
		if (f == null || f.isThunk()) {
			return false;
		}
//		int depthChange = 0;

		// Perform depth search of all functions reached by this function.
		// Any function that has not had its stack analyzed is added to a list.
		// This way, the lowest level functions frames are looked at to try and determine their
		//  stack purge, before this functions stack is analyzed.
		Stack<Function> stack = new Stack<Function>(); // functions needing to be looked at for valid frames
		ArrayList<Function> funcList = new ArrayList<Function>(); // list of functions needing stack frames created
		stack.push(f);
		while (!stack.isEmpty()) {
			monitor.checkCancelled();
			Function func = stack.pop();
			if (func.isThunk()) {
				continue;
			}
			// if the purge for the function is unknown, it has not been looked at yet.
			//  we need to add it to the list to analyze its stack frame.
			int numVars = func.getVariables(VariableFilter.STACK_VARIABLE_FILTER).length;
			if (numVars == 0) {
				// This function needs its stack looked at.
				funcList.add(0, func);
			}
			else if (forceProcessing && func.getEntryPoint().equals(entry)) {
				// This function needs its stack looked at.
				funcList.add(0, func);
			}
		}

		// Process all the functions identified as needing stack analysis.
		// The list will have the lowest level functions analyzed first.
//		int default_purge = program.getCompilerSpec().getCallStackMod();
//		int default_stackshift = program.getCompilerSpec().getCallStackShift();
		while (!funcList.isEmpty()) {
			monitor.checkCancelled();
			Function func = funcList.remove(0);
			SourceType oldSignatureSource = func.getSignatureSource();

			monitor.setMessage("Stack " + func.getName());
			createStackPointerVariables(func, monitor);

			if (oldSignatureSource != func.getSignatureSource()) {
				// preserve signature source 
				func.setSignatureSource(oldSignatureSource);
			}

//			if (depthChange > 0xfffff || depthChange < -0xfffff) {
//				depthChange = Function.INVALID_STACK_DEPTH_CHANGE;
//			}
//
//			// Stack purge is defined as the number of extra bytes that are popped
//			//   off of the stack beyond the normal calling conventions.
//			//   the default_callstackmod includes the normal call stack shift,
//			//   so subtract it out.
//			if (default_purge != PrototypeModel.UNKNOWN_EXTRAPOP) {
//				depthChange = default_purge - default_stackshift;
//			}
			// func.setStackPurgeSize(depthChange);
		}
		return true;
	}
Analyze a function to build a stack frame based on stack references.

@param entry   The address of the entry point for the new function
@param monitor the task monitor that is checked to see if the command has
been cancelled.
@throws CancelledException if the user canceled this command
Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/FunctionStackAnalysisCmd.java