Richard W.M. Jones
2016-Apr-04 15:51 UTC
[Libguestfs] [PATCH FOR DISCUSSION ONLY 1/2] scripts: Add a script for formatting all C code in the project.
~~~ Not to be applied, for discussion only ~~~ I think we need some kind of "checkpatch" script to catch all the annoying, nitpicky code style issues that submitters trip up on. I looked at a few scripts that exist, primarily the ones from Linux and qemu (massive and complicated), and libvirt (small and sane). There are a couple of problems: (1) Linux/qemu-style checkpatch only verifies new code that is submitted, leaving the old code in its current, possibly inconsistent state. (2) The libvirt one only checks a whitelist of known issues (but actually, it's still quite a good script). I thought a different approach might be to run 'indent' across the whole code base. As long as we force the indent style settings, and get submitters and reviews to run the command, then it should ensure all our code, past and future, has a consistent style. GNU indent isn't very good for this, but clang-format is a lot more configurable. Therefore: the first commit adds a wrapper around clang-format which runs it with the correct settings, and also does a bit of post- processing. Note you need clang-format 3.8.0, currently available in Fedora 24+ The second patch shows the changes that would be made. It's not too bad, but there are some problems: (a) The way struct initializers are formatted is weird. I'm not even sure I understand what rules clang is following, since structs get all sorts of different styles with no rhyme or reason. (b) It splits up long string constants (although it doesn't resplit string constants which are already sufficiently split). (c) It gets horribly confused by our start_element()...end_element() XML macros. This doesn't solve the whole problem. We would still need further scripts to look for problems such as: (i) Error messages terminated/not terminated by full stop. (ii) Not calling reply_with_* functions on error paths. and so on. Rich.
Richard W.M. Jones
2016-Apr-04 15:51 UTC
[Libguestfs] [PATCH FOR DISCUSSION ONLY 1/2] scripts: Add a script for formatting all C code in the project.
Note this requires clang-format from clang >= 3.8.0 (3.7.0 is too old as it does not have the BreakBeforeBraces: Custom style). --- .gitignore | 1 + scripts/code-format.pl | 146 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100755 scripts/code-format.pl diff --git a/.gitignore b/.gitignore index ca4e89c..ad166d2 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ cscope.out Makefile Makefile.in +/.clang-format /.sc-* /ABOUT-NLS /aclocal.m4 diff --git a/scripts/code-format.pl b/scripts/code-format.pl new file mode 100755 index 0000000..f4c1f34 --- /dev/null +++ b/scripts/code-format.pl @@ -0,0 +1,146 @@ +#!/usr/bin/perl -w +# libguestfs +# Copyright (C) 2016 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Reformat the code in libguestfs (currently only C code). + +use warnings; +use strict; + +use YAML qw(DumpFile); + +# Check we are run from the top level directory. +die "$0: you must run this script from the top level source directory\n" + unless -f "BUGS"; + +# Make sure we have the clang-format program. +system ("clang-format --help >/dev/null 2>&1") == 0 + or die "$0: 'clang-format' program (from Clang) must be installed\n"; + +my @c_files = `git ls-files '*.[ch]'`; +chomp @c_files; + +# http://clang.llvm.org/docs/ClangFormatStyleOptions.html +my $clang_stylesheet = { + Language => "Cpp", + AccessModifierOffset => -2, + AlignAfterOpenBracket => "true", + AlignConsecutiveAssignments => "false", + AlignEscapedNewlinesLeft => "false", + AlignOperands => "true", + AlignTrailingComments => "true", + AllowAllParametersOfDeclarationOnNextLine => "true", + AllowShortBlocksOnASingleLine => "false", + AllowShortCaseLabelsOnASingleLine => "false", + AllowShortFunctionsOnASingleLine => "All", + AllowShortIfStatementsOnASingleLine => "false", + AllowShortLoopsOnASingleLine => "false", + AlwaysBreakAfterDefinitionReturnType => "TopLevel", + AlwaysBreakBeforeMultilineStrings => "false", + AlwaysBreakTemplateDeclarations => "false", + BinPackArguments => "true", + BinPackParameters => "true", + BraceWrapping => { + AfterClass => "false", + AfterControlStatement => "false", + AfterEnum => "false", + AfterFunction => "true", + AfterNamespace => "true", + AfterObjCDeclaration => "false", + AfterStruct => "true", + AfterUnion => "true", + BeforeCatch => "false", + BeforeElse => "false", + #AfterIndentBraces => "false", -- only in clang > 3.8.0 + }, + BreakBeforeBinaryOperators => "None", + BreakBeforeBraces => "Custom", + BreakBeforeTernaryOperators => "true", + BreakConstructorInitializersBeforeComma => "false", + #BreakStringLiterals => "false", -- only in clang > 3.8.0 + ColumnLimit => 76, + CommentPragmas => "^ IWYU pragma:", + ConstructorInitializerAllOnOneLineOrOnePerLine => "false", + ConstructorInitializerIndentWidth => 4, + ContinuationIndentWidth => 4, + Cpp11BracedListStyle => "false", + DerivePointerAlignment => "false", + DisableFormat => "false", + ExperimentalAutoDetectBinPacking => "false", + ForEachMacros => [], + IndentCaseLabels => "false", + IndentWidth => 2, + IndentWrappedFunctionNames => "false", + KeepEmptyLinesAtTheStartOfBlocks => "true", + MacroBlockBegin => "", + MacroBlockEnd => "", + MaxEmptyLinesToKeep => 1, + NamespaceIndentation => "None", + ObjCBlockIndentWidth => 2, + ObjCSpaceAfterProperty => "false", + ObjCSpaceBeforeProtocolList => "true", + PenaltyBreakBeforeFirstCallParameter => 19, + PenaltyBreakComment => 300, + PenaltyBreakFirstLessLess => 120, + PenaltyBreakString => 1000, + PenaltyExcessCharacter => 1000000, + PenaltyReturnTypeOnItsOwnLine => 60, + PointerAlignment => "Right", + SortIncludes => "false", + SpaceAfterCStyleCast => "false", + SpaceBeforeAssignmentOperators => "true", + SpaceBeforeParens => "Always", + SpaceInEmptyParentheses => "false", + SpacesBeforeTrailingComments => 1, + SpacesInAngles => "false", + SpacesInContainerLiterals => "true", + SpacesInCStyleCastParentheses => "false", + SpacesInParentheses => "false", + SpacesInSquareBrackets => "false", + Standard => "Cpp11", + TabWidth => 8, + UseTab => "Never", +}; +DumpFile (".clang-format", $clang_stylesheet); + +# Run clang-format on each file, then post-process the output further. +foreach my $input (@c_files) { + my @o = (); + + open INPUT, "clang-format $input |" + or die "clang-format: $input: $!"; + push @o, $_ while <INPUT>; + close INPUT or die; + + # Post-process the output. + my ($i, $j); + for ($i = 0; $i < @o; ++$i) { + # rewrite gettext _ ("") -> _("") + if (($o[$i] =~ s{_ \("}{_("}g) == 1) { + # If the following lines are strings, assume a continuation + # string and reduce its indent by 1 character. + for ($j = $i+1; $j < @o; ++$j) { + last if ($o[$j] =~ s{^(\s+)\s"}{$1"}) == 0; + } + } + } + + # Overwrite the original file with the output. + open OUTPUT, "> $input" or die "$input: $!"; + print OUTPUT $_ foreach @o; + close OUTPUT; +} -- 2.7.4
Seemingly Similar Threads
- [PATCH v2 FOR DISCUSSION ONLY 1/2] scripts: Add a script for formatting all C code in the project.
- [PATCH 0/2] [clang-format] Add new configurations
- [LLVMdev] LLVM for crosscompiling?
- mac osx, g95 package port problem
- [PATCH libnbd discussion only 0/5] api: Implement concurrent writer.