diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..d9c131172 --- /dev/null +++ b/.clang-format @@ -0,0 +1,551 @@ +--- +### Clang-format adapted to Unit +# +# git integration docs: https://clang.llvm.org/docs/ClangFormat.html#git-integration +# +# Used tags for certain rules: +# - @NOTUSED for everything that's seemingly not used +# - @DOUBLECHECK the correct value for the rule. +# - @NEEDSTESTING needs to see what this rule actually does +# - @DEPRECATED option is no longer used, kept for backwards comp +# - @V20 option is only available in version 20 that's not released yet +# - @CHECKED for options that were double check and actually matter. + +Language: Cpp +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#language +# Per the documentation, this should be used for C and C++ languages. + +AlignAfterOpenBracket: Align +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignafteropenbracket +# No guidance in confluence, existing code suggests Align. + +AlignArrayOfStructures: Left +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignarrayofstructures +# No guidance in confluence. Leaving it as is. + +AlignConsecutiveAssignments: + AcrossComments: true + AcrossEmptyLines: true + AlignCompound: true + Enabled: false + PadOperators: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignconsecutiveassignments +# Has guidance in confluence under variables. + +AlignConsecutiveBitFields: + AcrossComments: true + AcrossEmptyLines: true + Enabled: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignconsecutivebitfields +# Some guidance in confluence, mainly around variable alignment. + +AlignConsecutiveDeclarations: + AcrossComments: true + AcrossEmptyLines: true + AlignFunctionPointers: false + Enabled: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignconsecutivedeclarations +# Guidance in confluence. + +AlignConsecutiveMacros: + AcrossComments: true + AcrossEmptyLines: false + Enabled: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignconsecutivemacros +# No guidance in confluence, current Unit codebase suggests the above +# settings. + +AlignEscapedNewlines: Left +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignescapednewlines +# No guidance in confluence, but existing codebase suggests Right. + +AlignOperands: Align +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alignoperands +# Guidance in confluence. +# Related rules: BreakBeforeBinaryOperators +# AlignAfterOperator +# Need to double check: @DOUBLECHECK + +AlignTrailingComments: + Kind: Leave + OverEmptyLines: 2 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#aligntrailingcomments +# No guidance on trailing comment alignment besides "don't use this +# style of comments, keep to the traditional c /* ... */ comments." +# +# Code doesn't use // type of trailing comments. +# Code does use /*...*/ type of trailing comments. +# +# @NEEDSTESTING + +AllowAllArgumentsOnNextLine: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowallargumentsonnextline +# No guidance. Code seems to not want to put all args onto newline. +# +# @CHECKED, doesn't have an effect in either true or false, keep it tho. + +AllowAllParametersOfDeclarationOnNextLine: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowallparametersofdeclarationonnextline +# No guidance. Code seems to not want to put all params onto newline. + +AllowShortBlocksOnASingleLine: Always +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowshortblocksonasingleline +# No guidance. There are only two total appearances of these short +# blocks in the entire codebase (find with regex `while.+\{.+\}`), and +# they are in the same line. + +AllowShortCaseExpressionOnASingleLine: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowshortcaseexpressiononasingleline +# No guidance. This doesn't seem to be used in the codebase, or every +# use is multiline. + +AllowShortCaseLabelsOnASingleLine: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowshortcaselabelsonasingleline +# No guidance, also either not used, or all uses are multiline. +# +# @CHECKED: this should be false, if it's true, there are SO MANY code +# changes that make reading things hard. + +AllowShortEnumsOnASingleLine: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowshortenumsonasingleline +# No guidance. Every enum in the codebase is multiline. +# +# @CHECKED: there are 3 places where this takes effect. Leaving it on +# false is the correct option for this codebase. + +AllowShortFunctionsOnASingleLine: All +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowshortfunctionsonasingleline + +AllowShortIfStatementsOnASingleLine: Never +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowshortifstatementsonasingleline +# No guidance, existing code seems to suggest this is Never. +# +# @CHECKED: This should be Never. All other values cause a lot of +# changes. + +AllowShortLoopsOnASingleLine: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#allowshortloopsonasingleline + +AlwaysBreakBeforeMultilineStrings: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#alwaysbreakbeforemultilinestrings + +BinPackArguments: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#binpackarguments +# No guidance, existing code suggests it should be false. +#  +# @CHECKED: this should be true. + +BinPackParameters: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#binpackparameters +# Same as above, existing code suggests it should be false. + +BitFieldColonSpacing: None +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#bitfieldcolonspacing +# No guidance on this. There's one for binary and ternary operators, but +# this colon is not a binary op. Existing code suggests None. + +BraceWrapping: + AfterCaseLabel: true + AfterClass: false + AfterControlStatement: MultiLine + AfterEnum: false + AfterExternBlock: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: false + AfterUnion: false + BeforeCatch: true + BeforeElse: false + BeforeLambdaBody: true + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyNamespace: true + SplitEmptyRecord: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#bracewrapping +# Related: BreakBeforeBraces. +# Individual options that need context: +# AfterCaseLabel: all case blocks are non braced +#  AfterClass: we don't have classes +# AfterExternBlock: we don't have extern blocks +# AfterNamespace: we don't have namespaces +# AfterObjCDeclaration: we don't have objective c declarations +# BeforeCatch: we don't have try-catch blocks +# IndentBraces: we don't seem to wrap braces, so this is unused. +# SplitEmptyFunction: needs AfterFunction to be true, unused. +# SplitEmptyRecord: needs AfterClass, and we don't have classes. +# SplitEmptyNamespace: needs AfterNamespace, and we don't have nss. + +BreakAdjacentStringLiterals: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakadjacentstringliterals +# No guidance. There are a lot more instances of breaking than sinlge +# line adjacent string literals. See the following regexes: +# `".+"\s+".+"` for single line literals and +# `".+"\n\s+".+"` for multi line literals + +BreakAfterReturnType: AllDefinitions +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakafterreturntype +# No guidance. Looking at the code, TopLevel seems to be the correct +# value here, but it needs testing. +# @DOUBLECHECK + +BreakBeforeBinaryOperators: All +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakbeforebinaryoperators +# No guidance on this one, only spacing. Code comments suggest this +# should be All. + +BreakBeforeBraces: Custom +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakbeforebraces +# No guidance. This is Custom, so individually set options on the +# BraceWrapping option get used. + +BreakBeforeTernaryOperators: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakbeforeternaryoperators +# No guidance, only spacing. Similar option to +# BreakBeforeBinaryOperators. + +BreakConstructorInitializers: BeforeColon +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakconstructorinitializers +# No guidance. I don't think this is used, but need to double check. +# @DOUBLECHECK + +BreakFunctionDefinitionParameters: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakfunctiondefinitionparameters +# No guidance. Existing code looks like it's false. + +BreakStringLiterals: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#breakstringliterals +# No guidance. It seems like this is a true. + +ColumnLimit: 80 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#columnlimit +# No guidance, but previous conversations about line length suggests +# this should be 72, but codebase looks like it's using 80. + +CommentPragmas: '^ IWYU pragma:' +# No guidance, and this is confusing, leaving it as default LLVM value, +# but we do need to double check what this does. +# @DOUBLECHECK + +ConstructorInitializerIndentWidth: 4 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#constructorinitializerindentwidth +# Probably not used because we don't have constructors? +# @DOUBLECHECK + +ContinuationIndentWidth: 4 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#continuationindentwidth +# No guidance, existing code suggests this should be 4. + +DerivePointerAlignment: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#derivepointeralignment + +DisableFormat: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#disableformat +# We want to format, this needs to be true. + +IncludeBlocks: Preserve +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#includeblocks +# No guidance. Existing code suggests this is Preserve. +# See src/nxt_java.c as an example + +IndentAccessModifiers: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentaccessmodifiers +# No guidance. Existing code suggests this is false. + +IndentCaseBlocks: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentcaseblocks +# Guidance here: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide#goto-labels + +IndentCaseLabels: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentcaselabels +# Guidance here: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide#goto-labels + +IndentGotoLabels: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentgotolabels +# Guidance here: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide#goto-labels + +IndentPPDirectives: None +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentppdirectives +# No guidance, existing code says it's None. + +IndentWidth: 4 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentwidth +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide#Indentation + +IndentWrappedFunctionNames: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#indentwrappedfunctionnames +# No guidance. We do have a rule where the return types will have a +# break before the function name, so this isn't going to take effect. +# Related rule: BreakAfterReturnType +# @DOUBLECHECK + +InsertNewlineAtEOF: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#insertnewlineateof +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide#Indentation +# Is a newline at the end of file a trailing whitespace? Existing code +# seems to have newlines at EOF, so setting this to true. + +KeepEmptyLines: + AtEndOfFile: true + AtStartOfBlock: true + AtStartOfFile: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#keepemptylines +# No guidance. Existing code suggests these all should be false. + +LambdaBodyIndentation: Signature +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#lambdabodyindentation +# No guidance, code suggests this should be Signature. + +LineEnding: DeriveLF +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#lineending +# No guidance, the DeriveLF seems like a great choice here. + +MacroBlockBegin: '' +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#macroblockbegin +# No guidance. I don't actually know what this should be. +# @DOUBLECHECK + +MacroBlockEnd: '' +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#macroblockend +# Same as above. +# @DOUBLECHECK + +MainIncludeChar: Any +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#mainincludechar +# No guidance. I think this should be Any, because I've seen both quotes +# and angle brackets used. + +MaxEmptyLinesToKeep: 3 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#maxemptylinestokeep +# No guidance, existing code suggests this should be 2. + + +PenaltyBreakAssignment: 2 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltybreakassignment +# Not sure what this does. +# @DOUBLECHECK + +PenaltyBreakBeforeFirstCallParameter: 19 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltybreakbeforefirstcallparameter +# Not sure what this does. +# @DOUBLECHECK + +PenaltyBreakComment: 300 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltybreakcomment +# Not sure what this does. +# @DOUBLECHECK + +PenaltyBreakFirstLessLess: 120 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltybreakfirstlessless +# Not sure what this does. +# @DOUBLECHECK + +PenaltyBreakOpenParenthesis: 0 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltybreakopenparenthesis +# Not sure what this does. +# @DOUBLECHECK + +PenaltyBreakScopeResolution: 500 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltybreakscoperesolution +# Not sure what this does. +# @DOUBLECHECK + +PenaltyBreakString: 1000 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltybreakstring +# Not sure what this does. +# @DOUBLECHECK + +PenaltyBreakTemplateDeclaration: 10 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltybreaktemplatedeclaration +# Not sure what this does. +# @DOUBLECHECK + +PenaltyExcessCharacter: 1000000 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltyexcesscharacter +# Not sure what this does. +# @DOUBLECHECK + +PenaltyIndentedWhitespace: 0 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltyindentedwhitespace +# Not sure what this does. +# @DOUBLECHECK + +PenaltyReturnTypeOnItsOwnLine: 60 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#penaltyreturntypeonitsownline +# Not sure what this does. +# @DOUBLECHECK + +PointerAlignment: Right +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#pointeralignment +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide#Spaces + +PPIndentWidth: -1 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#ppindentwidth +# There are only 2 places in the codebase, it suggests this is -1. + +QualifierAlignment: Leave +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#qualifieralignment +# No guidance. Code suggests this shuold be Left, but the warning on the +# rule says we should leave it at Leave. +# @DOUBLECHECK + +ReferenceAlignment: Middle +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#referencealignment +# Same as the PointerAlignment ruleset. + +ReflowComments: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#reflowcomments +# No guidance, though I think this should be either Always or Never. +# @DOUBLECHECK + +RemoveBracesLLVM: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#removebracesllvm +# No guidance. This should be false, setting this to true might break +# existing functionality. + +RemoveParentheses: Leave +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#removeparentheses +# No guidance. This should also stay as Leave. +# @DOUBLECHECK + +RemoveSemicolon: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#removesemicolon + +SeparateDefinitionBlocks: Leave +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#separatedefinitionblocks + +SkipMacroDefinitionBody: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#skipmacrodefinitionbody + +SortIncludes: Never +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#sortincludes +# No guidance. I think this should be CaseSensitive. There are related +# options here. They are: +# - IncludeBlocks +# - IncludeCategories +# - IncludeIsMainRegex +# - IncludeIsMainSourceRegex + + +SpaceAfterCStyleCast: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spaceaftercstylecast +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide#Spaces + +SpaceAfterLogicalNot: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spaceafterlogicalnot +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide + +SpaceAroundPointerQualifiers: Default +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacearoundpointerqualifiers +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide +# Leaving as default to use PointerAlignment. + +SpaceBeforeAssignmentOperators: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacebeforeassignmentoperators +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide + +SpaceBeforeCaseColon: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacebeforecasecolon +# No guidance, existing code suggests this is false. + +SpaceBeforeParens: Custom +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacebeforeparens +# This will be fine tuned in the SpaceBeforeParensOptions. + +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDeclarationName: false + AfterFunctionDefinitionName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: true + AfterRequiresInExpression: true + BeforeNonEmptyParentheses: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacebeforeparensoptions +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide +# - AfterForeachMacros: we're not using this +# - AfterFunctionDefinitionName: no guidance, but code says false +# - AfterFunctionDeclarationName: no guidance, but code says false +# - AfterIfMacros: no guidance, we don't seem to use this +# - AfterOverloadedOperator: no guidance, we don't seem to use this +# - AfterPlacementOperator: no guidance, we don't seem to use this +# - AfterRequiresInClause: no guidance, we don't use templates +# - AfterRequiresInExpression: no guidance, we don't seem to use templates +# - BeforeNonEmptyParentheses: no guidance, this should be false + +SpaceBeforeRangeBasedForLoopColon: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacebeforerangebasedforloopcolon +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide#Spaces + +SpaceBeforeSquareBrackets: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacebeforesquarebrackets +# No guidance, existing code says it should be false. + +SpaceInEmptyBlock: true +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spaceinemptyblock + +SpacesInLineCommentPrefix: + Maximum: 3 + Minimum: 0 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacesinlinecommentprefix +# It might only apply to // comments, not /* */ comments. Turns out we +# use plenty // comments. +# @CHECKED, value locked in. + +SpacesInParens: Custom +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacesinparens +# Setting this to Custom, so the longer SpacesInParensOptions will apply. + +SpacesInParensOptions: + ExceptDoubleParentheses: true + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacesinparensoptions +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide +# - ExceptDoubleParentheses: no guidance, but existing code says true + +SpacesInSquareBrackets: false +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#spacesinsquarebrackets +# No guidance, existing code says false. + +StatementAttributeLikeMacros: + - Q_EMIT +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#statementattributelikemacros +# No guidance, I don't think we use this, but need to double check. +# @DOUBLECHECK + +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#statementmacros +# Not sure whether we use any of these, or there are others not here. +# @DOUBLECHECK + +TabWidth: 2 +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#tabwidth +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide + +TableGenBreakInsideDAGArg: DontBreak +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#tablegenbreakinsidedagarg +# I don't think we're using this. +# DOUBLECHECK + +UseTab: Never +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#usetab +# Guidance: https://nginxsoftware.atlassian.net/wiki/spaces/UNIT/pages/2376368523/Unit+Core+-+Developers+Guide +# This option could / should be AlignWithSpaces for accessibility purposes, +# leaving at Never for the time being. + +WhitespaceSensitiveMacros: + - BOOST_PP_STRINGIZE + - CF_SWIFT_NAME + - NS_SWIFT_NAME + - PP_STRINGIZE + - STRINGIZE +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#whitespacesensitivemacros +...