From: "Michael D Kinney" <michael.d.kinney@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"mikuback@linux.microsoft.com" <mikuback@linux.microsoft.com>,
"Kinney, Michael D" <michael.d.kinney@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>,
Sean Brogan <sean.brogan@microsoft.com>,
Bret Barkelew <Bret.Barkelew@microsoft.com>
Subject: Re: [edk2-devel] [PATCH v4 1/1] .pytool/Plugin/UncrustifyCheck: Add Uncrustify CI plugin
Date: Thu, 25 Nov 2021 02:05:46 +0000 [thread overview]
Message-ID: <CO1PR11MB4929A7738CA99E58694C327DD2629@CO1PR11MB4929.namprd11.prod.outlook.com> (raw)
In-Reply-To: <8dbc6f60-dcb7-6a1f-c19e-3eb696c1afa3@linux.microsoft.com>
Hi Michael,
I agree with these updates.
Thank you for posting the branches.
Mike
> -----Original Message-----
> From: Michael Kubacki <mikuback@linux.microsoft.com>
> Sent: Wednesday, November 24, 2021 5:25 PM
> To: devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Liming Gao <gaoliming@byosoft.com.cn>; Sean Brogan <sean.brogan@microsoft.com>; Bret Barkelew
> <Bret.Barkelew@microsoft.com>
> Subject: Re: [edk2-devel] [PATCH v4 1/1] .pytool/Plugin/UncrustifyCheck: Add Uncrustify CI plugin
>
> I sent the v5 patch with the templates disabled:
> https://edk2.groups.io/g/devel/message/84068
>
> I also posted that patch on this branch:
> https://github.com/makubacki/edk2/tree/add_uncrustify_ci_plugin_v5
>
> I posted another branch that also has the commit to enable the templates
> here:
> https://github.com/makubacki/edk2/commits/add_uncrustify_ci_plugin_v5_w_template_enable_commit
>
> I will be out of office until Mon Nov. 29th for the US holiday.
>
> Thanks,
> Michael
>
> On 11/24/2021 7:24 PM, Michael Kubacki wrote:
> > Hi Mike,
> >
> > How about I quickly send a v5 with the lines commented out and follow up
> > with a patch to uncomment them that we can review but merge when ready?
> >
> > Thanks,
> > Michael
> >
> > On 11/24/2021 7:16 PM, Michael D Kinney wrote:
> >> The 2nd option I listed won't work. That will fail UncrustifyCheck as
> >> well because EDK II CI
> >> will insert missing file/function headers and the files will not match.
> >>
> >> We will need to comment out these 2 lines and submit an extra commit
> >> to re-enable.
> >>
> >> Mike
> >>
> >>> -----Original Message-----
> >>> From: Kinney, Michael D <michael.d.kinney@intel.com>
> >>> Sent: Wednesday, November 24, 2021 4:08 PM
> >>> To: devel@edk2.groups.io; mikuback@linux.microsoft.com; Kinney,
> >>> Michael D <michael.d.kinney@intel.com>
> >>> Cc: Liming Gao <gaoliming@byosoft.com.cn>; Sean Brogan
> >>> <sean.brogan@microsoft.com>; Bret Barkelew
> >>> <Bret.Barkelew@microsoft.com>
> >>> Subject: RE: [edk2-devel] [PATCH v4 1/1]
> >>> .pytool/Plugin/UncrustifyCheck: Add Uncrustify CI plugin
> >>>
> >>> Hi Michael,
> >>>
> >>> Unfortunately, enabling the templates in the uncrustify.cfg files
> >>> modifies 340 files with missing
> >>> file/function headers that will now fail UncrustifyCheck.
> >>>
> >>> cmt_insert_file_header = default_file_header.txt
> >>> cmt_insert_func_header = default_function_header.txt
> >>>
> >>> Perhaps we should leave this feature off to get the uncrustify format
> >>> changes committed and
> >>> enable this feature immediately after so patch reviews after that
> >>> will slowly fix these missing
> >>> file/function headers.
> >>>
> >>> Or I can comment these two lines out when I generate the final
> >>> version of the patch series so
> >>> we don’t have to do an extra commit to re-enable.
> >>>
> >>> Mike
> >>>
> >>>> -----Original Message-----
> >>>> From: Kinney, Michael D <michael.d.kinney@intel.com>
> >>>> Sent: Wednesday, November 24, 2021 3:06 PM
> >>>> To: devel@edk2.groups.io; mikuback@linux.microsoft.com; Kinney,
> >>>> Michael D <michael.d.kinney@intel.com>
> >>>> Cc: Liming Gao <gaoliming@byosoft.com.cn>; Sean Brogan
> >>>> <sean.brogan@microsoft.com>; Bret Barkelew
> >>>> <Bret.Barkelew@microsoft.com>
> >>>> Subject: RE: [edk2-devel] [PATCH v4 1/1]
> >>>> .pytool/Plugin/UncrustifyCheck: Add Uncrustify CI plugin
> >>>>
> >>>> Thanks. That makes sense.
> >>>>
> >>>> Mike
> >>>>
> >>>>> -----Original Message-----
> >>>>> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> >>>>> Michael Kubacki
> >>>>> Sent: Wednesday, November 24, 2021 2:55 PM
> >>>>> To: devel@edk2.groups.io; Kinney, Michael D
> >>>>> <michael.d.kinney@intel.com>
> >>>>> Cc: Liming Gao <gaoliming@byosoft.com.cn>; Sean Brogan
> >>>>> <sean.brogan@microsoft.com>; Bret Barkelew
> >>>>> <Bret.Barkelew@microsoft.com>
> >>>>> Subject: Re: [edk2-devel] [PATCH v4 1/1]
> >>>>> .pytool/Plugin/UncrustifyCheck: Add Uncrustify CI plugin
> >>>>>
> >>>>> Yes. Those were redundant and detected by the Python configparser
> >>>>> module
> >>>>> when I used it to parse the config file.
> >>>>>
> >>>>> Thanks,
> >>>>> Michael
> >>>>>
> >>>>> On 11/24/2021 5:45 PM, Michael D Kinney wrote:
> >>>>>> Hi Michael,
> >>>>>>
> >>>>>> I see a couple settings deleted from the uncrustify.cfg. Was that
> >>>>>> in purpose? Does it change the format?
> >>>>>>
> >>>>>>
> >>>>>> -nl_func_call_start_multi_line = true # Whether to add a
> >>>>>> newline after '(' in a function call if '(' and ')'
> >>>> are
> >>>>>> - # in different lines.
> >>>>>>
> >>>>>>
> >>>>>> -nl_func_call_args_multi_line = true
> >>>>>> -nl_func_call_args_multi_line_ignore_closures = false
> >>>>>>
> >>>>>>
> >>>>>> Thanks,
> >>>>>>
> >>>>>> Mike
> >>>>>>
> >>>>>>> -----Original Message-----
> >>>>>>> From: mikuback@linux.microsoft.com <mikuback@linux.microsoft.com>
> >>>>>>> Sent: Wednesday, November 24, 2021 1:42 PM
> >>>>>>> To: devel@edk2.groups.io
> >>>>>>> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Liming Gao
> >>>>>>> <gaoliming@byosoft.com.cn>; Sean Brogan
> >>>>>>> <sean.brogan@microsoft.com>; Bret Barkelew
> >>>>>>> <Bret.Barkelew@microsoft.com>
> >>>>>>> Subject: [PATCH v4 1/1] .pytool/Plugin/UncrustifyCheck: Add
> >>>>>>> Uncrustify CI plugin
> >>>>>>>
> >>>>>>> From: Michael Kubacki <michael.kubacki@microsoft.com>
> >>>>>>>
> >>>>>>> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3748
> >>>>>>>
> >>>>>>> Adds a new CI plugin for Uncrustify. This is used to check
> >>>>>>> coding standard compliance of source code to the EDK II C Coding
> >>>>>>> Standards Specification.
> >>>>>>>
> >>>>>>> An external dependency is added in the plugin directory to retrieve
> >>>>>>> the Uncrustify executable. Currently, the executable is from an edk2
> >>>>>>> fork of the application host in this repository:
> >>>>>>>
> >>>>>>> https://dev.azure.com/projectmu/Uncrustify/
> >>>>>>>
> >>>>>>> Note that the Uncrustify application outputs the commit ID that the
> >>>>>>> application was built from when given the --version parameter.
> >>>>>>>
> >>>>>>> This ID can be mapped to the version specified in the Uncrustify CI
> >>>>>>> plugin external dependency file (uncrustify_ext_dep.yaml) such as
> >>>>>>> 73.0.3 by visiting the Uncrustify edk2 fork release pipeline page
> >>>>>>> which associates the NuGet package version with the commit ID it was
> >>>>>>> built from:
> >>>>>>>
> >>>>>>> https://dev.azure.com/projectmu/Uncrustify/_build
> >>>>>>>
> >>>>>>> The default Uncrustify configuration files are added in the plugin
> >>>>>>> directory. Additional details are in the Readme.md file added in
> >>>>>>> the Uncrustify plugin directory.
> >>>>>>>
> >>>>>>> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> >>>>>>> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> >>>>>>> Cc: Sean Brogan <sean.brogan@microsoft.com>
> >>>>>>> Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
> >>>>>>> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
> >>>>>>> ---
> >>>>>>>
> >>>>>>> Notes:
> >>>>>>> V4 changes:
> >>>>>>>
> >>>>>>> 1. Updated commit subject to use the new plugin name.
> >>>>>>> 2. Enabled file and function header templates to be placed in
> >>>>>>> files missing a file or function header (comment block).
> >>>>>>> 3. Added support to detect whether a file header or function
> >>>>>>> header is missing in a file by searching files modified by
> >>>>>>> Uncrustify for the template file text.
> >>>>>>> 4. Updated the plugin name displayed in some log output
> >>>>>>> messages.
> >>>>>>>
> >>>>>>> V3 changes:
> >>>>>>>
> >>>>>>> 1. Renamed the CI plugin to "UncrustifyCheck" from
> >>>>>>> "Uncrustify"
> >>>>>>> to follow similar naming conventions used in other plugins
> >>>>>>> that check files
> >>>>>>> 2. Added a clarifying paragraph to the beginning of the
> >>>>>>> Uncrustify
> >>>>>>> CI plugin Readme.md file that the plugin is enabled by
> >>>>>>> default
> >>>>>>> and test results can be ignored by enabling "AuditOnly"
> >>>>>>> mode.
> >>>>>>> 3. Added instructions in the commit message on how to map the
> >>>>>>> version reported by the Uncrustify application
> >>>>>>> (--version) to
> >>>>>>> the version specified in the CI plugin external dependency
> >>>>>>> YAML file.
> >>>>>>>
> >>>>>>> V2 changes:
> >>>>>>>
> >>>>>>> 1. Changed plugin temp directory to
> >>>>>>> Build/.pytool/Plugin/Uncrustify
> >>>>>>> 2. Added TCBZ REF in patch commit message
> >>>>>>>
> >>>>>>> .pytool/Plugin/UncrustifyCheck/Readme.md |
> >>>>>>> 120 ++++
> >>>>>>> .pytool/Plugin/UncrustifyCheck/UncrustifyCheck.py |
> >>>>>>> 617 ++++++++++++++++++++
> >>>>>>> .pytool/Plugin/UncrustifyCheck/default_file_header.txt |
> >>>>>>> 9 +
> >>>>>>> .pytool/Plugin/UncrustifyCheck/default_function_header.txt |
> >>>>>>> 15 +
> >>>>>>> .pytool/Plugin/UncrustifyCheck/uncrustify.cfg |
> >>>>>>> 462 +++++++++++++++
> >>>>>>> .pytool/Plugin/UncrustifyCheck/uncrustify_ext_dep.yaml |
> >>>>>>> 16 +
> >>>>>>> .pytool/Plugin/UncrustifyCheck/uncrustify_plug_in.yaml |
> >>>>>>> 11 +
> >>>>>>> .pytool/Readme.md |
> >>>>>>> 4 +
> >>>>>>> 8 files changed, 1254 insertions(+)
> >>>>>>>
> >>>>>>> diff --git a/.pytool/Plugin/UncrustifyCheck/Readme.md
> >>>>>>> b/.pytool/Plugin/UncrustifyCheck/Readme.md
> >>>>>>> new file mode 100644
> >>>>>>> index 000000000000..bb263bcc87d7
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/.pytool/Plugin/UncrustifyCheck/Readme.md
> >>>>>>> @@ -0,0 +1,120 @@
> >>>>>>> +# UncrustifyCheck Plugin
> >>>>>>> +
> >>>>>>> +This CiBuildPlugin scans all the files in a given package and
> >>>>>>> checks for coding standard compliance issues.
> >>>>>>> +
> >>>>>>> +This plugin is enabled by default. If a package would like to
> >>>>>>> prevent the plugin from reporting errors, it can do
> >>>>>>> +so by enabling [`AuditOnly`](#auditonly) mode.
> >>>>>>> +
> >>>>>>> +This plugin requires the directory containing the Uncrustify
> >>>>>>> executable that should be used for this plugin to
> >>>>>>> +be specified in an environment variable named
> >>>>>>> `UNCRUSTIFY_CI_PATH`. This unique variable name is used to avoid
> >>>>> confusion
> >>>>>>> +with other paths to Uncrustify which might not be the expected
> >>>>>>> build for use by this plugin.
> >>>>>>> +
> >>>>>>> +By default, an Uncrustify configuration file named
> >>>>>>> "uncrustify.cfg" located in the same directory as the plugin is
> >>>>>>> +used. The value can be overridden to a package-specific path
> >>>>>>> with the `ConfigFilePath` configuration file option.
> >>>>>>> +
> >>>>>>> +* Uncrustify source code and documentation:
> >>>>>>> https://github.com/uncrustify/uncrustify
> >>>>>>> +* Project Mu Uncrustify fork source code and documentation:
> >>>>>>> https://dev.azure.com/projectmu/Uncrustify
> >>>>>>> +
> >>>>>>> +## Files Checked in a Package
> >>>>>>> +
> >>>>>>> +By default, this plugin will discover all files in the package
> >>>>>>> with the following default paths:
> >>>>>>> +
> >>>>>>> +```python
> >>>>>>> +[
> >>>>>>> +# C source
> >>>>>>> +"*.c",
> >>>>>>> +"*.h"
> >>>>>>> +]
> >>>>>>> +```
> >>>>>>> +
> >>>>>>> +From this list of files, any files ignored by Git or residing in
> >>>>>>> a Git submodule will be removed. If Git is not
> >>>>>>> +found, submodules are not found, or ignored files are not found
> >>>>>>> no changes are made to the list of discovered
> >>> files.
> >>>>>>> +
> >>>>>>> +To control the paths checked in a given package, review the
> >>>>>>> configuration options described in this file.
> >>>>>>> +
> >>>>>>> +## Configuration
> >>>>>>> +
> >>>>>>> +The plugin can be configured with a few optional configuration
> >>>>>>> options.
> >>>>>>> +
> >>>>>>> +``` yaml
> >>>>>>> + "UncrustifyCheck": {
> >>>>>>> + "AdditionalIncludePaths": [], # Additional paths to check
> >>>>>>> formatting (wildcards supported).
> >>>>>>> + "AuditOnly": False, # Don't fail the build if
> >>>>>>> there are errors. Just log them.
> >>>>>>> + "ConfigFilePath": "", # Custom path to an
> >>>>>>> Uncrustify config file.
> >>>>>>> + "IgnoreStandardPaths": [], # Standard Plugin defined
> >>>>>>> paths that should be ignored.
> >>>>>>> + "OutputFileDiffs": False, # Output chunks of
> >>>>>>> formatting diffs in the test case log.
> >>>>>>> + # This can significantly
> >>>>>>> slow down the plugin on very large packages.
> >>>>>>> + "SkipGitExclusions": False # Don't exclude git ignored
> >>>>>>> files and files in git submodules.
> >>>>>>> + }
> >>>>>>> +```
> >>>>>>> +
> >>>>>>> +### `AdditionalIncludePaths`
> >>>>>>> +
> >>>>>>> +A package configuration file can specify any additional paths to
> >>>>>>> be included with this option.
> >>>>>>> +
> >>>>>>> +At this time, it is recommended all files run against the plugin
> >>>>>>> be written in the C or C++ language.
> >>>>>>> +
> >>>>>>> +### `AuditOnly`
> >>>>>>> +
> >>>>>>> +`Boolean` - Default is `False`.
> >>>>>>> +
> >>>>>>> +If `True`, run the test in an "audit only mode" which will log
> >>>>>>> all errors but instead of failing the build, it
> >>> will
> >>>>> set
> >>>>>>> +the test as skipped. This allows visibility into the failures
> >>>>>>> without breaking the build.
> >>>>>>> +
> >>>>>>> +### `ConfigFilePath`
> >>>>>>> +
> >>>>>>> +`String` - Default is `"uncrustify.cfg"`
> >>>>>>> +
> >>>>>>> +When specified in the config file, this is a package relative
> >>>>>>> path to the Uncrustify configuration file.
> >>>>>>> +
> >>>>>>> +### `IgnoreStandardPaths`
> >>>>>>> +
> >>>>>>> +This plugin by default will check the below standard paths. A
> >>>>>>> package configuration file can specify any of these
> >>>>> paths
> >>>>>>> +to be ignored.
> >>>>>>> +
> >>>>>>> +```python
> >>>>>>> +[
> >>>>>>> +# C source
> >>>>>>> +"*.c",
> >>>>>>> +"*.h"
> >>>>>>> +]
> >>>>>>> +```
> >>>>>>> +
> >>>>>>> +### `OutputFileDiffs`
> >>>>>>> +
> >>>>>>> +`Boolean` - Default is `False`.
> >>>>>>> +
> >>>>>>> +If `True`, output diffs of formatting changes into the test case
> >>>>>>> log. This is helpful to exactly understand what
> >>>>> changes
> >>>>>>> +need to be made to the source code in order to fix a coding
> >>>>>>> standard compliance issue.
> >>>>>>> +
> >>>>>>> +Note that calculating the file diffs on a very large set of of
> >>>>>>> results (e.g. >100 files) can significantly slow
> >>> down
> >>>>>>> +plugin execution.
> >>>>>>> +
> >>>>>>> +### `SkipGitExclusions`
> >>>>>>> +
> >>>>>>> +`Boolean` - Default is `False`.
> >>>>>>> +
> >>>>>>> +By default, files in paths matched in a .gitignore file or a
> >>>>>>> recognized git submodule are excluded. If this option
> >>>>>>> +is `True`, the plugin will not attempt to recognize these files
> >>>>>>> and exclude them.
> >>>>>>> +
> >>>>>>> +## High-Level Plugin Operation
> >>>>>>> +
> >>>>>>> +This plugin generates two main sets of temporary files:
> >>>>>>> +
> >>>>>>> + 1. A working directory in the directory
> >>>>>>> `Build/.pytool/Plugin/Uncrustify`
> >>>>>>> + 2. For each source file with formatting errors, a sibling file
> >>>>>>> with the `.uncrustify_plugin` extension
> >>>>>>> +
> >>>>>>> +The working directory contains temporary files unique to
> >>>>>>> operation of the plugin. All of these files are removed
> >>> on
> >>>>>>> +exit of the plugin including successful or unsuccessful
> >>>>>>> execution (such as a Python exception occurring). If for
> >>> any
> >>>>>>> +reason, any files in the package exist prior to running the
> >>>>>>> plugin with the `.uncrustify_plugin` extension, the
> >>>> plugin
> >>>>>>> +will inform the user to remove these files and exit before
> >>>>>>> running Uncrustify. This is to ensure the accuracy of
> >>> the
> >>>>>>> +results reported from each execution instance of the plugin.
> >>>>>>> +
> >>>>>>> +The plugin determines the list of relevant files to check with
> >>>>>>> Uncrustify and then invokes Uncrustify with that
> >>> file
> >>>>>>> +list. For any files not compliant to the configuration file
> >>>>>>> provided, Uncrustify will generate a corresponding
> >>> file
> >>>>>>> +with the `.uncrustify_plugin` extension. The plugin discovers
> >>>>>>> all of these files. If any such files are present,
> >>>> this
> >>>>>>> +indicates a formatting issue was found and the test is marked
> >>>>>>> failed (unless `AuditOnly` mode is enabled).
> >>>>>>> +
> >>>>>>> +The test case log will contain a report of which files failed to
> >>>>>>> format properly, allowing the user to run
> >>>> Uncrustify
> >>>>>>> +against the file locally to fix the issue. If the
> >>>>>>> `OutputFileDiffs` configuration option is set to `True`, the
> >>>> plugin
> >>>>>>> +will output diff chunks for all code formatting issues in the
> >>>>>>> test case log.
> >>>>>>> diff --git a/.pytool/Plugin/UncrustifyCheck/UncrustifyCheck.py
> >>>>>>> b/.pytool/Plugin/UncrustifyCheck/UncrustifyCheck.py
> >>>>>>> new file mode 100644
> >>>>>>> index 000000000000..59534469a2d3
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/.pytool/Plugin/UncrustifyCheck/UncrustifyCheck.py
> >>>>>>> @@ -0,0 +1,617 @@
> >>>>>>> +# @file UncrustifyCheck.py
> >>>>>>> +#
> >>>>>>> +# An edk2-pytool based plugin wrapper for Uncrustify
> >>>>>>> +#
> >>>>>>> +# Copyright (c) Microsoft Corporation.
> >>>>>>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> >>>>>>> +##
> >>>>>>> +import configparser
> >>>>>>> +import difflib
> >>>>>>> +import errno
> >>>>>>> +import logging
> >>>>>>> +import os
> >>>>>>> +import pathlib
> >>>>>>> +import shutil
> >>>>>>> +import timeit
> >>>>>>> +from edk2toolext.environment import version_aggregator
> >>>>>>> +from edk2toolext.environment.plugin_manager import PluginManager
> >>>>>>> +from edk2toolext.environment.plugintypes.ci_build_plugin import
> >>>>>>> ICiBuildPlugin
> >>>>>>> +from edk2toolext.environment.plugintypes.uefi_helper_plugin
> >>>>>>> import HelperFunctions
> >>>>>>> +from edk2toolext.environment.var_dict import VarDict
> >>>>>>> +from edk2toollib.log.junit_report_format import JunitReportTestCase
> >>>>>>> +from edk2toollib.uefi.edk2.path_utilities import Edk2Path
> >>>>>>> +from edk2toollib.utility_functions import RunCmd
> >>>>>>> +from io import StringIO
> >>>>>>> +from typing import Any, Dict, List, Tuple
> >>>>>>> +
> >>>>>>> +#
> >>>>>>> +# Provide more user friendly messages for certain scenarios
> >>>>>>> +#
> >>>>>>> +class UncrustifyException(Exception):
> >>>>>>> + def __init__(self, message, exit_code):
> >>>>>>> + super().__init__(message)
> >>>>>>> + self.exit_code = exit_code
> >>>>>>> +
> >>>>>>> +
> >>>>>>> +class UncrustifyAppEnvVarNotFoundException(UncrustifyException):
> >>>>>>> + def __init__(self, message):
> >>>>>>> + super().__init__(message, -101)
> >>>>>>> +
> >>>>>>> +
> >>>>>>> +class UncrustifyAppVersionErrorException(UncrustifyException):
> >>>>>>> + def __init__(self, message):
> >>>>>>> + super().__init__(message, -102)
> >>>>>>> +
> >>>>>>> +
> >>>>>>> +class UncrustifyAppExecutionException(UncrustifyException):
> >>>>>>> + def __init__(self, message):
> >>>>>>> + super().__init__(message, -103)
> >>>>>>> +
> >>>>>>> +
> >>>>>>> +class
> >>>>>>> UncrustifyStalePluginFormattedFilesException(UncrustifyException):
> >>>>>>> + def __init__(self, message):
> >>>>>>> + super().__init__(message, -120)
> >>>>>>> +
> >>>>>>> +
> >>>>>>> +class
> >>>>>>> UncrustifyInputFileCreationErrorException(UncrustifyException):
> >>>>>>> + def __init__(self, message):
> >>>>>>> + super().__init__(message, -121)
> >>>>>>> +
> >>>>>>> +class
> >>>>>>> UncrustifyInvalidIgnoreStandardPathsException(UncrustifyException):
> >>>>>>> + def __init__(self, message):
> >>>>>>> + super().__init__(message, -122)
> >>>>>>> +
> >>>>>>> +class UncrustifyGitIgnoreFileException(UncrustifyException):
> >>>>>>> + def __init__(self, message):
> >>>>>>> + super().__init__(message, -140)
> >>>>>>> +
> >>>>>>> +
> >>>>>>> +class UncrustifyGitSubmoduleException(UncrustifyException):
> >>>>>>> + def __init__(self, message):
> >>>>>>> + super().__init__(message, -141)
> >>>>>>> +
> >>>>>>> +
> >>>>>>> +class UncrustifyCheck(ICiBuildPlugin):
> >>>>>>> + """
> >>>>>>> + A CiBuildPlugin that uses Uncrustify to check the source
> >>>>>>> files in the
> >>>>>>> + package being tested for coding standard issues.
> >>>>>>> +
> >>>>>>> + By default, the plugin runs against standard C source file
> >>>>>>> extensions but
> >>>>>>> + its configuration can be modified through its configuration
> >>>>>>> file.
> >>>>>>> +
> >>>>>>> + Configuration options:
> >>>>>>> + "UncrustifyCheck": {
> >>>>>>> + "AdditionalIncludePaths": [], # Additional paths to
> >>>>>>> check formatting (wildcards supported).
> >>>>>>> + "AuditOnly": False, # Don't fail the build if
> >>>>>>> there are errors. Just log them.
> >>>>>>> + "ConfigFilePath": "", # Custom path to an
> >>>>>>> Uncrustify config file.
> >>>>>>> + "IgnoreStandardPaths": [], # Standard Plugin defined
> >>>>>>> paths that should be ignored.
> >>>>>>> + "OutputFileDiffs": False, # Output chunks of
> >>>>>>> formatting diffs in the test case log.
> >>>>>>> + # This can significantly
> >>>>>>> slow down the plugin on very large packages.
> >>>>>>> + "SkipGitExclusions": False # Don't exclude git
> >>>>>>> ignored files and files in git submodules.
> >>>>>>> + }
> >>>>>>> + """
> >>>>>>> +
> >>>>>>> + #
> >>>>>>> + # By default, use an "uncrustify.cfg" config file in the
> >>>>>>> plugin directory
> >>>>>>> + # A package can override this path via "ConfigFilePath"
> >>>>>>> + #
> >>>>>>> + # Note: Values specified via "ConfigFilePath" are relative
> >>>>>>> to the package
> >>>>>>> + #
> >>>>>>> + DEFAULT_CONFIG_FILE_PATH = os.path.join(
> >>>>>>> + pathlib.Path(__file__).parent.resolve(), "uncrustify.cfg")
> >>>>>>> +
> >>>>>>> + #
> >>>>>>> + # The extension used for formatted files produced by this
> >>>>>>> plugin
> >>>>>>> + #
> >>>>>>> + FORMATTED_FILE_EXTENSION = ".uncrustify_plugin"
> >>>>>>> +
> >>>>>>> + #
> >>>>>>> + # A package can add any additional paths with
> >>>>>>> "AdditionalIncludePaths"
> >>>>>>> + # A package can remove any of these paths with
> >>>>>>> "IgnoreStandardPaths"
> >>>>>>> + #
> >>>>>>> + STANDARD_PLUGIN_DEFINED_PATHS = ("*.c", "*.h")
> >>>>>>> +
> >>>>>>> + #
> >>>>>>> + # The Uncrustify application path should set in this
> >>>>>>> environment variable
> >>>>>>> + #
> >>>>>>> + UNCRUSTIFY_PATH_ENV_KEY = "UNCRUSTIFY_CI_PATH"
> >>>>>>> +
> >>>>>>> + def GetTestName(self, packagename: str, environment:
> >>>>>>> VarDict) -> Tuple:
> >>>>>>> + """ Provide the testcase name and classname for use in
> >>>>>>> reporting
> >>>>>>> +
> >>>>>>> + Args:
> >>>>>>> + packagename: string containing name of package to
> >>>>>>> build
> >>>>>>> + environment: The VarDict for the test to run in
> >>>>>>> + Returns:
> >>>>>>> + A tuple containing the testcase name and the
> >>>>>>> classname
> >>>>>>> + (testcasename, classname)
> >>>>>>> + testclassname: a descriptive string for the
> >>>>>>> testcase can include whitespace
> >>>>>>> + classname: should be patterned
> >>>>>>> <packagename>.<plugin>.<optionally any unique condition>
> >>>>>>> + """
> >>>>>>> + return ("Check file coding standard compliance in " +
> >>>>>>> packagename, packagename + ".UncrustifyCheck")
> >>>>>>> +
> >>>>>>> + def RunBuildPlugin(self, package_rel_path: str, edk2_path:
> >>>>>>> Edk2Path, package_config: Dict[str, List[str]],
> >>>>>>> environment_config: Any, plugin_manager: PluginManager,
> >>>>>>> plugin_manager_helper: HelperFunctions, tc:
> >>>>> JunitReportTestCase,
> >>>>>>> output_stream=None) -> int:
> >>>>>>> + """
> >>>>>>> + External function of plugin. This function is used to
> >>>>>>> perform the task of the CiBuild Plugin.
> >>>>>>> +
> >>>>>>> + Args:
> >>>>>>> + - package_rel_path: edk2 workspace relative path to
> >>>>>>> the package
> >>>>>>> + - edk2_path: Edk2Path object with workspace and
> >>>>>>> packages paths
> >>>>>>> + - package_config: Dictionary with the package
> >>>>>>> configuration
> >>>>>>> + - environment_config: Environment configuration
> >>>>>>> + - plugin_manager: Plugin Manager Instance
> >>>>>>> + - plugin_manager_helper: Plugin Manager Helper Instance
> >>>>>>> + - tc: JUnit test case
> >>>>>>> + - output_stream: The StringIO output stream from this
> >>>>>>> plugin (logging)
> >>>>>>> +
> >>>>>>> + Returns
> >>>>>>> + >0 : Number of errors found
> >>>>>>> + 0 : Passed successfully
> >>>>>>> + -1 : Skipped for missing prereq
> >>>>>>> + """
> >>>>>>> + try:
> >>>>>>> + # Initialize plugin and check pre-requisites.
> >>>>>>> + self._initialize_environment_info(
> >>>>>>> + package_rel_path, edk2_path, package_config, tc)
> >>>>>>> + self._initialize_configuration()
> >>>>>>> + self._check_for_preexisting_formatted_files()
> >>>>>>> +
> >>>>>>> + # Log important context information.
> >>>>>>> + self._log_uncrustify_app_info()
> >>>>>>> +
> >>>>>>> + # Get template file contents if specified
> >>>>>>> + self._get_template_file_contents()
> >>>>>>> +
> >>>>>>> + # Create meta input files & directories
> >>>>>>> + self._create_temp_working_directory()
> >>>>>>> + self._create_uncrustify_file_list_file()
> >>>>>>> +
> >>>>>>> + self._run_uncrustify()
> >>>>>>> +
> >>>>>>> + # Post-execution actions.
> >>>>>>> + self._process_uncrustify_results()
> >>>>>>> +
> >>>>>>> + except UncrustifyException as e:
> >>>>>>> + self._tc.LogStdError(
> >>>>>>> + f"Uncrustify error {e.exit_code}.
> >>>>>>> Details:\n\n{str(e)}")
> >>>>>>> + logging.warning(
> >>>>>>> + f"Uncrustify error {e.exit_code}.
> >>>>>>> Details:\n\n{str(e)}")
> >>>>>>> + return -1
> >>>>>>> + else:
> >>>>>>> + if self._formatted_file_error_count > 0:
> >>>>>>> + if self._audit_only_mode:
> >>>>>>> + logging.info(
> >>>>>>> + "Setting test as skipped since AuditOnly
> >>>>>>> is enabled")
> >>>>>>> + self._tc.SetSkipped()
> >>>>>>> + return -1
> >>>>>>> + else:
> >>>>>>> + self._tc.SetFailed(
> >>>>>>> + f"{self._plugin_name} failed due to
> >>>>>>> {self._formatted_file_error_count} incorrectly
> >>> formatted
> >>>>>>> files.", "CHECK_FAILED")
> >>>>>>> + else:
> >>>>>>> + self._tc.SetSuccess()
> >>>>>>> + return self._formatted_file_error_count
> >>>>>>> + finally:
> >>>>>>> + self._cleanup_temporary_formatted_files()
> >>>>>>> + self._cleanup_temporary_directory()
> >>>>>>> +
> >>>>>>> + def _initialize_configuration(self) -> None:
> >>>>>>> + """
> >>>>>>> + Initializes plugin configuration.
> >>>>>>> + """
> >>>>>>> + self._initialize_app_info()
> >>>>>>> + self._initialize_config_file_info()
> >>>>>>> + self._initialize_file_to_format_info()
> >>>>>>> + self._initialize_test_case_output_options()
> >>>>>>> +
> >>>>>>> + def _check_for_preexisting_formatted_files(self) -> None:
> >>>>>>> + """
> >>>>>>> + Checks if any formatted files from prior execution are
> >>>>>>> present.
> >>>>>>> +
> >>>>>>> + Existence of such files is an unexpected condition. This
> >>>>>>> might result
> >>>>>>> + from an error that occurred during a previous run or a
> >>>>>>> premature exit from a debug scenario. In any case,
> >>>> the
> >>>>>>> package should be clean before starting a new run.
> >>>>>>> + """
> >>>>>>> + pre_existing_formatted_file_count = len(
> >>>>>>> + [str(path.resolve()) for path in
> >>>>>>> pathlib.Path(self._abs_package_path).rglob(f'*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}')])
> >>>>>>>
> >>>>>>> +
> >>>>>>> + if pre_existing_formatted_file_count > 0:
> >>>>>>> + raise UncrustifyStalePluginFormattedFilesException(
> >>>>>>> + f"{pre_existing_formatted_file_count} formatted
> >>>>>>> files already exist. To prevent overwriting these
> >>>>> files,
> >>>>>>> please remove them before running this plugin.")
> >>>>>>> +
> >>>>>>> + def _cleanup_temporary_directory(self) -> None:
> >>>>>>> + """
> >>>>>>> + Cleans up the temporary directory used for this
> >>>>>>> execution instance.
> >>>>>>> +
> >>>>>>> + This removes the directory and all files created during
> >>>>>>> this instance.
> >>>>>>> + """
> >>>>>>> + if hasattr(self, '_working_dir'):
> >>>>>>> + self._remove_tree(self._working_dir)
> >>>>>>> +
> >>>>>>> + def _cleanup_temporary_formatted_files(self) -> None:
> >>>>>>> + """
> >>>>>>> + Cleans up the temporary formmatted files produced by
> >>>>>>> Uncrustify.
> >>>>>>> +
> >>>>>>> + This will recursively remove all formatted files
> >>>>>>> generated by Uncrustify
> >>>>>>> + during this execution instance.
> >>>>>>> + """
> >>>>>>> + if hasattr(self, '_abs_package_path'):
> >>>>>>> + formatted_files = [str(path.resolve()) for path in
> >>>>>>> pathlib.Path(
> >>>>>>> +
> >>>>>>> self._abs_package_path).rglob(f'*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}')]
> >>>>>>>
> >>>>>>> +
> >>>>>>> + for formatted_file in formatted_files:
> >>>>>>> + os.remove(formatted_file)
> >>>>>>> +
> >>>>>>> + def _create_temp_working_directory(self) -> None:
> >>>>>>> + """
> >>>>>>> + Creates the temporary directory used for this execution
> >>>>>>> instance.
> >>>>>>> + """
> >>>>>>> + self._working_dir = os.path.join(
> >>>>>>> + self._abs_workspace_path, "Build", ".pytool",
> >>>>>>> "Plugin", f"{self._plugin_name}")
> >>>>>>> +
> >>>>>>> + try:
> >>>>>>> + pathlib.Path(self._working_dir).mkdir(parents=True,
> >>>>>>> exist_ok=True)
> >>>>>>> + except OSError as e:
> >>>>>>> + raise UncrustifyInputFileCreationErrorException(
> >>>>>>> + f"Error creating plugin directory
> >>>>>>> {self._working_dir}.\n\n{repr(e)}.")
> >>>>>>> +
> >>>>>>> + def _create_uncrustify_file_list_file(self) -> None:
> >>>>>>> + """
> >>>>>>> + Creates the file with the list of source files for
> >>>>>>> Uncrustify to process.
> >>>>>>> + """
> >>>>>>> + self._app_input_file_path = os.path.join(
> >>>>>>> + self._working_dir, "uncrustify_file_list.txt")
> >>>>>>> +
> >>>>>>> + with open(self._app_input_file_path, 'w',
> >>>>>>> encoding='utf8') as f:
> >>>>>>> +
> >>>>>>> f.writelines(f"\n".join(self._abs_file_paths_to_format))
> >>>>>>> +
> >>>>>>> + def _execute_uncrustify(self) -> None:
> >>>>>>> + """
> >>>>>>> + Executes Uncrustify with the initialized configuration.
> >>>>>>> + """
> >>>>>>> + output = StringIO()
> >>>>>>> + self._app_exit_code = RunCmd(
> >>>>>>> + self._app_path,
> >>>>>>> + f"-c {self._app_config_file} -F
> >>>>>>> {self._app_input_file_path} --if-changed --suffix
> >>>>>>> {UncrustifyCheck.FORMATTED_FILE_EXTENSION}", outstream=output)
> >>>>>>> + self._app_output = output.getvalue().strip().splitlines()
> >>>>>>> +
> >>>>>>> + def _get_git_ignored_paths(self) -> List[str]:
> >>>>>>> + """"
> >>>>>>> + Returns a list of file absolute path strings to all
> >>>>>>> files ignored in this git repository.
> >>>>>>> +
> >>>>>>> + If git is not found, an empty list will be returned.
> >>>>>>> + """
> >>>>>>> + if not shutil.which("git"):
> >>>>>>> + logging.warn(
> >>>>>>> + "Git is not found on this system. Git submodule
> >>>>>>> paths will not be considered.")
> >>>>>>> + return []
> >>>>>>> +
> >>>>>>> + outstream_buffer = StringIO()
> >>>>>>> + exit_code = RunCmd("git", "ls-files --other",
> >>>>>>> + workingdir=self._abs_workspace_path,
> >>>>>>> outstream=outstream_buffer,
> >>>>> logging_level=logging.NOTSET)
> >>>>>>> + if (exit_code != 0):
> >>>>>>> + raise UncrustifyGitIgnoreFileException(
> >>>>>>> + f"An error occurred reading git ignore settings.
> >>>>>>> This will prevent Uncrustify from running against
> >>>> the
> >>>>>>> expected set of files.")
> >>>>>>> +
> >>>>>>> + # Note: This will potentially be a large list, but at
> >>>>>>> least sorted
> >>>>>>> + return outstream_buffer.getvalue().strip().splitlines()
> >>>>>>> +
> >>>>>>> + def _get_git_submodule_paths(self) -> List[str]:
> >>>>>>> + """
> >>>>>>> + Returns a list of directory absolute path strings to the
> >>>>>>> root of each submodule in the workspace
> >>> repository.
> >>>>>>> +
> >>>>>>> + If git is not found, an empty list will be returned.
> >>>>>>> + """
> >>>>>>> + if not shutil.which("git"):
> >>>>>>> + logging.warn(
> >>>>>>> + "Git is not found on this system. Git submodule
> >>>>>>> paths will not be considered.")
> >>>>>>> + return []
> >>>>>>> +
> >>>>>>> + if os.path.isfile(os.path.join(self._abs_workspace_path,
> >>>>>>> ".gitmodules")):
> >>>>>>> + logging.info(
> >>>>>>> + f".gitmodules file found. Excluding submodules
> >>>>>>> in {self._package_name}.")
> >>>>>>> +
> >>>>>>> + outstream_buffer = StringIO()
> >>>>>>> + exit_code = RunCmd("git", "config --file .gitmodules
> >>>>>>> --get-regexp path",
> >>>>> workingdir=self._abs_workspace_path,
> >>>>>>> outstream=outstream_buffer, logging_level=logging.NOTSET)
> >>>>>>> + if (exit_code != 0):
> >>>>>>> + raise UncrustifyGitSubmoduleException(
> >>>>>>> + f".gitmodule file detected but an error
> >>>>>>> occurred reading the file. Cannot proceed with unknown
> >>>>>>> submodule paths.")
> >>>>>>> +
> >>>>>>> + submodule_paths = []
> >>>>>>> + for line in
> >>>>>>> outstream_buffer.getvalue().strip().splitlines():
> >>>>>>> + submodule_paths.append(
> >>>>>>> +
> >>>>>>> os.path.normpath(os.path.join(self._abs_workspace_path,
> >>>>>>> line.split()[1])))
> >>>>>>> +
> >>>>>>> + return submodule_paths
> >>>>>>> + else:
> >>>>>>> + return []
> >>>>>>> +
> >>>>>>> + def _get_template_file_contents(self) -> None:
> >>>>>>> + """
> >>>>>>> + Gets the contents of Uncrustify template files if they
> >>>>>>> are specified
> >>>>>>> + in the Uncrustify configuration file.
> >>>>>>> + """
> >>>>>>> +
> >>>>>>> + self._file_template_contents = None
> >>>>>>> + self._func_template_contents = None
> >>>>>>> +
> >>>>>>> + # Allow no value to allow "set" statements in the config
> >>>>>>> file which do
> >>>>>>> + # not specify value assignment
> >>>>>>> + parser = configparser.ConfigParser(allow_no_value=True)
> >>>>>>> + with open(self._app_config_file, 'r') as cf:
> >>>>>>> + parser.read_string("[dummy_section]\n" + cf.read())
> >>>>>>> +
> >>>>>>> + try:
> >>>>>>> + file_template_name =
> >>>>>>> parser["dummy_section"]["cmt_insert_file_header"]
> >>>>>>> +
> >>>>>>> + file_template_path = pathlib.Path(file_template_name)
> >>>>>>> +
> >>>>>>> + if not file_template_path.is_file():
> >>>>>>> + file_template_path =
> >>>>>>> pathlib.Path(os.path.join(self._plugin_path, file_template_name))
> >>>>>>> + self._file_template_contents =
> >>>>>>> file_template_path.read_text()
> >>>>>>> + except KeyError:
> >>>>>>> + logging.warn("A file header template is not
> >>>>>>> specified in the config file.")
> >>>>>>> + except FileNotFoundError:
> >>>>>>> + logging.warn("The specified file header template
> >>>>>>> file was not found.")
> >>>>>>> + try:
> >>>>>>> + func_template_name =
> >>>>>>> parser["dummy_section"]["cmt_insert_func_header"]
> >>>>>>> +
> >>>>>>> + func_template_path = pathlib.Path(func_template_name)
> >>>>>>> +
> >>>>>>> + if not func_template_path.is_file():
> >>>>>>> + func_template_path =
> >>>>>>> pathlib.Path(os.path.join(self._plugin_path, func_template_name))
> >>>>>>> + self._func_template_contents =
> >>>>>>> func_template_path.read_text()
> >>>>>>> + except KeyError:
> >>>>>>> + logging.warn("A function header template is not
> >>>>>>> specified in the config file.")
> >>>>>>> + except FileNotFoundError:
> >>>>>>> + logging.warn("The specified function header template
> >>>>>>> file was not found.")
> >>>>>>> +
> >>>>>>> + def _initialize_app_info(self) -> None:
> >>>>>>> + """
> >>>>>>> + Initialize Uncrustify application information.
> >>>>>>> +
> >>>>>>> + This function will determine the application path and
> >>>>>>> version.
> >>>>>>> + """
> >>>>>>> + # Verify Uncrustify is specified in the environment.
> >>>>>>> + if UncrustifyCheck.UNCRUSTIFY_PATH_ENV_KEY not in
> >>>>>>> os.environ:
> >>>>>>> + raise UncrustifyAppEnvVarNotFoundException(
> >>>>>>> + f"Uncrustify environment variable
> >>>>>>> {UncrustifyCheck.UNCRUSTIFY_PATH_ENV_KEY} is not present.")
> >>>>>>> +
> >>>>>>> + self._app_path = shutil.which('uncrustify',
> >>>>>>> path=os.environ[UncrustifyCheck.UNCRUSTIFY_PATH_ENV_KEY])
> >>>>>>> +
> >>>>>>> + if self._app_path is None:
> >>>>>>> + raise FileNotFoundError(
> >>>>>>> + errno.ENOENT, os.strerror(errno.ENOENT),
> >>>>>>> self._app_path)
> >>>>>>> +
> >>>>>>> + self._app_path =
> >>>>>>> os.path.normcase(os.path.normpath(self._app_path))
> >>>>>>> +
> >>>>>>> + if not os.path.isfile(self._app_path):
> >>>>>>> + raise FileNotFoundError(
> >>>>>>> + errno.ENOENT, os.strerror(errno.ENOENT),
> >>>>>>> self._app_path)
> >>>>>>> +
> >>>>>>> + # Verify Uncrustify is present at the expected path.
> >>>>>>> + return_buffer = StringIO()
> >>>>>>> + ret = RunCmd(self._app_path, "--version",
> >>>>>>> outstream=return_buffer)
> >>>>>>> + if (ret != 0):
> >>>>>>> + raise UncrustifyAppVersionErrorException(
> >>>>>>> + f"Error occurred executing --version: {ret}.")
> >>>>>>> +
> >>>>>>> + # Log Uncrustify version information.
> >>>>>>> + self._app_version = return_buffer.getvalue().strip()
> >>>>>>> + self._tc.LogStdOut(f"Uncrustify version:
> >>>>>>> {self._app_version}")
> >>>>>>> + version_aggregator.GetVersionAggregator().ReportVersion(
> >>>>>>> + "Uncrustify", self._app_version,
> >>>>>>> version_aggregator.VersionTypes.INFO)
> >>>>>>> +
> >>>>>>> + def _initialize_config_file_info(self) -> None:
> >>>>>>> + """
> >>>>>>> + Initialize Uncrustify configuration file info.
> >>>>>>> +
> >>>>>>> + The config file path is relative to the package root.
> >>>>>>> + """
> >>>>>>> + self._app_config_file =
> >>>>>>> UncrustifyCheck.DEFAULT_CONFIG_FILE_PATH
> >>>>>>> + if "ConfigFilePath" in self._package_config:
> >>>>>>> + self._app_config_file =
> >>>>>>> self._package_config["ConfigFilePath"].strip()
> >>>>>>> +
> >>>>>>> + self._app_config_file = os.path.normpath(
> >>>>>>> + os.path.join(self._abs_package_path,
> >>>>>>> self._app_config_file))
> >>>>>>> +
> >>>>>>> + if not os.path.isfile(self._app_config_file):
> >>>>>>> + raise FileNotFoundError(
> >>>>>>> + errno.ENOENT, os.strerror(errno.ENOENT),
> >>>>>>> self._app_config_file)
> >>>>>>> +
> >>>>>>> + def _initialize_environment_info(self, package_rel_path:
> >>>>>>> str, edk2_path: Edk2Path, package_config: Dict[str,
> >>>>>>> List[str]], tc: JunitReportTestCase) -> None:
> >>>>>>> + """
> >>>>>>> + Initializes plugin environment information.
> >>>>>>> + """
> >>>>>>> + self._abs_package_path =
> >>>>>>> edk2_path.GetAbsolutePathOnThisSytemFromEdk2RelativePath(
> >>>>>>> + package_rel_path)
> >>>>>>> + self._abs_workspace_path = edk2_path.WorkspacePath
> >>>>>>> + self._package_config = package_config
> >>>>>>> + self._package_name = os.path.basename(
> >>>>>>> + os.path.normpath(package_rel_path))
> >>>>>>> + self._plugin_name = self.__class__.__name__
> >>>>>>> + self._plugin_path =
> >>>>>>> os.path.dirname(os.path.realpath(__file__))
> >>>>>>> + self._rel_package_path = package_rel_path
> >>>>>>> + self._tc = tc
> >>>>>>> +
> >>>>>>> + def _initialize_file_to_format_info(self) -> None:
> >>>>>>> + """
> >>>>>>> + Forms the list of source files for Uncrustify to process.
> >>>>>>> + """
> >>>>>>> + # Create a list of all the package relative file paths
> >>>>>>> in the package to run against Uncrustify.
> >>>>>>> + rel_file_paths_to_format = list(
> >>>>>>> + UncrustifyCheck.STANDARD_PLUGIN_DEFINED_PATHS)
> >>>>>>> +
> >>>>>>> + # Allow the ci.yaml to remove any of the pre-defined
> >>>>>>> standard paths
> >>>>>>> + if "IgnoreStandardPaths" in self._package_config:
> >>>>>>> + for a in self._package_config["IgnoreStandardPaths"]:
> >>>>>>> + if a.strip() in rel_file_paths_to_format:
> >>>>>>> + self._tc.LogStdOut(
> >>>>>>> + f"Ignoring standard path due to ci.yaml
> >>>>>>> ignore: {a}")
> >>>>>>> + rel_file_paths_to_format.remove(a.strip())
> >>>>>>> + else:
> >>>>>>> + raise
> >>>>>>> UncrustifyInvalidIgnoreStandardPathsException(f"Invalid
> >>>>>>> IgnoreStandardPaths value: {a}")
> >>>>>>> +
> >>>>>>> + # Allow the ci.yaml to specify additional include paths
> >>>>>>> for this package
> >>>>>>> + if "AdditionalIncludePaths" in self._package_config:
> >>>>>>> + rel_file_paths_to_format.extend(
> >>>>>>> + self._package_config["AdditionalIncludePaths"])
> >>>>>>> +
> >>>>>>> + self._abs_file_paths_to_format = []
> >>>>>>> + for path in rel_file_paths_to_format:
> >>>>>>> + self._abs_file_paths_to_format.extend(
> >>>>>>> + [str(path.resolve()) for path in
> >>>>>>> pathlib.Path(self._abs_package_path).rglob(path)])
> >>>>>>> +
> >>>>>>> + if not "SkipGitExclusions" in self._package_config or
> >>>>>>> not self._package_config["SkipGitExclusions"]:
> >>>>>>> + # Remove files ignored by git
> >>>>>>> + logging.info(
> >>>>>>> + f"{self._package_name} file count before git
> >>>>>>> ignore file exclusion:
> >>>>>>> {len(self._abs_file_paths_to_format)}")
> >>>>>>> +
> >>>>>>> + ignored_paths = self._get_git_ignored_paths()
> >>>>>>> + self._abs_file_paths_to_format = list(
> >>>>>>> +
> >>>>>>> set(self._abs_file_paths_to_format).difference(ignored_paths))
> >>>>>>> +
> >>>>>>> + logging.info(
> >>>>>>> + f"{self._package_name} file count after git
> >>>>>>> ignore file exclusion:
> >>>>>>> {len(self._abs_file_paths_to_format)}")
> >>>>>>> +
> >>>>>>> + # Remove files in submodules
> >>>>>>> + logging.info(
> >>>>>>> + f"{self._package_name} file count before
> >>>>>>> submodule exclusion:
> >>>> {len(self._abs_file_paths_to_format)}")
> >>>>>>> +
> >>>>>>> + submodule_paths =
> >>>>>>> tuple(self._get_git_submodule_paths())
> >>>>>>> + for path in submodule_paths:
> >>>>>>> + logging.info(f" submodule path: {path}")
> >>>>>>> +
> >>>>>>> + self._abs_file_paths_to_format = [
> >>>>>>> + f for f in self._abs_file_paths_to_format if not
> >>>>>>> f.startswith(submodule_paths)]
> >>>>>>> +
> >>>>>>> + logging.info(
> >>>>>>> + f"{self._package_name} file count after
> >>>>>>> submodule exclusion:
> >>> {len(self._abs_file_paths_to_format)}")
> >>>>>>> +
> >>>>>>> + # Sort the files for more consistent results
> >>>>>>> + self._abs_file_paths_to_format.sort()
> >>>>>>> +
> >>>>>>> + def _initialize_test_case_output_options(self) -> None:
> >>>>>>> + """
> >>>>>>> + Initializes options that influence test case output.
> >>>>>>> + """
> >>>>>>> + self._audit_only_mode = False
> >>>>>>> + self._output_file_diffs = False
> >>>>>>> +
> >>>>>>> + if "AuditOnly" in self._package_config and
> >>>>>>> self._package_config["AuditOnly"]:
> >>>>>>> + self._audit_only_mode = True
> >>>>>>> +
> >>>>>>> + if "OutputFileDiffs" in self._package_config and
> >>>>>>> self._package_config["OutputFileDiffs"]:
> >>>>>>> + self._output_file_diffs = True
> >>>>>>> +
> >>>>>>> + def _log_uncrustify_app_info(self) -> None:
> >>>>>>> + """
> >>>>>>> + Logs Uncrustify application information.
> >>>>>>> + """
> >>>>>>> + self._tc.LogStdOut(f"Found Uncrustify at {self._app_path}")
> >>>>>>> + self._tc.LogStdOut(f"Uncrustify version:
> >>>>>>> {self._app_version}")
> >>>>>>> + self._tc.LogStdOut('\n')
> >>>>>>> + logging.info(f"Found Uncrustify at {self._app_path}")
> >>>>>>> + logging.info(f"Uncrustify version: {self._app_version}")
> >>>>>>> + logging.info('\n')
> >>>>>>> +
> >>>>>>> + def _process_uncrustify_results(self) -> None:
> >>>>>>> + """
> >>>>>>> + Process the results from Uncrustify.
> >>>>>>> +
> >>>>>>> + Determines whether formatting errors are present and
> >>>>>>> logs failures.
> >>>>>>> + """
> >>>>>>> + formatted_files = [str(path.resolve()) for path in
> >>>>>>> pathlib.Path(
> >>>>>>> +
> >>>>>>> self._abs_package_path).rglob(f'*{UncrustifyCheck.FORMATTED_FILE_EXTENSION}')]
> >>>>>>>
> >>>>>>> +
> >>>>>>> + self._formatted_file_error_count = len(formatted_files)
> >>>>>>> +
> >>>>>>> + if self._formatted_file_error_count > 0:
> >>>>>>> + self._tc.LogStdError("Files with formatting errors:\n")
> >>>>>>> +
> >>>>>>> + if self._output_file_diffs:
> >>>>>>> + logging.info("Calculating file diffs. This might
> >>>>>>> take a while...")
> >>>>>>> +
> >>>>>>> + for formatted_file in formatted_files:
> >>>>>>> + pre_formatted_file = formatted_file[:-
> >>>>>>> +
> >>>>>>> len(UncrustifyCheck.FORMATTED_FILE_EXTENSION)]
> >>>>>>> +
> >>>>>>> + if (self._output_file_diffs or
> >>>>>>> + self._file_template_contents is not None or
> >>>>>>> + self._func_template_contents is not None):
> >>>>>>> + self._tc.LogStdError(
> >>>>>>> + f"Formatting errors in
> >>>>>>> {os.path.relpath(pre_formatted_file, self._abs_package_path)}\n")
> >>>>>>> +
> >>>>>>> + with open(formatted_file) as ff:
> >>>>>>> + formatted_file_text = ff.read()
> >>>>>>> +
> >>>>>>> + if (self._file_template_contents is not None
> >>>>>>> and
> >>>>>>> + self._file_template_contents in
> >>>>>>> formatted_file_text):
> >>>>>>> + self._tc.LogStdError(f"File header is
> >>>>>>> missing in {os.path.relpath(pre_formatted_file,
> >>>>>>> self._abs_package_path)}\n")
> >>>>>>> +
> >>>>>>> + if (self._func_template_contents is not None
> >>>>>>> and
> >>>>>>> + self._func_template_contents in
> >>>>>>> formatted_file_text):
> >>>>>>> + self._tc.LogStdError(f"A function header
> >>>>>>> is missing in
> >>> {os.path.relpath(pre_formatted_file,
> >>>>>>> self._abs_package_path)}\n")
> >>>>>>> +
> >>>>>>> + if self._output_file_diffs:
> >>>>>>> + with open(pre_formatted_file) as pf:
> >>>>>>> + pre_formatted_file_text = pf.read()
> >>>>>>> +
> >>>>>>> + for line in
> >>>>>>> difflib.unified_diff(pre_formatted_file_text.split('\n'),
> >>>>>>> formatted_file_text.split('\n'), fromfile=pre_formatted_file,
> >>>>>>> tofile=formatted_file, n=3):
> >>>>>>> + self._tc.LogStdError(line)
> >>>>>>> +
> >>>>>>> + self._tc.LogStdError('\n')
> >>>>>>> + else:
> >>>>>>> + self._tc.LogStdError(pre_formatted_file)
> >>>>>>> +
> >>>>>>> + def _remove_tree(self, dir_path: str, ignore_errors: bool =
> >>>>>>> False) -> None:
> >>>>>>> + """
> >>>>>>> + Helper for removing a directory. Over time there have been
> >>>>>>> + many private implementations of this due to reliability
> >>>>>>> issues in the
> >>>>>>> + shutil implementations. To consolidate on a single
> >>>>>>> function this helper is added.
> >>>>>>> +
> >>>>>>> + On error try to change file attributes. Also add retry
> >>>>>>> logic.
> >>>>>>> +
> >>>>>>> + This function is temporarily borrowed from
> >>>>>>> edk2toollib.utility_functions
> >>>>>>> + since the version used in edk2 is not recent enough to
> >>>>>>> include the
> >>>>>>> + function.
> >>>>>>> +
> >>>>>>> + This function should be replaced by "RemoveTree" when it
> >>>>>>> is available.
> >>>>>>> +
> >>>>>>> + Args:
> >>>>>>> + - dir_path: Path to directory to remove.
> >>>>>>> + - ignore_errors: Whether to ignore errors during removal
> >>>>>>> + """
> >>>>>>> +
> >>>>>>> + def _remove_readonly(func, path, _):
> >>>>>>> + """
> >>>>>>> + Private function to attempt to change permissions on
> >>>>>>> file/folder being deleted.
> >>>>>>> + """
> >>>>>>> + os.chmod(path, os.stat.S_IWRITE)
> >>>>>>> + func(path)
> >>>>>>> +
> >>>>>>> + for _ in range(3): # retry up to 3 times
> >>>>>>> + try:
> >>>>>>> + shutil.rmtree(dir_path,
> >>>>>>> ignore_errors=ignore_errors, onerror=_remove_readonly)
> >>>>>>> + except OSError as err:
> >>>>>>> + logging.warning(f"Failed to fully remove
> >>>>>>> {dir_path}: {err}")
> >>>>>>> + else:
> >>>>>>> + break
> >>>>>>> + else:
> >>>>>>> + raise RuntimeError(f"Failed to remove {dir_path}")
> >>>>>>> +
> >>>>>>> + def _run_uncrustify(self) -> None:
> >>>>>>> + """
> >>>>>>> + Runs Uncrustify for this instance of plugin execution.
> >>>>>>> + """
> >>>>>>> + logging.info("Executing Uncrustify. This might take a
> >>>>>>> while...")
> >>>>>>> + start_time = timeit.default_timer()
> >>>>>>> + self._execute_uncrustify()
> >>>>>>> + end_time = timeit.default_timer() - start_time
> >>>>>>> +
> >>>>>>> + execution_summary = f"Uncrustify executed against
> >>>>>>> {len(self._abs_file_paths_to_format)} files in
> >>>>>>> {self._package_name} in {end_time:.2f} seconds.\n"
> >>>>>>> +
> >>>>>>> + self._tc.LogStdOut(execution_summary)
> >>>>>>> + logging.info(execution_summary)
> >>>>>>> +
> >>>>>>> + if self._app_exit_code != 0 and self._app_exit_code != 1:
> >>>>>>> + raise UncrustifyAppExecutionException(
> >>>>>>> + f"Error {str(self._app_exit_code)} returned from
> >>>>>>> Uncrustify:\n\n{str(self._app_output)}")
> >>>>>>> diff --git a/.pytool/Plugin/UncrustifyCheck/default_file_header.txt
> >>>>>>> b/.pytool/Plugin/UncrustifyCheck/default_file_header.txt
> >>>>>>> new file mode 100644
> >>>>>>> index 000000000000..2955a734dfe1
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/.pytool/Plugin/UncrustifyCheck/default_file_header.txt
> >>>>>>> @@ -0,0 +1,9 @@
> >>>>>>> +/** @file
> >>>>>>> + Brief description of the file's purpose.
> >>>>>>> +
> >>>>>>> + Detailed description of the file's contents and other useful
> >>>>>>> + information for a person viewing the file for the first time.
> >>>>>>> +
> >>>>>>> + <<Copyright>>
> >>>>>>> + SPDX-License-Identifier: BSD-2-Clause-Patent
> >>>>>>> +**/
> >>>>>>> diff --git
> >>>>>>> a/.pytool/Plugin/UncrustifyCheck/default_function_header.txt
> >>>>>>> b/.pytool/Plugin/UncrustifyCheck/default_function_header.txt
> >>>>>>> new file mode 100644
> >>>>>>> index 000000000000..66edc72e6731
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/.pytool/Plugin/UncrustifyCheck/default_function_header.txt
> >>>>>>> @@ -0,0 +1,15 @@
> >>>>>>> +/**
> >>>>>>> + Brief description of this function's purpose.
> >>>>>>> +
> >>>>>>> + Follow it immediately with the detailed description.
> >>>>>>> +
> >>>>>>> + @param[in] Arg1 Description of Arg1.
> >>>>>>> + @param[in] Arg2 Description of Arg2 This is complicated
> >>>>>>> and requires
> >>>>>>> + multiple lines to describe.
> >>>>>>> + @param[out] Arg3 Description of Arg3.
> >>>>>>> + @param[in, out] Arg4 Description of Arg4.
> >>>>>>> +
> >>>>>>> + @retval VAL_ONE Description of what VAL_ONE signifies.
> >>>>>>> + @retval OTHER This is the only other return value. If there
> >>>>>>> were other
> >>>>>>> + return values, they would be listed.
> >>>>>>> +**/
> >>>>>>> diff --git a/.pytool/Plugin/UncrustifyCheck/uncrustify.cfg
> >>>>>>> b/.pytool/Plugin/UncrustifyCheck/uncrustify.cfg
> >>>>>>> new file mode 100644
> >>>>>>> index 000000000000..1a87295ec9f9
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/.pytool/Plugin/UncrustifyCheck/uncrustify.cfg
> >>>>>>> @@ -0,0 +1,462 @@
> >>>>>>> +## @file
> >>>>>>> +# Uncrustify Configuration File for EDK II C Code
> >>>>>>> +#
> >>>>>>> +# Coding Standard:
> >>>>>>> https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/
> >>>>>>>
> >>>>>>> +#
> >>>>>>> +# This configuration file is meant to be a "best attempt" to
> >>>>>>> align with the
> >>>>>>> +# definitions in the EDK II C Coding Standards Specification.
> >>>>>>> +#
> >>>>>>> +# Copyright (c) Microsoft Corporation.
> >>>>>>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> >>>>>>> +##
> >>>>>>> +
> >>>>>>> +# Force UTF-8 encoding (no UTF-16)
> >>>>>>> +enable_digraphs = false
> >>>>>>> +utf8_byte = false
> >>>>>>> +utf8_force = true
> >>>>>>> +
> >>>>>>> +# Code width / line splitting
> >>>>>>> +#code_width =120 # TODO: This causes
> >>>>>>> non-deterministic behaviour in some cases when code
> >>>>> wraps
> >>>>>>> +ls_code_width =false
> >>>>>>> +ls_for_split_full =true
> >>>>>>> +ls_func_split_full =true
> >>>>>>> +pos_comma =trail
> >>>>>>> +
> >>>>>>> +# 5.1.7 All files must end with CRLF
> >>>>>>> +newlines = crlf
> >>>>>>> +
> >>>>>>> +# 5.1.2 Do not use tab characters
> >>>>>>> +
> >>>>>>> +cmt_convert_tab_to_spaces = true # Whether to convert
> >>>>>>> all tabs to spaces in comments. If false, tabs in
> >>>>>>> + # comments are left
> >>>>>>> alone, unless used for indenting.
> >>>>>>> +indent_columns = 2 # Number of spaces
> >>>>>>> for indentation
> >>>>>>> +indent_with_tabs = 0 # Do not use TAB
> >>>>>>> characters
> >>>>>>> +string_replace_tab_chars = true # Replace TAB with
> >>>>>>> SPACE
> >>>>>>> + # Note: This will
> >>>>>>> break .robot files but is needed for edk2 style
> >>>>>>> +
> >>>>>>> +# 5.2.1.1 There shall be only one statement on a line (statement
> >>>>>>> ends with ;)
> >>>>>>> +nl_multi_line_cond = true # Add a newline
> >>>>>>> between ')' and '{' if the ')' is on a different line
> >>>> than
> >>>>>>> + # the if/for/etc.
> >>>>>>> +nl_after_semicolon = true # Whether to add a
> >>>>>>> newline after semicolons, except in 'for'
> >>> statements.
> >>>>>>> +
> >>>>>>> +# 5.2.1.3 An open brace '{' goes on the same line as the closing
> >>>>>>> parenthesis ')' of simple predicate expressions
> >>>>>>> +mod_full_brace_do = add # Add or remove
> >>>>>>> braces on a single-line 'do' statement.
> >>>>>>> +mod_full_brace_for = add
> >>>>>>> +mod_full_brace_function = add # Add or remove
> >>>>>>> braces on a single-line function definition.
> >>>>>>> +mod_full_brace_if = add # Add or remove
> >>>>>>> braces on a single-line 'if' statement. Braces will
> >>> not
> >>>> be
> >>>>>>> + # removed if the
> >>>>>>> braced statement contains an 'else'.
> >>>>>>> +mod_full_brace_if_chain = false
> >>>>>>> +mod_full_brace_while = add
> >>>>>>> +
> >>>>>>> +# 5.2.1.4 A close brace '}' always goes at the beginning of the
> >>>>>>> last line of the body
> >>>>>>> +eat_blanks_after_open_brace = true
> >>>>>>> +eat_blanks_before_close_brace = true # Whether to remove
> >>>>>>> blank lines before '}'.
> >>>>>>> +
> >>>>>>> +# 5.2.2.2 Always put space before and after binary operators.
> >>>>>>> +sp_assign = add # Add or remove
> >>>>>>> space around assignment operator '=', '+=', etc.
> >>>>>>> +sp_assign_default = add
> >>>>>>> +sp_bool = add # Add or remove
> >>>>>>> space around boolean operators '&&' and '||'.
> >>>>>>> +sp_compare = add # Add or remove
> >>>>>>> space around compare operator '<', '>', '==', etc.
> >>>>>>> +
> >>>>>>> +# 5.2.2.3 Do not put space between unary operators and their object
> >>>>>>> +sp_addr = remove # A or remove space
> >>>>>>> after the '&' (address-of) unary operator.
> >>>>>>> +sp_incdec = remove # Add or remove
> >>>>>>> space between '++' and '--' the word to which it is
> >>>> being
> >>>>>>> + # applied, as in
> >>>>>>> '(--x)' or 'y++;'.
> >>>>>>> +sp_inv = remove # Add or remove
> >>>>>>> space after the '~' (invert) unary operator.
> >>>>>>> +sp_not = remove # Add or remove
> >>>>>>> space after the '!' (not) unary operator.
> >>>>>>> +sp_sign = remove # Add or remove
> >>>>>>> space after '+' or '-', as in 'x = -5' or 'y = +7'.
> >>>>>>> +
> >>>>>>> +# 5.2.2.4 Subsequent lines of multi-line function calls should
> >>>>>>> line up two spaces from the beginning of the
> >>> function
> >>>>>>> +# name
> >>>>>>> +nl_func_call_args_multi_line = true # Whether to add a
> >>>>>>> newline after each ',' in a function call if '('
> >>> and
> >>>>> ')'
> >>>>>>> + # are in different
> >>>>>>> lines.
> >>>>>>> +nl_func_call_args_multi_line_ignore_closures = false
> >>>>>>> +
> >>>>>>> +# - Indent each argument 2 spaces from the start of the function
> >>>>>>> name. If a
> >>>>>>> +# function is called through a structure or union member, of type
> >>>>>>> +# pointer-to-function, then indent each argument 2 spaces from
> >>>>>>> the start of the
> >>>>>>> +# member name.
> >>>>>>> +indent_func_call_edk2_style = true # Use EDK2
> >>>>>>> indentation style for function calls (**CUSTOM SETTING**)
> >>>>>>> +indent_paren_after_func_call = true # Whether to indent
> >>>>>>> the open parenthesis of a function call, if the
> >>>>>>> + # parenthesis is on
> >>>>>>> its own line.
> >>>>>>> +
> >>>>>>> +# - Align the close parenthesis with the start of the last argument
> >>>>>>> +indent_paren_close = 0 # How to indent a
> >>>>>>> close parenthesis after a newline.
> >>>>>>> + # (0: Body, 1:
> >>>>>>> Openparenthesis, 2: Brace level)
> >>>>>>> +
> >>>>>>> +
> >>>>>>> +# 5.2.2.5 Always put space after commas or semicolons that
> >>>>>>> separate items
> >>>>>>> +sp_after_comma = force # Add or remove
> >>>>>>> space after ',', i.e. 'a,b' vs. 'a, b'.
> >>>>>>> +sp_before_comma = remove # Add or remove
> >>>>>>> space before ','.
> >>>>>>> +
> >>>>>>> +# 5.2.2.6 Always put space before an open parenthesis
> >>>>>>> +sp_after_sparen = add # Add or remove
> >>>>>>> space after ')' of control statements.
> >>>>>>> +sp_attribute_paren = add # Add or remove
> >>>>>>> space between '__attribute__' and '('.
> >>>>>>> +sp_before_sparen = force # Add or remove
> >>>>>>> space before '(' of control statements
> >>>>>>> + # ('if', 'for',
> >>>>>>> 'switch', 'while', etc.).
> >>>>>>> +sp_defined_paren = force # Add or remove
> >>>>>>> space between 'defined' and '(' in '#if defined
> >>> (FOO)'.
> >>>>>>> +sp_func_call_paren = force # Add or remove
> >>>>>>> space between function name and '(' on function calls.
> >>>>>>> +sp_func_call_paren_empty = force # Add or remove
> >>>>>>> space between function name and '()' on function calls
> >>>>>>> + # without
> >>>>>>> parameters. If set to ignore (the default),
> >>> sp_func_call_paren
> >>>>> is
> >>>>>>> + # used.
> >>>>>>> +sp_func_def_paren = add # Add or remove
> >>>>>>> space between alias name and '(' of a non-pointer
> >>>> function
> >>>>>>> + # type typedef.
> >>>>>>> +sp_func_proto_paren = add # Add or remove
> >>>>>>> space between function name and '()' on function
> >>>>> declaration
> >>>>>>> +sp_sizeof_paren = force # Add or remove
> >>>>>>> space between 'sizeof' and '('.
> >>>>>>> +sp_type_func = add # Add or remove
> >>>>>>> space between return type and function name. A minimum
> >>>> of
> >>>>> 1
> >>>>>>> + # is forced except
> >>>>>>> for pointer return types.
> >>>>>>> +
> >>>>>>> +# Not specified, but also good style to remove spaces inside
> >>>>>>> parentheses (Optional)
> >>>>>>> +sp_cparen_oparen = remove # Add or remove
> >>>>>>> space between back-to-back parentheses, i.e. ')(' vs.
> >>> ')
> >>>>> ('.
> >>>>>>> +sp_inside_fparen = remove # Add or remove
> >>>>>>> space inside function '(' and ')'.
> >>>>>>> +sp_inside_fparens = remove # Add or remove
> >>>>>>> space inside empty function '()'.
> >>>>>>> +sp_inside_paren = remove # Add or remove
> >>>>>>> space inside '(' and ')'.
> >>>>>>> +sp_inside_paren_cast = remove # Add or remove
> >>>>>>> spaces inside cast parentheses. '(int)x'
> >>>>>>> +sp_inside_square = remove # Add or remove
> >>>>>>> space inside a non-empty '[' and ']'.
> >>>>>>> +sp_paren_paren = remove # Add or remove
> >>>>>>> space between nested parentheses, i.e. '((' vs. ') )'.
> >>>>>>> +sp_square_fparen = remove # Add or remove
> >>>>>>> space between ']' and '(' when part of a function
> >>> call.
> >>>>>>> +
> >>>>>>> +# 5.2.2.7 Put a space before an open brace if it is not on its
> >>>>>>> own line
> >>>>>>> +sp_do_brace_open = force # Add or remove
> >>>>>>> space between 'do' and '{'.
> >>>>>>> +sp_paren_brace = force # Add or remove
> >>>>>>> space between ')' and '{'.
> >>>>>>> +sp_sparen_brace = force # Add or remove
> >>>>>>> space between ')' and '{' of of control statements.
> >>>>>>> +
> >>>>>>> +# 5.2.2.8 Do not put spaces around structure member and pointer
> >>>>>>> operators
> >>>>>>> +sp_after_byref = remove # Add or remove
> >>>>>>> space after reference sign '&', if followed by a word.
> >>>>>>> +sp_before_byref = add # Add or remove
> >>>>>>> space before a reference sign '&'.
> >>>>>>> +sp_deref = remove # Add or remove
> >>>>>>> space after the '*' (dereference) unary operator. This
> >>>>> does
> >>>>>>> + # not affect the
> >>>>>>> spacing after a '*' that is part of a type.
> >>>>>>> +sp_member = remove # Add or remove
> >>>>>>> space around the '.' or '->' operators.
> >>>>>>> +
> >>>>>>> +# 5.2.2.9 Do not put spaces before open brackets of array
> >>>>>>> subscripts
> >>>>>>> +sp_before_square = remove # Add or remove
> >>>>>>> space before '[' (except '[]').
> >>>>>>> +sp_before_squares = remove # Add or remove
> >>>>>>> space before '[]'.
> >>>>>>> +sp_before_vardef_square = remove # Add or remove
> >>>>>>> space before '[' for a variable definition.
> >>>>>>> +
> >>>>>>> +# 5.2.2.10 Use extra parentheses rather than depending on
> >>>>>>> in-depth knowledge of the order of precedence of C
> >>>>>>> +mod_full_paren_if_bool = true # Whether to fully
> >>>>>>> parenthesize Boolean expressions in 'while' and
> >>> 'if'
> >>>>>>> + # statement, as in
> >>>>>>> 'if (a && b > c)' => 'if (a && (b > c))'.
> >>>>>>> +
> >>>>>>> +# 5.2.2.11 Align a continuation line with the part of the line
> >>>>>>> that it continues.
> >>>>>>> +use_indent_continue_only_once = true
> >>>>>>> +
> >>>>>>> +# Additional '{}' bracing rules (Optional)
> >>>>>>> +# NOTE - The style guide specifies two different styles for braces,
> >>>>>>> +# so these are ignored for now to allow developers some
> >>>>>>> flexibility.
> >>>>>>> +nl_after_brace_close = true # Whether to add a
> >>>>>>> newline after '}'. Does not apply if followed by a
> >>>>>>> + # necessary ';'.
> >>>>>>> +nl_brace_else = remove # Add or remove
> >>>>>>> newline between '}' and 'else'.
> >>>>>>> +nl_brace_while = remove # Add or remove
> >>>>>>> newline between '}' and 'while' of 'do' statement.
> >>>>>>> +nl_do_brace = remove # Add or remove
> >>>>>>> newline between 'do' and '{'.
> >>>>>>> +nl_else_brace = remove # Add or remove
> >>>>>>> newline between 'else' and '{'.
> >>>>>>> +nl_else_if = remove # Add or remove
> >>>>>>> newline between 'else' and 'if'.
> >>>>>>> +nl_elseif_brace = remove # Add or remove
> >>>>>>> newline between 'else if' and '{'.
> >>>>>>> +nl_enum_brace = remove # Add or remove
> >>>>>>> newline between 'enum' and '{'.
> >>>>>>> +nl_fcall_brace = remove # Add or remove
> >>>>>>> newline between a function call's ')' and '{',
> >>>>>>> + # as in
> >>>>>>> 'list_for_each(item, &list) { }'.
> >>>>>>> +nl_for_brace = remove # Add or remove
> >>>>>>> newline between 'for' and '{'.
> >>>>>>> +nl_if_brace = remove # Add or remove
> >>>>>>> newline between 'if' and '{'.
> >>>>>>> +nl_struct_brace = remove # Add or remove
> >>>>>>> newline between 'struct and '{'.
> >>>>>>> +nl_switch_brace = remove # Add or remove
> >>>>>>> newline between 'switch' and '{'.
> >>>>>>> +nl_union_brace = remove # Add or remove
> >>>>>>> newline between 'union' and '{'.
> >>>>>>> +nl_while_brace = remove # Add or remove
> >>>>>>> newline between 'while' and '{'.
> >>>>>>> +
> >>>>>>> +# Additional whitespace rules (Optional)
> >>>>>>> +sp_after_ptr_star = remove # Add or remove
> >>>>>>> space after pointer star '*', if followed by a word.
> >>>>>>> + # Useful when paired
> >>>>>>> with align_var_def_star_style==2
> >>>>>>> +sp_after_ptr_star_func = remove # Add or remove
> >>>>>>> space after a pointer star '*', if followed by a
> >>>> function
> >>>>>>> + # prototype or
> >>>>>>> function definition.
> >>>>>>> +sp_after_semi = remove # Add or remove
> >>>>>>> space after ';', except when followed by a comment.
> >>>>>>> +sp_before_case_colon = remove # Add or remove
> >>>>>>> space before case ':'.
> >>>>>>> +sp_before_ptr_star = add # Add or remove
> >>>>>>> space before pointer star '*'.
> >>>>>>> +sp_before_ptr_star_func = add # Add or remove
> >>>>>>> space before a pointer star '*', if followed by a
> >>>> function
> >>>>>>> + # prototype or
> >>>>>>> function definition.
> >>>>>>> +sp_before_semi = remove # Add or remove
> >>>>>>> space before ';'
> >>>>>>> +sp_before_semi_for = remove # Add or remove
> >>>>>>> space before ';' in non-empty 'for' statements.
> >>>>>>> +sp_before_semi_for_empty = add # Add or remove
> >>>>>>> space before a semicolon of an empty part of a for
> >>>>> statement
> >>>>>>> +sp_between_ptr_star = remove # Add or remove
> >>>>>>> space between pointer stars '*'. (ie, 'VOID **')
> >>>>>>> +sp_brace_close_while = force # Add or remove
> >>>>>>> space between '}' and 'while'.
> >>>>>>> +
> >>>>>>> +sp_after_cast = remove
> >>>>>>> +sp_after_type = add
> >>>>>>> +sp_balance_nested_parens = false
> >>>>>>> +sp_before_nl_cont = add
> >>>>>>> +sp_before_square_asm_block = ignore
> >>>>>>> +sp_before_unnamed_byref = add
> >>>>>>> +sp_brace_brace = ignore
> >>>>>>> +sp_brace_else = force
> >>>>>>> +sp_brace_typedef = add
> >>>>>>> +sp_case_label = force
> >>>>>>> +sp_cmt_cpp_doxygen = true
> >>>>>>> +sp_cond_colon = add
> >>>>>>> +sp_cond_question = add
> >>>>>>> +sp_cpp_cast_paren = force
> >>>>>>> +sp_else_brace = force
> >>>>>>> +sp_endif_cmt = force
> >>>>>>> +sp_enum_assign = add
> >>>>>>> +sp_inside_braces = force
> >>>>>>> +sp_inside_braces_empty = force
> >>>>>>> +sp_inside_braces_enum = force
> >>>>>>> +sp_inside_braces_struct = force
> >>>>>>> +sp_pp_concat = add
> >>>>>>> +sp_pp_stringify = add
> >>>>>>> +sp_return_paren = add
> >>>>>>> +sp_special_semi = force
> >>>>>>> +sp_while_paren_open = force
> >>>>>>> +
> >>>>>>> +# Additional Indentation Rules
> >>>>>>> +indent_access_spec = 1
> >>>>>>> +indent_access_spec_body = false
> >>>>>>> +indent_align_assign = true
> >>>>>>> +indent_align_string = true
> >>>>>>> +indent_bool_paren = true
> >>>>>>> +indent_brace_parent = false
> >>>>>>> +indent_braces = false
> >>>>>>> +indent_braces_no_class = false
> >>>>>>> +indent_braces_no_func = true
> >>>>>>> +indent_braces_no_struct = false
> >>>>>>> +indent_class = false
> >>>>>>> +indent_class_colon = false
> >>>>>>> +indent_cmt_with_tabs = false # Whether to
> >>>>>>> indent comments that are not at a brace level with
> >>> tabs
> >>>>> on
> >>>>>>> + # a tabstop.
> >>>>>>> Requires indent_with_tabs=2. If false, will use
> >>> spaces.
> >>>>>>> +indent_col1_comment = true
> >>>>>>> +indent_col1_multi_string_literal= true
> >>>>>>> +indent_comma_paren = true
> >>>>>>> +indent_else_if = true
> >>>>>>> +indent_extern = false
> >>>>>>> +indent_first_bool_expr = true
> >>>>>>> +
> >>>>>>> +indent_func_def_param_paren_pos_threshold = 0
> >>>>>>> +indent_func_param_double = false
> >>>>>>> +indent_func_proto_param = true
> >>>>>>> +indent_ignore_asm_block = true
> >>>>>>> +indent_label = 1
> >>>>>>> +indent_member = 2
> >>>>>>> +indent_namespace = false
> >>>>>>> +indent_param = 2
> >>>>>>> +indent_paren_nl = false
> >>>>>>> +indent_paren_open_brace = false
> >>>>>>> +indent_preserve_sql = false
> >>>>>>> +indent_relative_single_line_comments = false
> >>>>>>> +indent_sing_line_comments = 0
> >>>>>>> +indent_single_newlines = false
> >>>>>>> +indent_square_nl = false
> >>>>>>> +indent_switch_case = 2
> >>>>>>> +indent_template_param = true
> >>>>>>> +indent_var_def_blk = 0
> >>>>>>> +indent_var_def_cont = false
> >>>>>>> +
> >>>>>>> +# Tidy-up rules (Optional)
> >>>>>>> +mod_move_case_break = true # Whether to move a
> >>>>>>> 'break' that appears after a fully braced 'case'
> >>>>>>> + # before the close
> >>>>>>> brace, as in 'case X: { ... } break;' =>
> >>>>>>> + # 'case X: { ...
> >>>>>>> break; }'.
> >>>>>>> +mod_pawn_semicolon = false
> >>>>>>> +mod_remove_empty_return = false # Whether to remove
> >>>>>>> a void 'return;' that appears as the last
> >>> statement
> >>>>>>> + # in a function.
> >>>>>>> +mod_remove_extra_semicolon = true
> >>>>>>> +mod_sort_import = false
> >>>>>>> +mod_sort_include = false
> >>>>>>> +mod_sort_using = false
> >>>>>>> +nl_after_case = false # Whether to add a
> >>>>>>> newline after a 'case' statement.
> >>>>>>> +nl_end_of_file = force # Add or remove
> >>>>>>> newline at the end of the file.
> >>>>>>> +nl_end_of_file_min = 1 # The minimum number
> >>>>>>> of newlines at the end of the file
> >>>>>>> +nl_max = 2 # The maximum number
> >>>>>>> of consecutive newlines (3 = 2 blank lines).
> >>>>>>> +nl_start_of_file = remove # Add or remove
> >>>>>>> newlines at the start of the file.
> >>>>>>> +
> >>>>>>> +# Code alignment rules (Optional)
> >>>>>>> +align_asm_colon = false
> >>>>>>> +align_assign_span = 1 # The span for
> >>>>>>> aligning on '=' in assignments.
> >>>>>>> +align_assign_thresh = 4
> >>>>>>> +align_edk2_style = true # Whether to apply
> >>>>>>> edk2-specific alignment formatting
> >>>>>>> +align_enum_equ_span = 1 # The span for
> >>>>>>> aligning on '=' in enums.
> >>>>>>> +align_func_params = true # Whether to align
> >>>>>>> variable definitions in prototypes and functions.
> >>>>>>> +align_func_params_gap = 2
> >>>>>>> +align_func_params_span = 2 # The span for
> >>>>>>> aligning parameter definitions in function on parameter
> >>>>> name.
> >>>>>>> +align_func_params_thresh = 0
> >>>>>>> +align_func_proto_span = 0
> >>>>>>> +align_keep_tabs = false
> >>>>>>> +align_left_shift = false
> >>>>>>> +align_mix_var_proto = false
> >>>>>>> +align_nl_cont = false
> >>>>>>> +align_oc_decl_colon = false
> >>>>>>> +align_on_operator = false
> >>>>>>> +align_on_tabstop = false
> >>>>>>> +align_pp_define_gap = 2
> >>>>>>> +align_pp_define_span = 1
> >>>>>>> +align_right_cmt_at_col = 0 # Align trailing
> >>>>>>> comment at or beyond column N; 'pulls in' comments as
> >>>>>>> + # a bonus side
> >>>>>>> effect (0=ignore)
> >>>>>>> +align_right_cmt_gap = 0 # If a trailing
> >>>>>>> comment is more than this number of columns away from
> >>>> the
> >>>>>>> + # text it follows,
> >>>>>>> + # it will qualify
> >>>>>>> for being aligned. This has to be > 0 to do
> >>> anything.
> >>>>>>> +align_right_cmt_mix = false # If aligning
> >>>>>>> comments, mix with comments after '}' and #endif with
> >>> less
> >>>>>>> + # than 3 spaces
> >>>>>>> before the comment
> >>>>>>> +align_right_cmt_same_level = true # Whether to only
> >>>>>>> align trailing comments that are at the same brace
> >>>>> level.
> >>>>>>> +align_right_cmt_span = 2 # The span for
> >>>>>>> aligning comments that end lines.
> >>>>>>> +align_same_func_call_params = false
> >>>>>>> +align_single_line_brace = true
> >>>>>>> +align_single_line_func = true
> >>>>>>> +align_struct_init_span = 1 # The span for
> >>>>>>> aligning struct initializer values.
> >>>>>>> +align_typedef_amp_style = 1
> >>>>>>> +align_typedef_func = 1 # How to align
> >>>>>>> typedef'd functions with other typedefs.
> >>>>>>> + # (0: No align, 1:
> >>>>>>> Align open paranthesis, 2: Align function type
> >>> name)
> >>>>>>> +align_typedef_gap = 2
> >>>>>>> +align_typedef_span = 1 # The span for
> >>>>>>> aligning single-line typedefs.
> >>>>>>> +align_typedef_star_style = 1
> >>>>>>> +align_var_def_amp_style = 1
> >>>>>>> +align_var_def_attribute = true
> >>>>>>> +align_var_def_colon = true # Whether to align
> >>>>>>> the colon in struct bit fields.
> >>>>>>> +align_var_def_gap = 2 # The gap (minimum
> >>>>>>> spacing for aligned items) for variable
> >>> definitions.
> >>>>>>> +align_var_def_inline = false
> >>>>>>> +align_var_def_span = 1 # The span (lines
> >>>>>>> needed to align) for aligning variable definitions.
> >>>>>>> +align_var_def_star_style = 1 # How to consider
> >>>>>>> (or treat) the '*' in the alignment of variable
> >>>>>>> + # definitions.
> >>>>>>> + # 0: Part of the
> >>>>>>> type 'void * foo;' (default)
> >>>>>>> + # 1: Part of the
> >>>>>>> variable 'void *foo;'
> >>>>>>> + # 2:
> >>>>>>> Dangling 'void *foo;'
> >>>>>>> + # (Note - should
> >>>>>>> also set sp_after_ptr_star=remove)
> >>>>>>> +align_var_struct_gap = 4
> >>>>>>> +align_var_struct_span = 8 # The span for
> >>>>>>> aligning struct/union member definitions.
> >>>>>>> +align_var_struct_thresh = 0
> >>>>>>> +align_with_tabs = false
> >>>>>>> +
> >>>>>>> +# Comment formatting
> >>>>>>> +cmt_align_doxygen_javadoc_tags = true # Whether to align
> >>>>>>> doxygen javadoc-style tags ('@param', '@return',
> >>>> etc.)
> >>>>>>> + # TODO: Eats '[' in
> >>>>>>> '[in]'
> >>>>>>> +cmt_c_group = false
> >>>>>>> +cmt_c_nl_end = true # Whether to add a
> >>>>>>> newline before the closing '*/' of the combined c-
> >>>>> comment.
> >>>>>>> +cmt_c_nl_start = true
> >>>>>>> +cmt_cpp_group = false
> >>>>>>> +cmt_cpp_nl_end = true
> >>>>>>> +cmt_cpp_nl_start = true
> >>>>>>> +cmt_cpp_to_c = false
> >>>>>>> +cmt_indent_multi = false # Whether to apply
> >>>>>>> changes to multi-line comments, including
> >>> cmt_width,
> >>>>>>> + # keyword
> >>>>>>> substitution and leading chars.
> >>>>>>> +cmt_insert_before_preproc = false
> >>>>>>> +cmt_insert_file_header = default_file_header.txt
> >>>>>>> +cmt_insert_func_header = default_function_header.txt
> >>>>>>> +cmt_multi_check_last = false
> >>>>>>> +cmt_multi_first_len_minimum = 2
> >>>>>>> +cmt_reflow_mode = 1 # How to reflow
> >>>>>>> comments.
> >>>>>>> + # (0:No reflow, 1:No
> >>>>>>> touching at all, 2: Full reflow)
> >>>>>>> +cmt_sp_after_star_cont = 0 # The number of
> >>>>>>> spaces to insert after the star on subsequent comment
> >>>>> lines.
> >>>>>>> +cmt_sp_before_star_cont = 0 # The number of
> >>>>>>> spaces to insert at the start of subsequent comment
> >>>> lines.
> >>>>>>> +cmt_star_cont = false # Whether to put a
> >>>>>>> star on subsequent comment lines.
> >>>>>>> +cmt_width = 120 # Try to wrap
> >>>>>>> comments at N columns.
> >>>>>>> +sp_cmt_cpp_start = add # Add or remove
> >>>>>>> space after the opening of a C++ comment, as in
> >>>>>>> + # '// <here> A'.
> >>>>>>> NOTE: Breaks indentation within comments.
> >>>>>>> +
> >>>>>>> +# Function definitions / declarations
> >>>>>>> +indent_func_call_param = false # Whether to indent
> >>>>>>> continued function call parameters one indent
> >>> level,
> >>>>>>> + # rather than
> >>>>>>> aligning parameters under the open parenthesis.
> >>>>>>> +indent_func_class_param = false # Whether to indent
> >>>>>>> continued function call declaration one indent
> >>>> level,
> >>>>>>> + # rather than
> >>>>>>> aligning parameters under the open parenthesis.
> >>>>>>> +indent_func_ctor_var_param = false # Whether to indent
> >>>>>>> continued class variable constructors one indent
> >>>>> level,
> >>>>>>> + # rather than
> >>>>>>> aligning parameters under the open parenthesis.
> >>>>>>> +indent_func_def_param = true # Whether to indent
> >>>>>>> continued function definition parameters one
> >>> indent
> >>>>>>> + # level, rather than
> >>>>>>> aligning parameters under the open parenthesis.
> >>>>>>> +nl_fdef_brace = add # Add or remove
> >>>>>>> newline between function signature and '{'.
> >>>>>>> +nl_func_call_end_multi_line = true # Whether to add a
> >>>>>>> newline before ')' in a function call if '(' and
> >>> ')'
> >>>>> are
> >>>>>>> + # in different lines.
> >>>>>>> +nl_func_call_paren = remove # Add or remove
> >>>>>>> newline between a function name and the opening '(' in
> >>>> the
> >>>>>>> + # call.
> >>>>>>> +nl_func_call_start_multi_line = true # Whether to add a
> >>>>>>> newline after '(' in a function call if '(' and ')'
> >>>> are
> >>>>>>> + # in different lines.
> >>>>>>> +nl_func_decl_args = force # Add or remove
> >>>>>>> newline after each ',' in a function declaration.
> >>>>>>> +nl_func_decl_empty = add # Add or remove
> >>>>>>> newline between '()' in a function declaration.
> >>>>>>> +nl_func_def_args = force # Add or remove
> >>>>>>> newline after each ',' in a function definition.
> >>>>>>> +nl_func_def_empty = add # Add or remove
> >>>>>>> newline between '()' in a function definition.
> >>>>>>> +nl_func_def_paren = remove # Add or remove
> >>>>>>> newline between a function name and the opening '('
> >>>>>>> + # in the definition.
> >>>>>>> +nl_func_paren = remove # Add or remove
> >>>>>>> newline between a function name and the opening '(' in
> >>>>>>> + # the declaration.
> >>>>>>> +nl_func_type_name = add # Add or remove
> >>>>>>> newline between return type and function name in a
> >>>>> function
> >>>>>>> + # definition.
> >>>>>>> +sp_fparen_brace = force # Add or remove
> >>>>>>> space between ')' and '{' of function.
> >>>>>>> +use_indent_func_call_param = true #
> >>>>>>> indent_func_call_param will be used
> >>>>>>> +
> >>>>>>> +# Additional Newline Rules
> >>>>>>> +nl_after_brace_open = true #
> >>>>>>> Whether to add a newline after '{'. This also adds a
> >>>> newline
> >>>>>>> + # before
> >>>>>>> the matching '}'.
> >>>>>>> +nl_after_brace_open_cmt = true #
> >>>>>>> Whether to add a newline between the open brace and a
> >>>>>>> + #
> >>>>>>> trailing single-line comment.
> >>>>>>> + #
> >>>>>>> Requires nl_after_brace_open = true.
> >>>>>>> +nl_after_do = add # Add or
> >>>>>>> remove blank line after 'do/while' statement.
> >>>>>>> +nl_after_for = add # Add or
> >>>>>>> remove blank line after 'for' statement.
> >>>>>>> +nl_after_func_body = 2 # The
> >>>>>>> number of newlines after '}' of a multi-line
> >>> function
> >>>>> body
> >>>>>>> +nl_after_func_body_one_liner = 2
> >>>>>>> +nl_after_func_proto = 2
> >>>>>>> +nl_after_func_proto_group = 2
> >>>>>>> +nl_after_if = add
> >>>>>>> +nl_after_multiline_comment = false
> >>>>>>> +nl_after_return = false
> >>>>>>> +nl_after_struct = 2
> >>>>>>> +nl_after_switch = add
> >>>>>>> +nl_after_vbrace_close = true
> >>>>>>> +nl_after_vbrace_open = true
> >>>>>>> +nl_after_vbrace_open_empty = true
> >>>>>>> +nl_after_while = add
> >>>>>>> +nl_assign_leave_one_liners = true
> >>>>>>> +nl_before_block_comment = 2
> >>>>>>> +nl_before_case = false
> >>>>>>> +nl_before_do = ignore
> >>>>>>> +nl_before_for = ignore
> >>>>>>> +nl_before_if = ignore
> >>>>>>> +nl_before_switch = ignore
> >>>>>>> +nl_before_while = ignore
> >>>>>>> +nl_before_whole_file_ifdef = 2
> >>>>>>> +nl_brace_brace = force
> >>>>>>> +nl_brace_struct_var = remove
> >>>>>>> +nl_case_colon_brace = add
> >>>>>>> +nl_class_leave_one_liners = false
> >>>>>>> +nl_collapse_empty_body = false
> >>>>>>> +nl_comment_func_def = 1
> >>>>>>> +nl_create_for_one_liner = false
> >>>>>>> +nl_create_if_one_liner = false
> >>>>>>> +nl_create_while_one_liner = false
> >>>>>>> +nl_define_macro = false
> >>>>>>> +nl_ds_struct_enum_close_brace = true
> >>>>>>> +nl_ds_struct_enum_cmt = false
> >>>>>>> +nl_enum_leave_one_liners = false
> >>>>>>> +nl_func_decl_end = add
> >>>>>>> +nl_func_decl_start = add
> >>>>>>> +nl_func_def_end = add
> >>>>>>> +nl_func_def_start = add
> >>>>>>> +nl_func_leave_one_liners = false
> >>>>>>> +nl_func_proto_type_name = add
> >>>>>>> +nl_func_var_def_blk = 1
> >>>>>>> +nl_getset_leave_one_liners = false
> >>>>>>> +nl_if_leave_one_liners = false
> >>>>>>> +nl_multi_line_define = false
> >>>>>>> +nl_squeeze_ifdef = false
> >>>>>>> +nl_var_def_blk_end = 0
> >>>>>>> +nl_var_def_blk_start = 0
> >>>>>>> +
> >>>>>>> +# Preprocessor Rules
> >>>>>>> +pp_define_at_level = true
> >>>>>>> +pp_if_indent_code = false
> >>>>>>> +pp_indent_func_def = false
> >>>>>>> +pp_indent_extern = false
> >>>>>>> +pp_ignore_define_body = true # Workaround: Turn
> >>>>>>> off processing for #define body
> >>>>>>> + # (current rules
> >>>>>>> do not work for some defines)
> >>>>>>> +pp_indent = add
> >>>>>>> +pp_indent_at_level = true
> >>>>>>> +pp_indent_count = 2
> >>>>>>> +pp_indent_if = 2
> >>>>>>> +pp_indent_region = 2
> >>>>>>> +pp_region_indent_code = false
> >>>>>>> +pp_space = remove
> >>>>>>> +
> >>>>>>> +#
> >>>>>>> +# The tokens below are assigned specific types so they are
> >>>>>>> always recognized properly.
> >>>>>>> +#
> >>>>>>> +
> >>>>>>> +# Explicitly define EDK II qualifiers
> >>>>>>> +set QUALIFIER CONST
> >>>>>>> +set QUALIFIER EFIAPI
> >>>>>>> +set QUALIFIER IN
> >>>>>>> +set QUALIFIER OPTIONAL
> >>>>>>> +set QUALIFIER OUT
> >>>>>>> +
> >>>>>>> +# Explicitly define EDK II types
> >>>>>>> +set TYPE EFI_STATUS
> >>>>>>> +set TYPE VOID
> >>>>>>> diff --git a/.pytool/Plugin/UncrustifyCheck/uncrustify_ext_dep.yaml
> >>>>>>> b/.pytool/Plugin/UncrustifyCheck/uncrustify_ext_dep.yaml
> >>>>>>> new file mode 100644
> >>>>>>> index 000000000000..d8c22403b4b1
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/.pytool/Plugin/UncrustifyCheck/uncrustify_ext_dep.yaml
> >>>>>>> @@ -0,0 +1,16 @@
> >>>>>>> +## @file
> >>>>>>> +# Downloads the Uncrustify application from a Project Mu NuGet
> >>>>>>> package.
> >>>>>>> +#
> >>>>>>> +# Copyright (c) Microsoft Corporation.
> >>>>>>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> >>>>>>> +##
> >>>>>>> +{
> >>>>>>> + "id": "uncrustify-ci-1",
> >>>>>>> + "scope": "cibuild",
> >>>>>>> + "type": "nuget",
> >>>>>>> + "name": "mu-uncrustify-release",
> >>>>>>> + "source":
> >>>>>>> "https://pkgs.dev.azure.com/projectmu/Uncrustify/_packaging/mu_uncrustify/nuget/v3/index.json",
> >>>>>>>
> >>>>>>> + "version": "73.0.3",
> >>>>>>> + "flags": ["set_shell_var", "host_specific"],
> >>>>>>> + "var_name": "UNCRUSTIFY_CI_PATH"
> >>>>>>> +}
> >>>>>>> diff --git a/.pytool/Plugin/UncrustifyCheck/uncrustify_plug_in.yaml
> >>>>>>> b/.pytool/Plugin/UncrustifyCheck/uncrustify_plug_in.yaml
> >>>>>>> new file mode 100644
> >>>>>>> index 000000000000..06c76af02759
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/.pytool/Plugin/UncrustifyCheck/uncrustify_plug_in.yaml
> >>>>>>> @@ -0,0 +1,11 @@
> >>>>>>> +## @file
> >>>>>>> +# CiBuildPlugin used to check coding standard compliance of EDK
> >>>>>>> II style C source code
> >>>>>>> +#
> >>>>>>> +# Copyright (c) Microsoft Corporation.
> >>>>>>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> >>>>>>> +##
> >>>>>>> +{
> >>>>>>> + "scope": "cibuild",
> >>>>>>> + "name": "Uncrustify Coding Standard Test",
> >>>>>>> + "module": "UncrustifyCheck"
> >>>>>>> +}
> >>>>>>> diff --git a/.pytool/Readme.md b/.pytool/Readme.md
> >>>>>>> index f6505507966a..e0d07f317049 100644
> >>>>>>> --- a/.pytool/Readme.md
> >>>>>>> +++ b/.pytool/Readme.md
> >>>>>>> @@ -264,6 +264,10 @@ BSD-2-Clause-Patent.
> >>>>>>> Run the Ecc tool on the package. The Ecc tool is available in
> >>>>>>> the BaseTools
> >>>>>>> package. It checks that the code complies to the EDKII coding
> >>>>>>> standard.
> >>>>>>>
> >>>>>>> +### Coding Standard Compliance - UncrustifyCheck
> >>>>>>> +
> >>>>>>> +Runs the Uncrustify application to check for coding standard
> >>>>>>> compliance issues.
> >>>>>>> +
> >>>>>>> ## PyTool Scopes
> >>>>>>>
> >>>>>>> Scopes are how the PyTool ext_dep, path_env, and plugins are
> >>>>>>> activated. Meaning
> >>>>>>> --
> >>>>>>> 2.28.0.windows.1
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>>
> >>
> >>
> >>
> >>
> >>
> >>
> >
> >
> >
> >
prev parent reply other threads:[~2021-11-25 2:05 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-24 21:41 [PATCH v4 1/1] .pytool/Plugin/UncrustifyCheck: Add Uncrustify CI plugin Michael Kubacki
2021-11-24 22:45 ` Michael D Kinney
2021-11-24 22:54 ` [edk2-devel] " Michael Kubacki
2021-11-24 23:05 ` Michael D Kinney
2021-11-25 0:08 ` Michael D Kinney
2021-11-25 0:16 ` Michael D Kinney
2021-11-25 0:24 ` Michael Kubacki
[not found] ` <16BAA253C971EED8.15594@groups.io>
2021-11-25 1:25 ` Michael Kubacki
2021-11-25 2:05 ` Michael D Kinney [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CO1PR11MB4929A7738CA99E58694C327DD2629@CO1PR11MB4929.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox