Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

a2ltool User Manual

a2ltool is a command line utility that helps you work with a2l files.

A2L files describe measurement variables and tunable parameters of an embedded device (typically: an automotive ECU).

Features

You can:

  • create A2L files from scratch
  • merge multiple a2l files
  • update the information in an a2l file based debug info of the software
  • delete existing elements
  • check the consistency of a file

Installation

a2ltool binaries are available on the github releases page. You can get pre-built binaries for Windows (x64) and Linux (x64) there.

For any other platforms you can clone the git repository and compile it as ususal, using cargo build --release.

Quick start

Every invocation of a2ltool requires either an input file name, or the parameter --create to start with an empty file. Whenever you want to write output to a file, you must use the --output parameter. A minimal call to a2ltool that does not perform any actions by itself looks like this:

a2ltool input.a2l --output output.a2l

or

a2ltool --create --output output.a2l

You can add any additional parameters you need to this basic command.

Note

By default, a2ltool is silent; only errors are printed to the console.

While getting started with a2ltool, you may find it useful to use the --verbose (or -v) option to enable additional output.

Basic examples

Merging

a2ltool input.a2l --merge other.a2l --output output.a2l

Updating

a2ltool input.a2l --elffile ecu_software.elf --update -v --output output.a2l

Support

If you encounter any bugs, you can report them in the issue tracker on Github.

Usage of a2ltool

Basic options

--create

Create a new A2L file instead of loading an existing one

-o <A2LFILE>, --output <A2LFILE>

Write to the given output file. If this flag is not present, no output will be written.

-s, --strict

Parse all input in strict mode. An error wil be reported if the file has any inconsistency.

-v, --verbose

Display additional information

-e <ELFFILE>, --elffile <ELFFILE>

Elf file containing symbols and address information in DWARF2+ format. An exe file produced by MinGW with DWARF2 debug info can also be used.

--pdbfile <PDBFILE>

PDB file containig debugging information in Microsoft's Program Database format. This is used for programs that are compiled by Visual Studio

-h, --help

Print the built in help message and exit.

-V, --version

Print the version and exit.

Merge and Update

-m <A2LFILE>, --merge <A2LFILE>

Merge another a2l file on the MODULE level. The input file and the merge file must each contain exactly one MODULE. The contents will be merged so that there is one merged MODULE in the output.

--merge-preference <PREF>

Choose how to handle conflicts when merging MODULES. PREF can be one of:

  • EXISTING: Keep the existing item
  • NEW: Use the new item from the merge file.
  • BOTH: keep both items, renaming the new item if necessary (default)

-i, --merge-includes

Merge the content of all included files. The output file will contain no /include commands.

--merge-project <A2LFILE>

Merge another a2l file on the PROJECT level. If the input file contains m MODULES and the merge file contains n MODULES, then there will be m + n MODULEs in the output.

Warning: Unless you know exactly what you're doing, this option is not what you want.

-u [<UPDATE_TYPE>], --update [<UPDATE_TYPE>]

Update the A2L file based on the elf file. The update type can omitted to perform a full update or it can be one of:

  • FULL: Update the address and type info of all items. This is the default.
  • ADDRESSES: Update only the addresses.

The arg --elffile must be present in order to perform an update.

