private void createFunctionApplySignature(AutoAnalysisManager aMgr, Program program,
			Address address, FunctionDefinition funcDefn) {

		// System.out.println("@ " + address + " - Typedef Function " + ((FunctionDefinition)ptrToDT).getPrototypeString());

		Listing listing = program.getListing();

		// defined data (that isn't an undefined) don't do anything
		Data data = listing.getDefinedDataContaining(address);
		if (data != null) {
			return;
		}

		// if memory is undefined bytes, don't disassemble or create function
		MemoryBlock block = program.getMemory().getBlock(address);
		if (block == null || !block.isInitialized()) {
			return;
		}

		// normalize the address to where code should start (ARM and MIPS can be offset by one)
		Address normalizedAddr =
			PseudoDisassembler.getNormalizedDisassemblyAddress(program, address);
		if (!listing.isUndefined(normalizedAddr, normalizedAddr)) {
			// if not undefined, must be an instruction to continue
			Instruction instr = listing.getInstructionAt(normalizedAddr);
			if (instr == null) {
				return;
			}
		}
		else {
			// if nothing defined here, disassemble
			address = PseudoDisassembler.setTargetContextForDisassembly(program, address);
			DisassembleCommand cmd = new DisassembleCommand(address, null, true);
			cmd.applyTo(program, monitor);
		}

		// see if there is an existing function
		FunctionManager funcMgr = program.getFunctionManager();
		Function func = funcMgr.getFunctionAt(address);
		// if no function at the address, make sure not in the middle of a function
		if (func == null) {
			func = funcMgr.getFunctionContaining(address);
			// don't create a function in the middle of another
			if (func != null) {
				return;
			}
		}

		if (func != null) {
			if (func.isThunk()) {
				return;
			}

			SourceType mostTrusted = getMostTrustedParameterSource(func);
			if (SourceType.ANALYSIS.isLowerPriorityThan(mostTrusted)) {
				return;
			}
		}
		else {
			CreateFunctionCmd createFunctionCmd = new CreateFunctionCmd(address, false);
			aMgr.schedule(createFunctionCmd, AnalysisPriority.FUNCTION_ANALYSIS.priority());
		}

		// only apply the signature if actually creating data, the function/code has already been created
		if (!createDataFromPointers) {
			return;
		}

		// if no arguments, could be an opaque function pointer, don't apply arguments
		ParameterDefinition[] arguments = funcDefn.getArguments();
		DataType returnType = funcDefn.getReturnType();
		if (arguments == null ||
			(arguments.length == 0 && (returnType == null || Undefined.isUndefined(returnType)))) {
			return;
		}

		// applying function signatures considered data
		// don't change name, even default name
		ApplyFunctionSignatureCmd applyFunctionSignatureCmd =
			new ApplyFunctionSignatureCmd(address, funcDefn, SourceType.ANALYSIS, true, false,
				DataTypeConflictHandler.DEFAULT_HANDLER, FunctionRenameOption.NO_CHANGE);
		aMgr.schedule(applyFunctionSignatureCmd,
			AnalysisPriority.FUNCTION_ANALYSIS.after().priority());
	}
Create a function/code at a location and apply the 

@param aMgr auto analysis manager
@param program the program
@param address location to create function
@param funcDefn function definition if known
Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/analysis/ConstantPropagationContextEvaluator.java