http://invisible-island.net/autoconf/my-autoconf/
Copyright © 2019-2020,2021 by Thomas E. Dickey
#!/usr/bin/env perl
# $Id: xpg3-fixup.pl,v 1.5 2019/01/27 01:40:00 tom Exp $
# -----------------------------------------------------------------------------
# Copyright 2019 by Thomas E. Dickey
#
# All Rights Reserved
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name(s) of the above copyright
# holders shall not be used in advertising or otherwise to promote the
# sale, use or other dealings in this Software without prior written
# authorization.
# -----------------------------------------------------------------------------
# convert xpg4 case-statements to xpg3 format in shell scripts
use strict;
use warnings;
use Getopt::Std;
$| = 1;
our ( $opt_d, $opt_n, $opt_v );
sub doit($) {
my $path = shift;
printf "** $path\n" if ($opt_v);
if ( open( my $fh, $path ) ) {
my @data = <$fh>;
close $fh;
my $changes = 0;
my $b4_here = 0;
my $literal = "";
my $level = 0;
my $errors = 0;
for my $n ( 0 .. $#data ) {
# When in a here-document, autoconf may a case-statement which
# may/may not be a fragment.
if ( $data[$n] =~ /^\s*cat\s+\>[^\s]+\s+\</ ) {
$b4_here = $level;
$literal = $data[$n];
chomp $literal;
$literal =~ s/^.*<//;
$literal =~ s/['\\]//g;
printf "%s:%d: begin here-doc '$literal'\n", $path, $n + 1
if ($opt_d);
}
elsif ( $literal ne "" ) {
if ( $data[$n] =~ /^\s*$literal\b/ ) {
printf "%s:%d: finish here-doc '$literal'\n", $path, $n + 1
if ($opt_d);
$literal = "";
$level = $b4_here;
}
}
# The patterns skip zero or more "[" or space at the beginning of a
# line to accommodate autoconf's use of "[" and "]" delimiters.
# There could be more complicated patterns, but much harder to deal
# with.
if ( $data[$n] =~ /^[\[\s]*case\s+.*\s+in\s*(#.*)?$/ ) {
printf "%s:%d: push %s", $path, $n + 1, $data[$n] if ($opt_d);
++$level;
}
elsif ( $data[$n] =~ /^\s*case\b.*:/ ) {
# ignore, C code
}
elsif ( $data[$n] =~ /^[\[\s]*case\b/ ) {
printf STDERR "%s:%d: unexpected case\n", $path, $n + 1;
++$errors;
}
elsif ( $data[$n] =~ /^[\[\s]*esac\s*(#.*)?$/ ) {
printf "%s:%d: pop %s", $path, $n + 1, $data[$n] if ($opt_d);
if ( --$level < 0 ) {
if ( $literal eq "" ) {
printf STDERR "%s:%d: case/esac unbalanced\n", $path,
$n + 1;
return;
}
}
}
elsif ( $data[$n] =~
/^\s*\((set|void|int|short|char|long|float|double)\)/ )
{
# ignore, special cases for autoconf
}
elsif ( $level > 0
and $data[$n] =~
/^[\[\s]*\((\\.|'[^']+'|\s*\|\s*|\S)+\)(\s+\S.*)?$/ )
{
printf "%s:%d: edit %s", $path, $n + 1, $data[$n] if ($opt_d);
$data[$n] =~ s/\(//;
printf "%s:%d: -> %s", $path, $n + 1, $data[$n] if ($opt_d);
$changes++;
}
elsif ( $level > 0
and $data[$n] =~ /^[\[\s]*\(.\).*;;/ )
{
printf "%s:%d: edit %s", $path, $n + 1, $data[$n] if ($opt_d);
$data[$n] =~ s/\(//;
printf "%s:%d: -> %s", $path, $n + 1, $data[$n] if ($opt_d);
$changes++;
}
}
if ( $changes > 0 ) {
if ( not $opt_n ) {
my $save = $path . ".orig";
if ( -f $save ) {
printf STDERR "%s: already exists\n", $save;
return;
}
if ( not rename( $path, $save ) ) {
printf STDERR "%s: cannot rename to %s\n", $save, $path;
return;
}
if ( open( my $fh, ">$path" ) ) {
for my $n ( 0 .. $#data ) {
printf $fh "%s", $data[$n];
}
close $fh;
chmod 0755, $path if ( -x $save );
}
else {
printf STDERR "%s: cannot create\n", $path;
rename( $save, $path );
return;
}
}
printf "%d changes %smade\n", $changes, $opt_n ? "would be " : "";
}
else {
printf "No changes %smade\n", $opt_n ? "would be " : "";
}
}
}
sub main::HELP_MESSAGE() {
printf STDERR <<EOF
Usage: $0 [options] [files]
Convert xpg4 case-statements to xpg3 format in shell scripts.
Options:
-d debug (more verbose)
-n dry-run/noop (do not modify files)
-v verbose
EOF
;
exit 1;
}
$Getopt::Std::STANDARD_HELP_VERSION = 1;
&getopts('dnv') || &main::HELP_MESSAGE;
$opt_v = 1 if ($opt_d);
&main::HELP_MESSAGE if ( $#ARGV < 0 );
while ( $#ARGV >= 0 ) {
&doit( pop @ARGV );
}
1;