´--update-mode [<UPDATE_MODE>]`

Update the A2L file based on the elf file. Action can be one of:

  • DEFAULT: Unknown objects are removed, invalid settings are updated.
  • STRICT: Unknown objects or invalid settings trigger an error.
  • PRESERVE: Unknown objects are preserved, with the address set to zero.

The arg --update must be present.

Creating and Removing Items

-C <VAR>, --characteristic <VAR>

Insert a CHARACTERISTIC based on a variable in the elf file. The variable name can be complex, e.g. var.element[0].subelement

--characteristic-regex <REGEX>

Compare all symbol names in the elf file to the given regex. All matching ones will be inserted as CHARACTERISTICs

--characteristic-range <ADDR> <ADDR>

Insert multiple CHARACTERISTICs. All variables whose address is inside the given range will be inserted as CHARACTERISTICs. This is useful in order to add all variables from a tuning data section with fixed addresses.

Example: --characteristic-range 0x1000 0x2000

--characteristic-section <SECTION>

Insert all variables from the given section as CHARACTERISTICs.

-M <VAR>, --measurement <VAR>

Insert a MEASUREMENT based on a variable in the elf file. The variable name can be complex, e.g. var.element[0].subelement

--measurement-regex <REGEX>

Compare all symbol names in the elf file to the given regex. All matching ones will be inserted as MEASUREMENTs

--measurement-range <ADDR> <ADDR>

Insert multiple MEASUREMENTs. All variables whose address is inside the given range will be inserted as MEASUREMENTs. Example: --measurement-range 0x1000 0x2000

--measurement-section <SECTION>

Insert all variables from the given section as MEASUREMENTs.

--target-group <GROUP>

When inserting items, put them into the group named in this option. The group will be created if it doe not exist.

--from-source <SOURCE_FILE>

Create elements in the a2l file based on special comments in a source file. Argument can be a filename or pattern (e.g. *.c).

-t, --enable-structures

Enable the the use of INSTANCE, TYPEDEF_STRUCTURE & co. for all operations. Requires a2l version 1.7.1 The use of structurs is not supported in many other tools. You should check if the consumer of your a2l files can handle such data before using this option.

-R <REGEX>, --remove <REGEX>

Remove any CHARACTERISTICs, MEASUREMENTs, AXIS_PTS and INSTANCEs whose name matches the given regex.

--remove-range <ADDR> <ADDR>

Remove any CHARACTERISTICs, MEASUREMENTs, AXIS_PTS and INSTANCEs whose address is inside the given range.

-c, --cleanup

Remove empty or unreferenced items.

--ifdata-cleanup

Remove all IF_DATA blocks that cannot be parsed according to A2ML

Other

--check

Perform additional consistency checks

--sort

Sort all the elements in the file first by item type and then alphabetically. This gives the file a deterministic order.

-a <A2L_VERSION>, --a2lversion <A2L_VERSION>

Convert the input file to the given version (e.g. "1.5.1", "1.6.0", etc.). It can upgrade or downgrade the version of an a2l file. When downgrading this is a lossy operation, which deletes incompatible information.

Permitted versions are 1.5.0, 1.5.1, 1.6.0, 1.6.1, 1.7.0, 1.7.1

--debug-print

Display internal data for debugging / troubleshooting.

--show-xcp

Display the XCP settings in the a2l file, if they exist

Merging A2L Files

Motivation

An embedded software project often generates multiple separate A2L files for different parts of the overall system. For example, there might be hand-crafted files as well as files generated for individual components by calibration data management tools, AUTOSAR RTE generators, etc.

All these files must be merged into a single file so that measurement and calibration tools can utilize the information.

Basic Example

You can use a2ltool as follows:

a2ltool main.a2l --merge first.a2l --merge second.a2l --output out.a2l

The --merge option can be repeated as many times as needed to merge multiple input files in a single command.

Merge Modes

Ideally, the information in your input files should be completely disjoint. In other words, no two files should define an object with the same name.

For example, if one file defines a measurement variable speed as an integer, but another file defines speed as a floating point value, then it is impossible to know which definition is correct. By default, the merge keeps both definitions, renaming the second one to speed.MERGE. This allows you to select the correct variant in the measurement tool.

You can change this behavior by setting a merge preference.

a2ltool supports three different ways to handle merges:

  • --merge-preference EXISTING: Prefer existing items, discarding any items from the merge that have conflicting names.
  • --merge-preference NEW: Prefer new items, overwriting any existing items with conflicting names.
  • --merge-preference BOTH: Keep both, renaming conflicts as described above. This is the default if no merge preference is set.

The merge preference applies to all merge operations in the same a2ltool invocation. Call a2ltool multiple times if you want to use different preferences for different files.

Example

a2ltool main.a2l --merge other.a2l --merge-preference NEW --output out.a2l

Merging includes

A2L files can include other A2L files using the directive /include "file.a2l". This form is not widely supported by measurement and calibration tools, so included files are usually merged into a single file.

a2ltool can perform this merging step using the --merge-includes command-line option.

Example

a2ltool file_with_includes.a2l --merge-includes --output file_without_includes.a2l

Updating Files

Motivation

Programs that load A2L files depend on the memory addresses specified within those files to correctly read and write data. In most workflows, these addresses are initially set to zero.

To resolve this, the update process must locate each item defined in the A2L file within the debug data of the compiled software, then update the A2L file with the correct address.

By default, a2ltool removes obsolete elements and updates all other information that can be derived from debug data, including:

  • Data type
  • Array dimensions
  • Upper and lower limits
  • Bit masks for bit fields
  • Enumerators for types declared as enums

This enables a2ltool to update existing A2L files that were originally created for different versions of ECU software.

Basic Example

a2lfile input.a2l --elffile ecu_software.elf --update --output updated.a2l

Update Modes

a2lfile can update all settings in an A2L file or restrict updates to addresses only. The operation is controlled by the --update parameter:

  • --update or --update FULL: Update addresses and type information for all items.
  • --update ADDRESSES: Update only the addresses.

You can also specify how to handle invalid or unknown items using the --update-mode parameter:

  • --update-mode DEFAULT: Default behavior: unknown objects are removed and invalid settings are updated.
  • --update-mode STRICT: Unknown objects or invalid settings will cause an error.
  • --update-mode PRESERVE: Unknown objects are preserved, but their addresses are set to zero.

Debug Data Formats

Most embedded development toolchains produce ELF files containing debug data in the DWARF2 (or 3/4/5) format.

In some cases, parts of an embedded program may also be compiled using PC compilers in order to target simulation or "virtual ECU" environments. These builds may produce EXE or DLL files with debug information in the PDB format.

To support these scenarios, a2lfile includes parsers for both DWARF2 and PDB formats.

Use the --elffile option to load a file containing DWARF2 debug info, or use --pdbfile to load debug information in the PDB format.

An interesting special case is compilation on Windows using MinGW, which produces EXE files with DWARF2 debug info. These files can also be loaded using the --elffile option.

One of these options must be provided to perform any update.

Examples

Update all information and preserve unknown items:

a2lfile input.a2l --elffile ecu_software.elf --update --update-mode PRESERVE --output updated.a2l

Update addresses only, and abort if the file contains invalid items:

a2lfile input.a2l --elffile ecu_software.elf --update ADDRESSES --update-mode STRICT --output updated.a2l

Creating new Elements in A2L Files

Overview

a2ltool supports two different ways of creating elements in a2l files.

  1. a2ltool can create items based on debug information
  2. a2ltool can process special comments in source files

Creating items from debug information

Creating single named items

Use the command line options --characteristic or --measurement to create a single MEASUREMENT or CHARACTERISTIC element in the A2L file for the named global variable or struct member.

The variable name can refer to a struct member or array element. For example, myStruct.member[3].x works, provided it is a valid global name in the ECU software.

Local variables (allocated on the stack) cannot be added to the A2L file.

Example

a2ltool input.a2l --elffile sw.elf --measurement globalVar --output out.a2l

a2ltool input.a2l --elffile sw.elf --characteristic myStruct.member[3].x --output out.a2l

Creating multiple named items using regex

Use the command line options --characteristic-regex or --measurement-regex to insert multiple named items at once using regular expressions. a2ltool matches each variable name against the provided regular expressions and creates a MEASUREMENT or CHARACTERISTIC for every match.

For example, the regular expression some.* matches someFoo and someBar, but not bla_some.

Example

a2ltool input.a2l --elffile sw.elf --measurement-regex "thing\d+.member.[xy]" --output out.a2l

Creating multiple items based on an address range

The command line options --characteristic-range or --measurement-range take a pair of addresses. Any global variable located within this range is added to the A2L file.

Example

Assume that the ECU software has the following variables:

  • time at address 0x1200
  • space at address 0x1300

The following command adds both variables to the A2L file:

a2ltool input.a2l --elffile sw.elf --characteristic-range 0x1000 0x2000 --output out.a2l

Creating multiple items based on the section

Elements of the embedded software may be placed into distinct named sections. The options --characteristic-section and --measurement-section look up the address range of each section in the ELF file header. All items within the memory range of the specified section are then inserted into the A2L file.

Group assignment

By default, items created from debug information are not assigned to any group. You can change this by using the --target-group option. The specified group will be extended or created as needed.

Creating items based on comments in source files

This mode is compatible with "Vector ASAP2 Creator".

Special comments within the source code define A2L elements for variables and structures.

The command-line option --from-source can be specified multiple times to provide a list of file names or file name patterns. All patterns are fully expanded, and the resulting files are processed to extract special comments.

File name patterns

File name patterns are an easy way to specify multiple file names.

For example, *.c matches all .c files in the current directory. A more complex pattern, src/**/*.h, matches all .h files at any depth within the src directory.

File types

a2ltool processes any text file, regardless of its type. The syntax of the code is not evaluated, and C-style preprocessor directives are ignored. a2ltool only searches for comments—either blocks enclosed in /* */ or lines starting with //.

Example

Example Input

src/input_1.c

/*
@@ MAIN_GROUP = main
@@ DESCRIPTION = "Main group description"
@@ END
*/

/*
@@ SYMBOL = test_case
@@ A2L_TYPE = MEASURE
@@ WRITEABLE
@@ alt_name
@@ DATA_TYPE = UBYTE 0x3f [3...40] [0...45]
@@ CONVERSION = LINEAR 2 3 "kkk" 8 4
@@ DESCRIPTION = "Test description"
@@ ALIAS = TestAlias
@@ BASE_OFFSET = 1
@@ GROUP = parent | TestGroup
@@ DIMENSION = 3 4 5 SPLIT USE_TEMPLATE "._%d_[%d]bla%dblub"
@@ ADDRESS = 0x12345678
@@ ADDRESS_EXTENSION = 0x10
@@ EVENT CCP = 0
@@ COLOR = 0xFF0000
@@ VAR_CRITERION = Variant
@@ LAYOUT = TestLayout
@@ BYTE_ORDER = INTEL
@@ END
*/

...

src/input_2.c

/*
@@ SUB_GROUP = sub
@@ DESCRIPTION = "Sub group description"
@@ END
*/

/*
@@ SYMBOL = param1
@@ A2L_TYPE = PARAMETER
@@ WRITEABLE
@@ DATA_TYPE = FLOAT [0...100] [-10 ... 1000]
@@ CONVERSION = FORMULA "x*2+3" INVERSE "(x-3)/2" "unit" 8 4
@@ DESCRIPTION = "Parameter description"
@@ ALIAS = ParamAlias
@@ BASE_OFFSET = 2
@@ GROUP IN = sub
@@ DIMENSION = 10 SPLIT USE "_a" "_b" "_c" "_d" "_e" "_f" "_g" "_h" "_i" "_j"
@@ ADDRESS = 0x87654321
@@ ADDRESS_EXTENSION = 0x20
@@ EVENT XCP = FIXED 1
@@ COLOR = 0x00FF00
@@ VAR_CRITERION = Variant
@@ LAYOUT = ParamLayout
@@ BYTE_ORDER = MOTOROLA
@@ END
*/

...

src/input_3.c

/*
@@ CONVERSION = LinearConversion
@@ A2L_TYPE = LINEAR 12 3
@@ UNIT = "unit" 5 2
@@ DESCRIPTION = "Linear conversion"
@@ END
*/

/*
@@ CONVERSION = TableConversion
@@ A2L_TYPE = TABLE
@@ 0 0 "zero"
@@ 10 10 "ten"
@@ 20 20 "twenty"
@@ DEFAULT_VALUE "unknown"
@@ END
*/

src/input_4.c

/*
@@ SUB_STRUCTURE = SubStruct
@@ STRUCTURE = abc
@@ DATA_TYPE = STRUCTURE TypeName
@@ DIMENSION = 3 SPLIT
@@ BASE_OFFSET = 333
@@ SIZE = 64
@@ END
*/

/*
@@ ELEMENT = ElementName
@@ STRUCTURE = abc | def
@@ A2L_TYPE = MEASURE
@@ DATA_TYPE = ULONG
@@ END
*/

/*
@@ INSTANCE = InstanceName
@@ STRUCTURE = abc
@@ ADDRESS = 0x1234
@@ DIMENSION = 3 4 SPLIT
@@ SIZE = 9000
@@ GROUP = GroupName
@@ OVERWRITE x RANGE = [ -1 ... 1 ]
@@ OVERWRITE abc | def | ElementName CONVERSION = LINEAR 2 3 "s"
@@ END
*/

src/input_5.c

/*
@@ VAR_CRITERION = Variant
@@ DESCRIPTION = "Variant description"
@@ SELECTOR = MEASURE InputMeasurement
@@   VARIANT = Apple 1 0x0
@@   VARIANT = Orange 2 0x1000
@@   VARIANT = Banana 3 0x2000
@@ END
*/

Command

a2ltool --create --from-source "src/*.c" --output out.a2l

Syntax

Within the special comments each line must begin with the marker @@.

After stripping the @@ marker, the remaining text is parsed as a <definition> according to the following grammar:

Definition

<definition> ::=   <symbol>
                | <element>
                | <sub-structure>
                | <instance>
                | <conversion>
                | <main-group>
                | <sub-group>
                | <variant-criterion>

Symbol

<symbol> ::= "SYMBOL" "=" <identifier>
             "A2L_TYPE" "=" <item-definition>
             "END"

Element

<element> ::= "ELEMENT" "=" <identifier>
              "STRUCTURE" "=" <structure-path>
              "A2L_TYPE" "=" <item-definition>
              "END"

<structure-path> ::= <identifier> ( | <identifier> )*

Item definition

<item-definition> ::=   <axis-item-defition>
                      | <curve-item-defintion>
                      | <map-item-definition>
                      | <measure-item-definition>
                      | <parameter-item-definition>
                      | <string-item-definition>
                    
<axis-item-defition> ::= "AXIS" [ <write-access> ] [ <identifier> ]
                         <data-type>
                         "LAYOUT" "=" <identifier>
                         "DIMENSION" "=" <dimension>
                         [ <input> ]
                         ( <acm-attribute> )*

<curve-item-defintion> ::= "CURVE" [ <write-access> ] [ <identifier> ]
                           <data-type>
                           "LAYOUT" "=" <identifier>
                           ( <acm-attribute> )*
                           "X_AXIS" "=" <axis-definition>

<map-item-definition> ::= "MAP" [ <write-access> ] [ <identifier> ]
                          <data-type>
                          "LAYOUT" "=" <identifier>
                          ( <acm-attribute> )*
                          "X_AXIS" "=" <axis-definition>
                          "Y_AXIS" "=" <axis-definition>

<measure-item-definition> ::= "MEASURE" [ <write-access> ] [ <identifier> ]
                              <data-type>
                              ( <attribute> )*

<parameter-item-definition> ::= "PARAMETER" [ <write-access> ] [ <identifier> ]
                                <data-type>
                                ( <attribute> )*

<string-item-definition> ::= "STRING" <length> [ <write-access> ] [ <identifier> ]
                             ( <string-attribute> )*

Item values

<data-type> ::=   "DATA_TYPE" "=" "UBYTE" [ <bitmask> ] [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "UWORD" [ <bitmask> ] [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "ULONG" [ <bitmask> ] [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "UINT64" [ <bitmask> ] [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "SBYTE" [ <bitmask> ] [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "SWORD" [ <bitmask> ] [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "SLONG" [ <bitmask> ] [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "INT64" [ <bitmask> ] [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "FLOAT" [ <range> ] [ <range> ]
                | "DATA_TYPE" "=" "DOUBLE" [ <range> ] [ <range> ]

<bitmask> ::= <value>

<range> ::= "[" <value> "..." <value> "]"

<write-access> ::= "WRITEABLE" | "READ_ONLY"

<input> ::= "INPUT" "=" [ "INSTANCE_NAME" ] <identifier>

<axis-defintion> ::=   "STANDARD" <data-type>
                       <dimension-attr>
                       [ <input> ]
                       [ <conversion-attr> ]
                     | "FIX" ( <value> )+
                       [ <input> ]
                       [ <conversion-attr> ]
                     | "FIX" <range> [ "," <value> ]
                       [ <input> ]
                       [ <conversion-attr> ]
                     | "COMMON" [ "INSTANCE_NAME" ] <identifier>

Attribute groups

<attribute> ::=   <address-attr>
                | <address-extension-attr>
                | <alias-attr>
                | <base-offset-attr>
                | <byte-order-attr>
                | <color-attr>
                | <conversion-attr>
                | <description-attr>
                | <dimension-attr> <split>
                | <event-attr>
                | <group-attr>
                | <layout-attr>
                | <var-criterion-attr>

<acm-attribute> ::=   <address-attr>
                    | <address-extension-attr>
                    | <alias-attr>
                    | <base-offset-attr>
                    | <byte-order-attr>
                    | <conversion-attr>
                    | <description-attr>
                    | <group-attr>
                    | <var-criterion-attr>

<string-attribute> ::=   <address-attr>
                       | <address-extension-attr>
                       | <alias-attr>
                       | <base-offset-attr>
                       | <description-attr>
                       | <dimension-attr> <split>
                       | <group-attr>
                       | <var-criterion-attr>

Attribute definition

<address-attr> ::= "ADDRESS" "=" <value>

<address-extension-attr> ::= "ADDRESS_EXTENSION" "=" <value>

<alias-attr> ::= "ALIAS" "=" <identifier>

<base-offset-attr> ::= "BASE_OFFSET" "=" <VALUE>

<byte-order-attr> ::= "BYTE_ORDER" "=" ( "INTEL" | "MOTOROLA" )

<color-attr> ::= "COLOR" "=" <value>

<conversion-attr> ::=   "CONVERSION" "=" <identifier>
                        [[ <length> ] <digits> ]
                      | "CONVERSION" "=" "LINEAR"
                        <factor> <offset> <unit>  [[ <length> ] <digits> ]
                      | "CONVERSION" "=" "FORMULA"
                        <string> [ "INVERSE" <string> ]
                        <unit> [[ <length> ] <digits> ]
                      | "CONVERSION" "=" "TABLE"
                        ( value [<value>] <string> )+
                        [ "DEFAULT_VALUE" <string> ]
                        [ "FORMAT" <length> <digits> ]
                      | "UNIT" "=" [[ <length> ] <digits> ]

<description-attr> ::= "DESCRIPTION" "=" <string>

<dimension-attr> ::= "DIMENSION" "=" <value>
                     [<value>] [<value>] [<value>] [<value>]

<event-attr> ::=   "EVENT" "CCP" "=" <value>
                 | "EVENT" "XCP" "=" "FIXED" <value>
                 | "EVENT" "XCP" "=" "VARIABLE" ( <value> )+
                 | "EVENT" "XCP" "=" "DEFAULT" <value>

<group-attr> ::= "GROUP" [ "IN" | "OUT" | "DEF" ] "="
                 <identifier> ( | <identifier> )*

<layout-attr> ::= "LAYOUT" "=" <identifier>

<var-criterion-attr> ::= "VAR_CRITERION" "=" <identifier>

<split> ::=   "SPLIT"
            | "SPLIT" "USE" ( <string> )+
            | "SPLIT" "USE_TEMPLATE" <string>

Sub-Structure

<sub-structure> ::= "SUB_STRUCTURE" "=" <identifier>
                    "STRUCTURE" "=" <structure-path>
                    [ "DATA_TYPE" "=" "STRUCTURE <identifier> ]
                    ( <structure-attribute> )*
                    END

<structure-attribute> ::=   <base-offset-attr>
                          | <dimension-attr>
                          | <size-attr>

<size-attr> ::= "SIZE" "=" <value>

Instance

<instance> ::= "INSTANCE" "=" <identifier> [ <identifier> ]
               "STRUCTURE" "=" <identifier>
               [ <address-attr> ]
               [ <dimension-attr> [ <split> ]]
               [ <size-attr> ]
               [ <group-attr> ]
               ( <overwrite> )*
               "END"

<overwrite> ::= "OVERWRITE" <element-spec> <overwrite-details>

<overwrite-details> ::=   <alias-attr>
                        | <color-attr>
                        | <conversion-attr>
                        | <description-attr>
                        | <group-attr>
                        | "RANGE" = <range>

<element-spec> ::= [ <structure-path> | ] <identifier>

Conversion

<conversion> ::= "CONVERSION" "=" <identifier>
                 "A2L_TYPE" = "=" <conversion-type>
                 [ "UNIT" "=" <string> <length> <digits> ]
                 [ "DESCRIPTION" "=" <string> ]
                 "END"

<conversion-type> ::=   "LINEAR" <factor> <offset>
                      | "FORMULA" <string> [ "INVERSE" <string> ]
                      | "TABLE" ( value [<value>] <string> )+
                        [ "DEFAULT_VALUE" <string> ]

Main group

<main-group> ::= "MAIN_GROUP" "=" <identifier>
                 [ <description-attr> ]
                 "END"

Sub group

<sub-group> ::= "SUB_GROUP" "=" <identifier>
                [ <description-attr> ]
                "END"

Variant criterion

<variant-criterion> ::= "VAR_CRITERION" "=" <identifier>
                        [ <description-attr> ]
                        "SELECTOR" = ( "PARAMETER" | "MEASURE" ) <identifier>
                        ( <variant> )*
                        "END"

<variant> ::= "VARIANT" "=" <identifier> <value> <value>

Notes

a2ltool performs only minimal consistency checks when creating items from source comments.

For example, added items may reference COMPU_METHODs or RECORD_LAYOUTs by name, which are not guaranteed to exist.

To perform a full sanity check, use the --check option together with --from-source.

Removing Elements

Overview

You may need to remove elements from an A2L file to protect sensitive information when sharing files with clients, or to prevent unauthorized users from modifying critical settings.

a2ltool supports removing elements in several ways:

  • Obsolete elements that are no longer present in the ECU software can be deleted during an update.
    This is described in the update chapter.
  • Elements can be deleted by name or by matching a regular expression.
  • Elements can be deleted based on their address.
  • Supporting elements such as COMPU_METHODs and RECORD_LAYOUTs can be automatically removed if they are unreferenced.

Removing Elements by Name

The --remove option deletes any CHARACTERISTIC, MEASUREMENT, AXIS_PTS, INSTANCE, or BLOB that matches the specified name or regular expression.

You can pass this option multiple times in a single a2ltool command to remove several elements at once.

It is recommended to use --cleanup as well (see below).

Example

a2ltool input.a2l --remove SecretValue --remove DangerousTuning.* --cleanup --output out.a2l

Removing Elements by Address

The --remove-range option deletes any CHARACTERISTIC, MEASUREMENT, AXIS_PTS, INSTANCE, or BLOB located within the specified address range.

This is useful for removing entire categories of elements, as the address space of an embedded controller is typically divided into distinct regions. Hardware usually places RAM, ROM, and device registers in separate memory regions, and embedded software often further subdivides these regions.

It is recommended to use --cleanup as well (see below).

Example

Given a hardware and project-specific memory map like:

...
0x10008000 - 0x10009FFF: safety-critical parameters
0x1000A000 - 0x1000FFFF: non-critical parameters
...
0x20000000 - 0x2000FFFF: RAM region for safety-critical tasks
0x20010000 - 0x2001FFFF: RAM region for non-critical tasks
...

You could run a2ltool to remove all A2L elements containing safety-critical data at once:

a2ltool input.a2l --remove-range 0x10008000 0x10009FFF --remove-range 0x20000000 0x2000FFFF --cleanup --output out.a2l

Cleaning up Unused Items

An A2L file contains many "supporting" items: COMPU_METHOD, COMPU_TAB, RECORD_LAYOUT, GROUP, etc.
These support the definition of main elements (CHARACTERISTIC, MEASUREMENT, AXIS_PTS, INSTANCE, and BLOB), but are not useful on their own.

When main elements are removed, some supporting items may become unused.

The --cleanup option checks each supporting item to determine if it is still referenced, and deletes those that are no longer needed.

Example

a2ltool input.a2l --remove ".*" --cleanup --output nearly_empty.a2l

Checking A2L File Consistency

Motivation

Syntactically valid a2l files can still contain incorrect or inconsistent content.

This can occur in several ways:

  • Deleting an item that is referenced elsewhere in the file. For example, an axis may use a MEASUREMENT as an input. a2ltool can delete a referenced MEASUREMENT using the --remove command-line option.
  • Adding items without including the elements they reference. With a2ltool, this may happen when using the --from-source option, as correctness depends on the input provided by the user.
  • Other tools that generate a2l files may have bugs.
  • The a2l file may be manually edited in a text editor, introducing errors.

Checks

With the --check option, a2ltool performs the following checks:

  • Verifies all cross-references between elements.
  • Ensures that various elements have mandatory or forbidden sub-elements depending on their type. For example, an AXIS_DESCR of type COM_AXIS requires an AXIS_PTS_REF. Similarly, a COMPU_METHOD of type TAB_VERB must have a COMPU_TAB_REF.
  • Checks that CHARACTERISTICs have the correct number of AXIS_DESCRs based on their type.
  • Validates that the lower and upper limits of elements are within the outer limits defined by their COMPU_METHOD and data type.
  • Checks the group hierarchy: it must start with a group marked as ROOT and must not contain any cycles.

Usage notes

By itself, the option --check only prints a list of warnings about incorrect a2l file elements.

When used in automation, such as a Makefile or CI job, it is recommended to also use --strict, which turns warnings into errors and sets a non-zero exit status to signal the error to the environment.

The check only considers information within the a2l file. To also compare the content to the ECU software, use --update --update-mode STRICT, which raises an error if there is a mismatch between the a2l file and the debug information.

Examples

a2ltool input.a2l --verbose --check --strict

a2ltool input.a2l --elffile sw.elf --update --update-mode STRICT --check --strict

Complex Command Lines

Order of Operations

All options supported by a2ltool can be combined in a single command line.

When combining options, it is useful to understand the overall order of operations:

  1. Load the input A2L or create a new file (--create)
  2. Convert the file version (--a2lversion)
  3. Merge additional A2L files (--merge)
  4. Merge includes (--merge-includes)
  5. Remove items (--remove and --remove-range)
  6. Insert items generated from source comments (--from-source)
  7. Update addresses and other settings (--update)
  8. Insert items based on debug data (e.g., --characteristic, --measurement, etc.)
  9. Clean-up (--cleanup)
  10. If-data clean-up (--ifdata-cleanup)
  11. Sort all elements (--sort)
  12. Check consistency (--check)
  13. Write the output file (--output)

Response files

a2ltool supports many options, several of which may be used multiple times. This can cause command lines to become very long, making them unmanageable or even exceeding system-imposed command line length limits.

To address this, a2ltool supports response files—files that contain command line options. When a response file is included in the command line, a2ltool loads the file and reads additional options from it.

A response file must be prefixed with @ on the command line.

Example

Example response file (Response.rsp):

--elffile sw.elf
--update ADDRESSES
--update-mode PRESERVE
--cleanup

Example command using a response file:

a2lfile input.a2l @Response.rsp --output out.a2l

Additional Examples

Merge

Merge two a2l files

a2ltool file1.a2l --merge file2.a2l --output merged.a2l

Merge multiple a2l files

a2ltool file1.a2l --merge file2.a2l --merge file3.a2l --merge file4.a2l --output merged.a2l

Merge all included files into the main file

a2ltool file1.a2l --merge-includes --output flat.a2l

Update

Update the addresses and other data in an a2l file

a2ltool input.a2l --elffile input.elf --update --output updated.a2l

Update the addresses and other data in an a2l file, while keeping invalid elements

a2ltool input.a2l --elffile input.elf --update --update-mode PRESERVE --output updated.a2l

Update only the addresses in an a2l file, and exit with an error if any other a2l elements are incorrect

a2ltool input.a2l --elffile input.elf --update ADDRESSES --update-mode STRICT --output updated.a2l

Create

Create a new a2l file and add a characteristic from an elf file to it

a2ltool --create --elffile input.elf --characteristic my_var --output newfile.a2l

Create a new a2l file and add multiple measurements from an elf file to it using a regular expression

a2ltool --create --elffile input.elf --measurement-regex ".*name_pattern\d\d+*" --output newfile.a2l

Create a new a2l file and add multiple measurements from an elf file to it using an address range

a2ltool --create --elffile input.elf --measurement-range 0x1000 0x3000 --output newfile.a2l

A2L Version

Change the version of an a2l file, while deleting any incompatible elements

a2ltool input.a2l --a2lversion 1.5.1 --output downgraded.a2l

Create a new A2L File with a specific version

a2ltool --create --a2lversion 1.6.1 --output a2lver_161.a2l

Check

Check an a2lfile for consistency

a2ltool input.a2l --check --strict

Check for consistency and also verify that the a2l file matches the DWARF2 debug data

a2ltool input.a2l --elffile sw.elf --update ADDRESSES --update-mode STRICT --check --strict

Response Files

Use response files containing command arguments

Assume that the file a2ltool.rsp exists and contains valid arguments for a2ltool.

a2ltool @a2ltool.rsp

Changelog

Version 3.0.0

  • Implement compatibility with Vector's ASAP2 Creator and allow creation of a2l elements using the same special comment syntax
  • Implement additional modes for file merges. The standard so far was to keep both conflicting elements. Not the --merge-preference option can be used to always use the existing version or the new version instead.
  • Add a manual for a2ltool.
  • Support non-standard SYMBOL-LINK notation, where the compile unit name is used as a prefix of the real symbol name
  • Implement the ability to update VAR_ADDRESS info of VAR_CHARACTERISTIC
  • Handle negative bit-offsets in DWARF2 debug info correctly instead of panicing
  • Increase the size of the containing type for bitfields that extend past the end of their nominal containig type.
  • Add more plausibility checks to --check

Version 2.7.0

  • support C++ references in the DWARF debug data reader
  • update to a2lfile 3.0.0
    • Comments are now preserved in some cases. Specifically, any comment that occurs in a position where a block is permitted can be can be represented in the data, and is written to the output file. Sorting a2l files erases comments.
    • The values of BIT_MASK and error mask are u64 instead of u32, and parsing no longer fails for values that don't fit in u32.
    • Allow multiple CALIBRATION_HANDLEs inside of CALIBRATION_METHOD (by Rainer Zaiser)

Version 2.6.0

  • handle offset values other than zero in SYMBOL_LINK Offset values are still restricted to only point to the beginning of values, and cannot refer to e.g. the second byte of a 32-bit value.
  • update to a2lfile 2.5.0, which brings some bug fixes:
    • improvements for the merge function:
      • TYPEDEF_CHARACTERISTIC may reference a MEASUREMENT, but this reference was not updated during merges
      • USER_RIGHTS can no longer get duplicate user entries as a result of the merge
      • all items are merged in the order in which they appear in the merge file. Previously they were merged in reverse order
    • During checking, accept references from an AXIS_PRS_REF or CURVE_AXIS_REF of a TYPEDEF_CHARACTERISTIC to a structure component of the containing structure using the notation THIS.component_name.

Version 2.5.0

  • Support program information in PDB format The new option --pdbfile can be used instead of --elffile in order to read address and data type information from a PDB file. This supports the "virtual ECU" use case, where some parts of a microcontroller application are built on Windows and run inside a simulation environment.
  • Improve the limit adjustment logic If an object with a 64-bit float data type had a compu-method, the limit calculation could produce +-INF. This has been prevented.
  • Update to a2lfile 2.4.0, which brings the following improvements:
    • The handling of /include normlizes the path separators, so that Windows paths work on Linux (by @AkhilTThomas)
    • a2l checker improvements:
      • The RECORD_LAYOUT used by a CHARACTERISTIC must contain FNC_VALUES
      • A RECORD_LAYOUT must contain an AXIS_PTS_X/Y/Z for each internal axis
      • There should be a specific number of AXIS_DESCR depending on the type of RECORD_LAYOUT
      • The lower and upper limits of CHARACTERISTICs, MEASUREMENTs and AXIS_PTS are checked for plausibility based on the data type of the item and its COMPU_METHOD.
  • Bugfix: in some cases IF_DATA of newly merged files was not updated
  • Bugfix: For both DWARF and PDB input the signedness of enums is now read and used. Previously all enums were treated as unsigned.
  • Expanded and improved unit tests
  • a new relase workflow automatically builds binaries for Windows and Linux

Version 2.4.0

  • Document and validate the ability to use exe/DWARF2+ files, which are produced by MinGW gcc. In practice support for these files has always existed because the object crate transparently supports getting sections from exe files.
  • Allow greater control over the a2l update process
    • The option --update can now take an argument FULL or ADDRESSES (if the argument is not provided it defaults to FULL) Mode FULL updates addresses, datatypes, upper and lower limits, etc. It is a comprehensive update of all information in the a2l file. The mode ADDRESSES only updates the addresses, leaving everything else untouched.
    • The option --upate-preserve has been removed. Instead there is not --update-mode, which works in combination with --update Update mode STRICT verifies all information in the al2 file. If anything other than the addresses would be modified, then a2lfile reports an error. Update mode PRESERVE PRESERVE behaves like --update-preserve, and keeps unknown objects. Update mode DEFAULT (or omitting the option entirely) allows incorrect information, and discards invalid blocks.
  • Upgrade to a2lfile 2.3.2
    • Bugfix: Escape codes \r, \n and \t in quoted strings were not handled correctly while writing files
  • Bugfix: support the case where a compiler omits type information after the volatile tag for "volatile void*"

Version 2.3.0

  • Bugfix: Handle the case of incomplete DWARF type info C allows incomplete type declarations. For example "struct foo;" without a definition only tells the compiler that his type exists, and results in a stub type entry with the attribute DW_AT_declaration in the DWARF data.
  • upgrade to a2lfile 2.3.1
    • change the behavior of merge for GROUPS and FUNCTION Previously, if two GROUPS in a merge had the same name, then the incoming group was renamed with the suffix ".MERGE". Now the content for GROUPs/FUNCTIONs with the same name is combined.
    • a2l checker improvements: fix several bugs, and handle some additional cases
  • In strict mode, any problems detected by --check now cause a2ltool to exit with an error code. Outside of strict mode, --check remains informational.

Version 2.2.0

  • upgrade to a2lfile 2.2.0
    • Bugfix: during merges, some items might be renamed to prevent name collisions, but not all references to renamed items were updated inside of TYPEDEF_*
    • Successfully parse non-standard a2l files which contain hex-encoded integers where the parser expects a float value. (by @louiscaron)
  • Add the ability to remove items by regex. This will remove any CHARACTERISTIC, MEASUREMENT or INSTANCE whose name matches. Removal happens before insertion, if both are done in the same run.
  • Change the behavior of insertion by regex: the regex must match the whole variable name, instead of any substring inside it. This makes insertion more precise, but some regexes that worked previously will need to be extended with .*

Version 2.1.1

  • Bugfix: Don't fail to read DWARF type info if it contains any of the attributes packed, atomic, restrict, or immutable.
  • During update, set ECU_ADDRESSes that were "0" to hexadecimal display mode

Version 2.1.0

  • Enable the use of response files on the command line, using an @filename argument
  • display XCPplus parameters in --show-xcp

Version 2.0.2

  • update to a2lfile 2.1.0
    • add handling for /include inside A2ML (by @louiscaron)
    • fix multi-level /include inside A2L

Version 2.0.1

  • Fix issue #30: don't remove the BIT_MASK from elements during update (by @louiscaron)
  • Fix issue #32: the COMPU_METHOD must be taken into account while updating the data limits
  • Fix: Performance regression from version 2.0.0

Version 2.0.0

  • upgrade to a2lfile 2.0.0
    • fix the definition of AR_COMPONENT
    • don't remove valid elements during cleanup
  • Create and update INSTANCEs and TYPEDEF_MEASUREMENTs if the file version is 1.7.1 and --enable-structures is set
  • Insert whole arrays of MEASUREMENTs and CHARACTERISTICs instead of separate items for each element if the array elements have a simple datatype
  • Items can now be inserted based on the containing elf section
  • Debug data reader improvements - extracted information should now be better and more complete With assistance and fixes by @oleid - Thanks!
  • Support XCP IF_DATA up to version 1.4 (previously only version 1.2 was supported)
  • Use new array notation if the file version is 1.7.0 or newer - "[x]" instead of "._x_"
  • Fix the BIT_MASK attribute for big-endian targets
  • Remove a stray debug print that caused message spam while inserting CHARACTERISTICs

Version 1.6.0

  • Upgrade to a2lfile version 1.5.0
    • Ensure that the components of a RECORD_LAYOUT are written in the correct order
    • fix the definitions if the OVERWRITE and REF_MEMORY_SEGMENT elements
    • be more strict about a2l versions, and reject unknown ones
    • improved error handling for invalid identifiers
  • Bugfix: handle inherited members of C++ classes correctly
  • Correctly read array information from the DWARF debug data even if it does not have a size attribute Contributed by @oleid
  • reduce clap and regex versions in order to be compatible with rustc 1.63 on Debian stable Contributed by @oleid
  • add an option to change the a2l file version. This option deletes any elements that are unsupported in the target version.

Version 1.5.0

Upgrade to the a2lfile crate version 1.4.0 Allow a2ltool to load and merge a2l fragments. An a2l fragment is a file that contains only the content of a MODULE, but none of the surrounding elements. Upgrade all dependencies; one of these (rustix, an indirect dependency) had a vulnerability that is fixed in the latest version.

Version 1.4.4

Upgrade to the a2lfile crate version 1.3.4, to get a fix in the a2l parser. Previous versions were unable to handle some strings with double "" escapes, e.g. "some ""text"" here"

Version 1.4.3

Improve the formatting of the --help message by

  • enabling color
  • enabling automatic wrapping of the descriptons

Add basic usage examples to the README, since some people seemed confused

Version 1.4.2

Upgrade to the a2lfile crate version 1.3.3. This brings:

  • The double quotes around filenames in /include are no longer mandatory; quotes are only required if the path contains spaces. Fixed by @jl-rbpt
  • The a2ml parser had a bug that prevented the datatype uint64 from being recognized
  • Handling of USER_RIGHTS block during merging is improved, so that duplicate blocks will not be created any more
  • Extra spaces will no longer be added to A2ML blocks during writing

Version 1.4.1

Version 1.4.1 contains one bug fix compared to 1.4.0:

  • C++ Symbol demangling was incorrectly applied to both variable names and names of struct members. A trivial example is that "c" can be demangled to "const", so "somestruct.c" would be demangled to "somestruct.const" and then updating / inserting would fail. The handling of name demangling has been changed completely and should make much more sense now.

Version 1.4.0

Changes since version 1.3:

  • upgrade to a2lfile 1.3.2, which fixes a mistake in the parsing of REF_UNIT
  • upgrade clap from 2.34 to 4.0. The layout and look of the --help text changes, but all functionality should remain unchanged
  • bug fix for one case where it was possible to create duplicate measurements or characteristics

Version 1.3.0

Upgrade to the a2lfile crate version 1.3.0. This brings:

  • perfect support for all of a2l version 1.7.1
  • a bug fix in the tokenizer. It didn't handle strings that end in \" correctly and files that had such strings could not be loaded

Version 1.2.0

  • add --cleanup wich cleans up unused or useless items in the file It removes empty groups and functions, as well as unused compu_methods, compu_tabs, record_layouts and units.
  • add --target-group which allows new items created by --measurement[...] and --characteristic[...] to be directly added to a group
  • minor formatting improvements

Version 1.1.0

  • rename --insert-characteristic to --characteristic and --insert-measurement to --measurement. The old names remain as aliases, though they are not shown by --help.
  • add --measurement-range and --characteristic-range. Each of these takes a start address and an end address and inserts all variables found in this range into the a2l file.
  • add --measurement-regex and --characteristic-regex. Each of these takes a regex pattern. Any variable matching the pattern will be inserted into the a2l file. Example: [...] --characteristic-regex "TuningData" [...] would insert TuningData1 and TuningData2, and also DefaultTuningData Example: [...] --measurement-regex "^TestVar\._0_.*" [...] would insert TestVar._0_.member, but not TestVar._1_.member
  • Bugfix: the output path is no longer restricted to valid utf-8

Version 1.0.1

  • fix a bug where referring to array elements using angle brackets (array[0]) did not work corrctly
  • fix a bug in --insert-characteristic and --insert-measurement where these could only reference variables, but not array elements or struct members
  • allow creating new a2l files using the option --create

Version 1.0.0

  • initial stable release

License

a2ltool is dual-licensed under the MIT and APACHE2 licenses

MIT license

The MIT License (MIT)

Copyright (c) 2021 Daniel Thaler

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Apache2 license

                             Apache License
                       Version 2.0, January 2004
                    http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

  1. Definitions.

    "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.

    "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.

    "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.

    "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.

    "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.

    "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.

    "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).

    "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.

    "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."

    "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.

  2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.

  3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.

  4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:

    (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and

    (b) You must cause any modified files to carry prominent notices stating that You changed the files; and

    (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and

    (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.

    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.

  5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.

  6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.

  7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.

  8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.

  9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

  To apply the Apache License to your work, attach the following
  boilerplate notice, with the fields enclosed by brackets "[]"
  replaced with your own identifying information. (Don't include
  the brackets!)  The text should be enclosed in the appropriate
  comment syntax for the file format. We also recommend that a
  file or class name and description of purpose be included on the
  same "printed page" as the copyright notice for easier
  identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.