From patchwork Thu Mar 25 21:51:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Giuliano Procida X-Patchwork-Id: 42779 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 88167385800D; Thu, 25 Mar 2021 21:52:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 88167385800D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1616709144; bh=/S8nG4KAD608CGa20OEvBU0+Hj8j1yBvsrwlLsVF62A=; h=Date:In-Reply-To:References:Subject:To:List-Id:List-Unsubscribe: List-Archive:List-Help:List-Subscribe:From:Reply-To:Cc:From; b=ojSOvZyVKZUCSSJJu/8gdwc2MZI1+QROAvBbC/lhrRujsem9CdzaRoUhr9HI8Z7KM tncCvGPyxrTZxDYNeR1RZVmQYTslcwveuiv8OcXVyvBGIPw7GTzKEieM3NXM093Afm zBtxpylULd1cb5mIkHxFEIR0Z9o5/YRGJ0PwxgS8= X-Original-To: libabigail@sourceware.org Delivered-To: libabigail@sourceware.org Received: from mail-qk1-x749.google.com (mail-qk1-x749.google.com [IPv6:2607:f8b0:4864:20::749]) by sourceware.org (Postfix) with ESMTPS id 1F667385BF9E for ; Thu, 25 Mar 2021 21:52:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 1F667385BF9E Received: by mail-qk1-x749.google.com with SMTP id g18so4874069qki.15 for ; Thu, 25 Mar 2021 14:52:21 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=/S8nG4KAD608CGa20OEvBU0+Hj8j1yBvsrwlLsVF62A=; b=QG1TKpYjCVh7s4m6sFk+Zhubwo0//oxZj6+toWR7aUFbRDL64dLBRb23usirZpYDHc auevtcV5aOq04PbO28HwV+zegQYemKhTIXK6nA31h0hcIIS1m0XR37ma6XzXlPL6N40Z AdNg+x8AP4G/o/VViQwOgfi1b6gkzLYPEohz0jZD0PndLQRi8HozrYgr7j9imroK82mg A/KmDKRZereE1MZ3TYcBHE9qC1T9mWIcbnH1VOAOYij78xN2NTI/eQgjMYSH2H0FNU1K X1VypwgzM/Q3ZFKtRLofiniRq/wBpcSU0uXkmoIUYOGGljAAgUflCCEnGDS0WGipAike ZK4w== X-Gm-Message-State: AOAM5329txmOhgsJLW8aNPZvBJXgWSbyn7XNmM9jCsmH9LmY7KoNRmoS DC7JO4pH7QeMkPdHx8ypxa1ndTuf+9AyXnNwZ+kJWx2X0gSmrnhLj7rTSPXfV+h1PVYlnJ4RFKv Qcz2MFUnT9ymfjewWNjaMvRyxmmx6h1jjxp8EZjTNMxmwexSHy6lZZlYNKmGoUvaX840ay/A= X-Google-Smtp-Source: ABdhPJyqNcRzILN3b3vP9vdeZIM2LgS8as3G0FPfK167DiCnYkxsYEarDqdsHTIk4FE81x3zmKZ5BlEbhskM2w== X-Received: from tef.lon.corp.google.com ([2a00:79e0:d:110:2df6:f24a:7f54:86a8]) (user=gprocida job=sendgmr) by 2002:a0c:c248:: with SMTP id w8mr10366073qvh.58.1616709140702; Thu, 25 Mar 2021 14:52:20 -0700 (PDT) Date: Thu, 25 Mar 2021 21:51:45 +0000 In-Reply-To: <20210325215146.3597963-1-gprocida@google.com> Message-Id: <20210325215146.3597963-9-gprocida@google.com> Mime-Version: 1.0 References: <20210316165509.2658452-1-gprocida@google.com> <20210325215146.3597963-1-gprocida@google.com> X-Mailer: git-send-email 2.31.0.291.g576ba9dcdaf-goog Subject: [RFC PATCH 8/9] Add pass to stabilise types and declarations To: libabigail@sourceware.org X-Spam-Status: No, score=-22.7 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libabigail@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list of the Libabigail project List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-Patchwork-Original-From: Giuliano Procida via Libabigail From: Giuliano Procida Reply-To: Giuliano Procida Cc: maennich@google.com, kernel-team@android.com Errors-To: libabigail-bounces@sourceware.org Sender: "Libabigail" This commit adds a pass which consolidates all types and declarations within an abi-corpus into a replacement abi-instr. These elements are then ordered by id and name respectively, with types before declarations. * scripts/abitidy.pl (stabilise_types_and_declarations): New function to order types and declarations as deterministically as possible within an abi-corpus. Signed-off-by: Giuliano Procida --- scripts/abitidy.pl | 84 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/scripts/abitidy.pl b/scripts/abitidy.pl index 35b3c054..67fe3a69 100755 --- a/scripts/abitidy.pl +++ b/scripts/abitidy.pl @@ -496,6 +496,82 @@ sub report_duplicate_types($dom) { } } +# Stabilise types and declarations. +sub stabilise_types_and_declarations($dom) { + my $corpus_path = new XML::LibXML::XPathExpression('//abi-corpus'); + my $instr_path = new XML::LibXML::XPathExpression('abi-instr'); + my $type_or_decl_path = new XML::LibXML::XPathExpression('*[@id]|*[@name]'); + + my @corpora = $dom->findnodes($corpus_path); + for my $coprus (@corpora) { + # Let's squish it. We expect its abi-instr elements to have + # consistent attributes, ignoring path. + my %attrs; + my @children = $coprus->findnodes($instr_path); + for my $child (@children) { + for my $attr (keys %$child) { + my $value = $child->{$attr}; + $attrs{$attr}{$value} = undef; + } + } + next unless scalar keys %attrs; + + # Create a replacement abi-instr node. + my $replacement = new XML::LibXML::Element('abi-instr'); + # Original attribute ordering is lost, may as well be deterministic here. + for my $attr (sort keys %attrs) { + # Check attribute consistency. + for my $values ($attrs{$attr}) { + if (scalar keys %{$values} > 1) { + die "unexpected non-constant abi-instr attribute $attr\n" + unless $attr eq 'path' || $attr eq 'comp-dir-path' || $attr eq 'language'; + $values = { 'various' => undef }; + } + for my $value (keys %$values) { + $replacement->setAttribute($attr, $value); + } + } + } + + # Gather sorted types and decls. + my @types_and_decls = sort { + my $a_id = $a->{id}; + my $a_name = $a->{name}; + die unless defined $a_id || defined $a_name; + my $b_id = $b->{id}; + my $b_name = $b->{name}; + die unless defined $b_id || defined $b_name; + # types before declarations + # order types by id + # order declarations by name + defined $a_id != defined $b_id ? !defined $a_id <=> !defined $b_id + : defined $a_id ? $a_id cmp $b_id + : $a_name cmp $b_name + } map { $_->findnodes($type_or_decl_path) } @children; + + # Add them to replacement abi-instr + map { + my $prev = $_->previousSibling(); + if ($prev && $prev->nodeType == XML_COMMENT_NODE) { + $prev->unbindNode(); + $replacement->appendChild($prev); + } + $_->unbindNode(); + $replacement->appendChild($_) + } @types_and_decls; + # Remove the old abi-instr nodes. + for my $child (@children) { + if ($child->hasChildNodes()) { + warn "failed to evacuate abi-instr: ", $child->toString(), "\n"; + next; + } + remove_node($child); + } + # Add the replacement abi-instr node to the abi-corpus. + $coprus->appendChild($replacement); + } +} + # Parse arguments. my $input_opt; my $output_opt; @@ -505,17 +581,19 @@ my $drop_opt; my $prune_opt; my $normalise_opt; my $eliminate_opt; +my $stabilise_opt; my $report_opt; GetOptions('i|input=s' => \$input_opt, 'o|output=s' => \$output_opt, 's|symbols=s' => \$symbols_opt, 'a|all' => sub { - $drop_opt = $prune_opt = $normalise_opt = $eliminate_opt = $report_opt = 1 + $drop_opt = $prune_opt = $normalise_opt = $eliminate_opt = $stabilise_opt = $report_opt = 1 }, 'd|drop-empty!' => \$drop_opt, 'p|prune-unreachable!' => \$prune_opt, 'n|normalise-anonymous!' => \$normalise_opt, 'e|eliminate-duplicates!' => \$eliminate_opt, + 't|stabilise-order!' => \$stabilise_opt, 'r|report-duplicates!' => \$report_opt, ) and !@ARGV or die("usage: $0", map { (' ', $_) } ( @@ -527,6 +605,7 @@ GetOptions('i|input=s' => \$input_opt, '[-p|--[no-]prune-unreachable]', '[-n|--[no-]normalise-anonymous]', '[-e|--[no-]eliminate-duplicates]', + '[-t|--[no-]stabilise-order]', '[-r|--[no-]report-duplicates]', ), "\n"); @@ -555,6 +634,9 @@ report_duplicate_types($dom) if $report_opt; # Prune unreachable elements. prune_unreachable($dom) if $prune_opt; +# Stabilise types and declarations. +stabilise_types_and_declarations($dom) if $stabilise_opt; + # Drop empty elements. drop_empty($dom) if $drop_opt;