This document describes the current behavior of dtsformat, how configuration works, and what parts of DTS syntax the formatter currently handles well.
dtsformat is a formatter for .dts and .dtsi files.
It is designed for:
- Linux-style DTS sources
- Zephyr overlays and DTS files
- Zephyr files that contain C preprocessor directives such as
#includeand#ifdef
It is not a full semantic parser. The current implementation is a DTS-aware token formatter with layout rules for common DTS structures.
meson setup build
env CCACHE_DISABLE=1 meson compile -C buildBasic usage:
./build/dtsformat [--in-place] [--config PATH] [FILE ...]Options:
--in-place,-iWrite the formatted output back to the input file.--config PATHUse an explicit config file instead of searching for.dtsformat.--help,-hShow usage.
If no file is passed, input is read from stdin and output is written to stdout.
The formatter searches for .dtsformat starting from the directory of the input file and walking upward toward the filesystem root.
When formatting stdin, it searches upward starting from the current working directory.
Example .dtsformat:
UseTab: Never
IndentWidth: 4
ColumnLimit: 88Supported keys are:
Controls whether indentation is emitted with tabs or spaces.
Allowed values:
AlwaysNever
Notes:
- When
UseTab: Alwaysis used, indentation levels are written as tabs. IndentWidthstill exists in config for consistency, but tab indentation is emitted as tabs rather than being expanded into spaces.
Positive integer.
Used when UseTab: Never.
Example:
IndentWidth: 2Positive integer.
Used as a wrapping target for long property values and collections. The formatter tries to keep output under this limit, but exact wrapping is heuristic rather than guaranteed for every token sequence.
The formatter currently normalizes:
- node indentation
- spaces around
= - spaces around bitwise
| - spaces after list commas when they are separators rather than part of a DTS property name
- property continuation indentation
- wrapping of long
<...>and[...]values - standalone line comments and block comments
/include/ "file.dtsi"directives- preprocessor lines such as
#include,#ifdef,#endif,#define, and related directives - preservation of at most one empty line from the input
Comments are emitted as standalone formatted lines.
This is important for DTS properties like:
map =
// Left
<0>, <1>, <2>, <3>,
// Right
<4>, <5>, <6>, <7>;
Without explicit handling, comments in the middle of a property value tend to collapse onto the same line as = or a list item.
The formatter keeps them on their own continuation line.
The formatter supports both of these styles:
/include/ "soc.dtsi"
#include "board.dtsi"Preprocessor directives are preserved as directive lines. This includes common forms such as:
#include#if#ifdef#ifndef#elif#else#endif#define#undef#error#pragma#line
The formatter distinguishes these from DTS properties such as #address-cells and #size-cells.
The formatter preserves vertical separation from the input, but normalizes runs of multiple blank lines down to one empty line.
That means:
- one empty line stays one empty line
- two or more consecutive empty lines become one empty line
- no blank line is inserted unless it already exists in the source or is required by normal formatting rules
The repository uses fixture-based tests driven by Python and Meson.
Current fixture coverage includes:
- Linux-style formatting
- Zephyr tab-based formatting
/include/handling- preprocessor directive handling
- blank-line preservation
- comments inside array/list property values
Run tests with:
env CCACHE_DISABLE=1 meson test -C build --print-errorlogsCurrent limitations include:
- formatting is token/layout based rather than AST-based
- line wrapping is heuristic and not guaranteed to be globally optimal
- very complex macro-heavy preprocessed DTS input may still need additional rules
- the config format intentionally supports only a small subset of
.clang-format-style key/value behavior
src/main.c: CLI, file IO, config resolution, in-place formattingsrc/config.c:.dtsformatparsing and config discoverysrc/formatter.c: tokenization and formatting rulestests/test_formatter.py: fixture runnertests/fixtures/: regression cases