From 66a7cc3c345b29e2413a7a5e4cc8f9e234f61619 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Tue, 28 Apr 2020 15:34:47 +0200 Subject: [PATCH] check xs format --- .github/workflows/clangformat.yml | 5 + .github/workflows/clangformat/clang-format-xs | 114 ++++++++++++++++++ .github/workflows/clangformat/format-xs-1.pl | 73 +++++++++++ .github/workflows/clangformat/format-xs-2.pl | 10 ++ .../workflows/clangformat/format-xs-xml.pl | 44 +++++++ 5 files changed, 246 insertions(+) create mode 100755 .github/workflows/clangformat/clang-format-xs create mode 100644 .github/workflows/clangformat/format-xs-1.pl create mode 100644 .github/workflows/clangformat/format-xs-2.pl create mode 100644 .github/workflows/clangformat/format-xs-xml.pl diff --git a/.github/workflows/clangformat.yml b/.github/workflows/clangformat.yml index b52dad8b..71f2ffed 100644 --- a/.github/workflows/clangformat.yml +++ b/.github/workflows/clangformat.yml @@ -10,6 +10,11 @@ jobs: | refs=($(git log -1 --format=%s)) git fetch --depth=1 origin "${refs[3]}" + - name: configure clang-format + run: + | + git config clangformat.binary $PWD/.github/workflows/clangformat/clang-format-xs + git config clangformat.extensions c,h,xs - name: run git-clang-format and Check if no changes are needed run: | diff --git a/.github/workflows/clangformat/clang-format-xs b/.github/workflows/clangformat/clang-format-xs new file mode 100755 index 00000000..c77b7305 --- /dev/null +++ b/.github/workflows/clangformat/clang-format-xs @@ -0,0 +1,114 @@ +#!/bin/bash + +set -eu + +srcdir=$(dirname "$(readlink -f "$0")") +test -z "$srcdir" && srcdir=. + +CLANG_FORMAT=${CLANG_FORMAT:-clang-format} +options=() +files=() +lines=() +no_options=0;inplace=0;xml=0;keep_offset=0;keep_length=0;keep=0; +filename=tmp.1.c +offsets= +karg= +off_opts=() +for arg in "$@"; do + if [[ $keep = 1 ]]; then + if [[ "$karg" = "-offset" ]]; then + offsets="$offsets${offsets:+ }$arg" + off_opts+=("$karg" "$arg") + elif [[ "$karg" = "-length" ]]; then + offsets="$offsets:$arg" + off_opts+=("$karg" "$arg") + elif [[ "$karg" = "-assume-filename" ]]; then + filename="$arg" + options+=("$karg" "$arg") + else + options+=("$karg" "$arg") + fi + keep=0 + elif [[ $no_options = 0 ]]; then + case "$arg" in + -assume-filename=*) + filename="${arg#-assume-filename=}" + ;; + -lines=*) + lines+=("${arg#-lines=}") + ;; + *) + ;; + esac + case "$arg" in + --) no_options=1 + ;; + -i) inplace=1 + ;; + -output-replacements-xml) + xml=1 + ;; + -offset|-length|-cursor|-assume-filename|-fallback-style|-style) + keep=1 + karg="$arg" + ;; + -*) options+=("$arg") + ;; + *) files+=("$arg") + ;; + esac + else + files+=("$arg") + fi +done + +export IN_LINES="${lines[*]}" +export OFFSETS="$offsets" + +options_o=("${options[@]}") +if [[ $inplace = 1 ]]; then + options_o=("-i" "${options[@]}") +fi +if [[ $xml = 1 ]]; then + options_o=("-output-replacements-xml" "${options[@]}") +fi +options_o+=("${off_opts[@]}") + +do_xs() { + perl "$srcdir"/format-xs-1.pl "$1" > "$1".1.c + $CLANG_FORMAT -i "${options[@]}" -- "$1".1.c + if [[ $xml = 1 ]]; then + perl "$srcdir"/format-xs-2.pl "$1".1.c > "$1".1.xs + perl "$srcdir"/format-xs-xml.pl <(diff -U0 <(od -An -tu1 -w1 -v "$1") <(od -An -tu1 -w1 -v "$1".1.xs)) + rm "$1".1.xs + elif [[ $inplace = 1 ]]; then + perl "$srcdir"/format-xs-2.pl "$1".1.c > "$1" + else + perl "$srcdir"/format-xs-2.pl "$1".1.c + fi + rm "$1".1.c +} + +if [[ ${#files[@]} -eq 0 ]]; then + case "$filename" in + *.xs) + cat > "$filename".1.xs + do_xs "$filename".1.xs + rm "$filename".1.xs + ;; + *) + $CLANG_FORMAT "${options_o[@]}" + ;; + esac +else + for file in "${files[@]}"; do + case "$file" in + *.xs) + do_xs "$file" + ;; + *) + $CLANG_FORMAT "${options_o[@]}" -- "$file" + ;; + esac + done +fi diff --git a/.github/workflows/clangformat/format-xs-1.pl b/.github/workflows/clangformat/format-xs-1.pl new file mode 100644 index 00000000..1d15316e --- /dev/null +++ b/.github/workflows/clangformat/format-xs-1.pl @@ -0,0 +1,73 @@ +use strict; +use warnings; + +my $in_code = 1; +my @lines = $ENV{IN_LINES} =~ /(\d+):(\d+)/g; +sub in_lines { + if (@lines) { + for (my $i = 0; $i < @lines; $i += 2) { + if ($_[0] >= $lines[$i] && $_[0] <= $lines[$i + 1]) { + return 1; + } + } + return ''; + } else { + return 1; + } +} +while (<>) { + chomp; + my $copy; + my $prot = 0; + my $code = $in_code; + if (/^#(define|undef|include|if)/) { + $copy = 1; + } + elsif (/^#[* ]/) { + $prot = 1; + } + elsif (/^[A-Z_]+\s*=/) { + $prot = 2; + $in_code = 0; + } + elsif (/^((PP)?CODE|PREINIT):/) { + $prot = 1; + $in_code = 3; + } + elsif (/^[A-Z_]*:/) { + $prot = 1; + $in_code = 0; + } + elsif (/^[\w:* ]+\s*$/) { + $in_code = 0; + } + + if ($prot || (!$copy && !$in_code)) { + if ($code == 2) { + print "}/* -xs- */"; + } + if ($prot == 2) { + print "/* clang-format off */"; + } + s/^\s+/\t/ if in_lines($.); + print "/* =xs= $_ */"; + if ($prot == 2) { + print "/* clang-format on */"; + } + if ($in_code == 3) { + print "{"; + $in_code = 2; + } + print "\n"; + } + elsif ($copy) { + print "$_\n"; + } + elsif ($in_code) { + print "$_\n"; + } + +} +if ($in_code) { + print "}/* -xs- */\n"; +} diff --git a/.github/workflows/clangformat/format-xs-2.pl b/.github/workflows/clangformat/format-xs-2.pl new file mode 100644 index 00000000..40242553 --- /dev/null +++ b/.github/workflows/clangformat/format-xs-2.pl @@ -0,0 +1,10 @@ +use strict; +use warnings; + +my $doc = do { local $/; <> }; + +$doc =~ s{\}[ \t]*/[*] -xs- [*]/\s*}{}g; +$doc =~ s{^[ \t]*?/[*] =xs= (.*?) [*]/(\s*\{$)?}{$1}gms; +$doc =~ s{^[ \t]*?/[*] clang-format off [*]//[*] =xs= (.*?) [*]/\s?/[*] clang-format on [*]/(\s*\{$)?}{$1}gms; + +print $doc; diff --git a/.github/workflows/clangformat/format-xs-xml.pl b/.github/workflows/clangformat/format-xs-xml.pl new file mode 100644 index 00000000..151649ca --- /dev/null +++ b/.github/workflows/clangformat/format-xs-xml.pl @@ -0,0 +1,44 @@ +use strict; +use warnings; + +my @diff = <>; +if (@diff && $diff[0] !~ /^---/) { + die "Not valid diff output"; +} +my @offs = $ENV{OFFSETS} =~ /(\d+):(\d+)/g; +sub in_off { + if (@offs) { + for (my $i = 0; $i < @offs; $i += 2) { + if ($_[0] + $_[1] >= $offs[$i] && $_[0] <= $offs[$i] + $offs[$i + 1]) { + return 1; + } + } + return ''; + } else { + return 1; + } +} + +print " +\n"; +my $open; +for (@diff) { + if (/^\@\@ -(\d+)(,(\d+))? /) { + if ($open) { + print "\n"; + } + if (in_off($1-($3//1?1:0), $3//1)) { + print ""; + $open = 1; + } else { + $open = 0; + } + } + elsif (/^[+] +(\d+)/ && $open) { + print "&#$1;"; + } +} +if ($open) { + print "\n"; +} +print "\n";