diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..a9722db2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,63 @@ +--- +Language: Cpp +BasedOnStyle: LLVM + +AccessModifierOffset: -4 + +AlignAfterOpenBracket: DontAlign +AlignEscapedNewlinesLeft: true +# AlignOperands: true +AlignTrailingComments: true + +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false + +AlwaysBreakAfterDefinitionReturnType: All +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false + +# BinPackArguments: false +# BinPackParameters: true + +BreakBeforeBinaryOperators: false +BreakBeforeBraces: Custom +BraceWrapping: { AfterFunction: true } +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true + +ColumnLimit: 80 + +ContinuationIndentWidth: 4 + +DerivePointerAlignment: false #XXX +DisableFormat: false +ExperimentalAutoDetectBinPacking: false #XXX +ForEachMacros: [ LIST_FOREACH, SIMPLEQ_FOREACH, CIRCLEQ_FOREACH, TAILQ_FOREACH, TAILQ_FOREACH_REVERSE, HT_FOREACH ] + +IndentCaseLabels: false +IndentFunctionDeclarationAfterType: false +IndentWidth: 4 +IndentWrappedFunctionNames: false + +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 2 + +PointerAlignment: Right #XXX + +# SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +Standard: Cpp03 +TabWidth: 4 +UseTab: Always +SortIncludes: false +... diff --git a/.uncrustify b/.uncrustify new file mode 100644 index 00000000..da2daa13 --- /dev/null +++ b/.uncrustify @@ -0,0 +1,55 @@ +input_tab_size = 8 +output_tab_size = 8 +indent_with_tabs = 2 +indent_cmt_with_tabs = false +indent_brace_parent = false +indent_func_call_param = true +indent_func_def_param = true +sp_enum_before_assign = add +sp_enum_after_assign = add +sp_inside_paren = remove +sp_paren_brace = add +sp_before_ptr_star = add +sp_before_unnamed_ptr_star = add +sp_between_ptr_star = remove +sp_after_ptr_star = remove +sp_after_ptr_star_func = add +sp_before_ptr_star_func = add +sp_before_sparen = add +sp_inside_sparen = remove +sp_inside_sparen_close = remove +sp_after_sparen = add +sp_sparen_brace = add +sp_special_semi = remove +sp_before_semi_for = remove +sp_after_comma = add +sp_after_cast = remove +sp_inside_braces_struct = add +sp_type_func = remove +sp_func_def_paren = remove +sp_inside_fparen = remove +sp_fparen_brace = add +sp_func_call_paren = remove +sp_else_brace = add +sp_after_oc_block_caret = remove +align_keep_tabs = true +align_with_tabs = true +align_on_tabstop = true +nl_fcall_brace = remove +nl_enum_brace = remove +nl_struct_brace = remove +nl_union_brace = remove +nl_if_brace = remove +nl_brace_else = remove +nl_elseif_brace = remove +nl_else_brace = remove +nl_else_if = remove +nl_for_brace = remove +sp_after_semi_for_empty = remove +nl_while_brace = remove +nl_do_brace = remove +nl_brace_while = remove +nl_switch_brace = remove +nl_func_type_name = add +nl_fdef_brace = add +mod_paren_on_return = ignore diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..38756939 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,35 @@ +# Contributing to the libevent + +## Coding style + +First and most generic rule: **just look around**. + +But, we have a script for checking patches/files/git-refs: +```shell +# Chech HEAD git ref +./checkpatch.sh -r +./checkpatch.sh -r HEAD + +# Check patch +git format-patch --stdout -1 | ./checkpatch.sh -p +git show -1 | ./checkpatch.sh -p + +# Or via regular files +git format-patch --stdout -2 +./checkpatch.sh *.patch + +# Over a file +./checkpatch.sh -d event.c +./checkpatch.sh -d < event.c + +# And print the whole file not only summary +./checkpatch.sh -f event.c +./checkpatch.sh -f < event.c + +# See +./checkpatch.sh -h +``` + +## Testing +- Write new unit test in `test/regress_{MORE_SUITABLE_FOR_YOU}.c` +- `make verify` diff --git a/checkpatch.sh b/checkpatch.sh new file mode 100755 index 00000000..6eaa19c4 --- /dev/null +++ b/checkpatch.sh @@ -0,0 +1,299 @@ +#!/usr/bin/env bash + +# TODO: +# - inline replace +# - clang-format-diff replacement +# - uncrustify for patches (not git refs) +# - maybe integrate into travis-ci? + +function usage() +{ + cat <&2 + exit 1 +} +function default_arg() +{ + if [ "${options[ref]}" -eq 1 ]; then + echo "HEAD" + else + [ ! -t 0 ] || abort " is a tty" + echo "/dev/stdin" + fi +} +function parse_options() +{ + options[patch]=0 + options[file]=0 + options[file_diff]=0 + options[ref]=1 + options[clang]=1 + options[uncrustify]=0 + options[cfg]= + + local OPTARG OPTIND c + while getopts "pfrdCUc:h?" c; do + case "$c" in + p) + options[patch]=1 + options[ref]=0 + options[file]=0 + options[file_diff]=0 + ;; + f) + options[file]=1 + options[ref]=0 + options[patch]=0 + options[file_diff]=0 + ;; + r) + options[ref]=1 + options[file]=0 + options[patch]=0 + options[file_diff]=0 + ;; + d) + options[file_diff]=1 + options[file]=0 + options[patch]=0 + options[ref]=0 + ;; + C) + options[clang]=1 + options[uncrustify]=0 + ;; + U) + options[uncrustify]=1 + options[clang]=0 + ;; + c) options[cfg]="$OPTIND" ;; + ?|h) + usage + exit 0 + ;; + *) + usage + exit 1 + ;; + esac + done + + options[cfg]="$(cfg)" + + [ -f "${options[cfg]}" ] || \ + abort "Config '%s' does not exist" "${options[cfg]}" + + shift $((OPTIND - 1)) + args=( "$@" ) + + if [ ${#args[@]} -eq 0 ]; then + # exit on error globally, not only in subshell + default_arg > /dev/null + args=( "$(default_arg)" ) + fi + + if [ "${args[0]}" = "/dev/stdin" ]; then + TMP_FILE="/tmp/libevent.checkpatch.$RANDOM" + cat > "$TMP_FILE" + trap "rm '$TMP_FILE'" EXIT + + args[0]="$TMP_FILE" + fi +} + +function diff() { command diff --color=always "$@"; } + +function clang_style() +{ + local c="${options[cfg]}" + echo "{ $(sed -e 's/#.*//' -e '/---/d' -e '/\.\.\./d' "$c" | tr $'\n' ,) }" +} +function clang_format() { clang-format --style="$(clang_style)" "$@"; } +function clang_format_diff() { clang-format-diff --style="$(clang_style)" "$@"; } +# for non-bare repo will work +function clang_format_git() +{ git format-patch --stdout "$@" -1 | clang_format_diff; } + +function uncrustify() { command uncrustify -c "${options[cfg]}" "$@"; } +function uncrustify_frag() { uncrustify -l C --frag "$@"; } +function uncrustify_indent_off() { echo '/* *INDENT-OFF* */'; } +function uncrustify_indent_on() { echo '/* *INDENT-ON* */'; } +function git_hunk() +{ + local ref=$1 f=$2 + shift 2 + git cat-file -p $ref:$f +} +function uncrustify_git_indent_hunk() +{ + local start=$1 end=$2 + shift 2 + + # Will be beatier with tee(1), but doh bash async substitution + { uncrustify_indent_off; git_hunk "$@" | head -n$((start - 1)); } + { uncrustify_indent_on; git_hunk "$@" | head -n$((end - 1)) | tail -n+$start; } + { uncrustify_indent_off; git_hunk "$@" | tail -n+$((end + 1)); } +} +function strip() +{ + local start=$1 end=$2 + shift 2 + + # seek indent_{on,off}() + let start+=2 + head -n$end | tail -n+$start +} +function patch_ranges() +{ + egrep -o '^@@ -[0-9]+(,[0-9]+|) \+[0-9]+(,[0-9]+|) @@' | \ + cut -d' ' -f3 +} +function git_ranges() +{ + local ref=$1 f=$2 + shift 2 + + git diff -W $ref^..$ref -- $f | patch_ranges +} +function diff_substitute() +{ + local f="$1" + shift + + sed \ + -e "s#^--- /dev/fd.*\$#--- a/$f#" \ + -e "s#^+++ /dev/fd.*\$#+++ b/$f#" +} +function uncrustify_git() +{ + local ref=$1 r f start end length + shift + + local files=( $(git diff --name-only $ref^..$ref | egrep "\.(c|h)$") ) + for f in "${files[@]}"; do + local ranges=( $(git_ranges $ref "$f") ) + for r in "${ranges[@]}"; do + [[ ! "$r" =~ ^\+([0-9]+)(,([0-9]+)|)$ ]] && continue + start=${BASH_REMATCH[1]} + [ -n "${BASH_REMATCH[3]}" ] && \ + length=${BASH_REMATCH[3]} || \ + length=1 + end=$((start + length)) + echo "Range: $start:$end ($length)" >&2 + + diff -u \ + <(uncrustify_git_indent_hunk $start $end $ref "$f" | strip $start $end) \ + <(uncrustify_git_indent_hunk $start $end $ref "$f" | uncrustify_frag | strip $start $end) \ + | diff_substitute "$f" + done + done +} +function uncrustify_diff() { abort "Not implemented"; } +function uncrustify_file() { uncrustify -f "$@"; } + +function checker() +{ + local c=$1 u=$2 + shift 2 + + [ "${options[clang]}" -eq 0 ] || { + $c "$@" + return + } + [ "${options[uncrustify]}" -eq 0 ] || { + $u "$@" + return + } +} +function check_patch() { checker clang_format_diff uncrustify_diff "$@"; } +function check_file() { checker clang_format uncrustify_file "$@"; } +function check_ref() { checker clang_format_git uncrustify_git "$@"; } + +function check_arg() +{ + [ "${options[patch]}" -eq 0 ] || { + check_patch "$@" + return + } + [ "${options[file]}" -eq 0 ] || { + check_file "$@" + return + } + [ "${options[file_diff]}" -eq 0 ] || { + diff -u "$@" <(check_file "$@") | diff_substitute "$@" + return + } + [ "${options[ref]}" -eq 0 ] || { + check_ref "$@" + return + } +} + +function main() +{ + local a + for a in "${args}"; do + check_arg "$a" + done +} + +declare -A options +parse_options "$@" + +main "$@" | less -FRSX