public boolean applyFunctionSignature(Function toFunction, ToolOptions markupOptions,
			boolean forceApply) throws VersionTrackingApplyException {

		VTMatchApplyChoices.FunctionSignatureChoices functionSignatureChoice = markupOptions
				.getEnum(VTOptionDefines.FUNCTION_SIGNATURE, DEFAULT_OPTION_FOR_FUNCTION_SIGNATURE);

		int toParamCount = toFunction.getParameterCount();

		if ((functionSignatureChoice == FunctionSignatureChoices.WHEN_SAME_PARAMETER_COUNT) &&
			(toParamCount != parameterInfos.size())) {
			// Don't replace since number of parameters differs.
			Msg.debug(this, "Number of parameters differs so function signature not applied at " +
				toFunction.getEntryPoint() + ".");
			return false;
		}
		CommentChoices commentChoice =
			markupOptions.getEnum(PARAMETER_COMMENTS, DEFAULT_OPTION_FOR_PARAMETER_COMMENTS);

		// Set the parameters and their storage.
		try {

			applyInline(toFunction, isInline, markupOptions);
			applyNoReturn(toFunction, hasNoReturn, markupOptions);

			String conventionName = getCallingConvention(toFunction, markupOptions);

			// Adjust whether or not the resulting function will use custom storage.
			boolean useCustomStorage = false;

			boolean sameLanguage =
				FunctionUtility.isSameLanguageAndCompilerSpec(toFunction.getProgram(), program);

			// if source program has custom storage and both programs have same language then
			// set the useCustomStorage flag to enable using custom storage in destination program
			if (sameLanguage && hasCustomStorage) {
				useCustomStorage = true;
			}

			Parameter returnParam =
				getReturnParameter(toFunction, markupOptions, forceApply, useCustomStorage);

			List<Parameter> newParams =
				getParameters(toFunction, markupOptions, forceApply, useCustomStorage);

			toFunction
					.updateFunction(conventionName, returnParam, newParams,
						useCustomStorage ? FunctionUpdateType.CUSTOM_STORAGE
								: FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,
						true, signatureSource);
			if (forceApply) {
				// must force signatureSource if precedence has been lowered
				// TODO: Should any manual change in function signature force source to be USER_DEFINED instead ??
				toFunction.setSignatureSource(signatureSource);
			}
		}
		catch (DuplicateNameException e) {
			throw new VersionTrackingApplyException(e.getMessage(), e);
		}
		catch (InvalidInputException e) {
			throw new VersionTrackingApplyException(e.getMessage(), e);
		}

		boolean hasFromVarArgs = hasVarargs;
		boolean hasToVarArgs = toFunction.hasVarArgs();
		if (hasFromVarArgs != hasToVarArgs) {
			applyVarArgs(toFunction, hasFromVarArgs, markupOptions);
		}
		applyCallFixup(toFunction, callFixup, markupOptions);

		if (forceApply) {
			forceParameterNames(toFunction);
		}
		else {
			applyParameterNames(toFunction, markupOptions, true, toParamCount);
		}

		replaceParameterComments(toFunction, commentChoice);

		return true;
	}
@param toFunction the function whose signature we are setting.
@param markupOptions the options indicate what parts of the function signature to apply.
@param forceApply true indicates that the function signature should be applied even if the
function signature, return type, parameter data type or parameter name options are set
to "do not apply".
@throws VersionTrackingApplyException if all desired parts of the function signature couldn't be applied.
Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/stringable/FunctionSignatureStringable.java