All pastes #869283 Raw Edit

unsyn.pl

public text v1 · immutable
#869283 ·published 2008-01-23 01:32 UTC
rendered paste body
#!/usr/bin/perl -w

# Ed Dolan <bytecolor@yahoo.com>
# 01/20/2008

#
# Remove all APT SYN/ assignments.
#

use strict;

my (%synhash, $synre);
my $fixed = "remark|partno|pprint|insert|titles";
my $help = <<END_help;
Remove all the SYN/ assignments from an apt360 source file.
Usage: unsyn.pl foo.apt
       Output is to stdout.
Note: If an expanded statement is > 72 chars AND it ends in a
comment, the comment will be moved to the line preceding the
statement.
END_help

if (@ARGV && $ARGV[0] =~ /--?h(elp)?/) {
    print  $help;
    exit 1;
}

while (<>) {
    chomp;
    # match a SYN/ statement
    if (/^\s*([a-z0-9]{1,6}\))?\s*syn\s*\/([a-z0-9,\s]+)(\$.*)?$/i) {
        my ($synstr, @synlist, %newhash);
        # could be: SYN/ $ with no arguments on this line.
        # fscked yes, but possible...
        if ($2) { $synstr .= $2; }
        # comment out the SYN/ statement
        print "\$\$ $_\n";
        # continuation?
        if ($3) {
            while (<>) {
                chomp;
                # comment or blank line terminates a requested continuation
                if (/^\s*\$\s*\$/ || /^$/) {
                    print "$_\n";
                    last;
                }
                # only a continuation on the line with optional comment suffix
                elsif (/^\s*\$.*/) {
                    print "\$\$ $_\n";
                    next;
                }
                # might be an illegal continued line
                elsif (/^($fixed)|([^a-z0-9,\$\s]+)/i) {
                    die "suspicious continued line:\n$_\n";
                }
                # XXX goofy re
                elsif (/^(\s+)?([a-z0-9,\s]+)(\$.*)?$/i) {
                    $synstr .= $2;
                    # comment out the SYN/ statement
                    print "\$\$ $_\n";
                    if ($3) { next; } else { last; }
                }
                else {
                    die "should not be here\n";
                }
            }
        }
        # assemble the hash, merging, if multiple SYN/ statements are found
        $synstr =~ tr/[ \t]//d;
        @synlist = split(/,/, $synstr);
        %newhash = split(/,/, $synstr);
        # swap the keys and values, if an APT keyword was
        # first in the list of pairs
        if (length $synlist[0] > length $synlist[1]) {
            %newhash = reverse %newhash;
        }
        # merge
        %synhash = (%synhash, %newhash);

        # XXX why doesn't this work?
        #$synhash{keys %newhash} = values %newhash;
        #print join("\n", keys %synhash);

        # re to match the defined synonyms
        $synre = "\\b(" . join("|", keys %synhash) . ")\\b";
    }
    else {
        if (%synhash) {
            unless (/^(($fixed)|(\s*\$\s*\$))/i) {
                s/$synre/$synhash{$1}/g;
                fit72($_) if length > 72;
            }
        }
        print "$_\n";
    }
}

# Dice a line > 72 characters up into 72-char-max chunks,
# including the $ continuation character.
# The APT processor does not care where I break the line.
# It can be in the middle of an identifier.
# The statement: point1 = point/ 0, 0
# could be:
# po$
# in                      $
# t1 = point/ 0, 0
sub fit72 {
    my ($i, @parts, $code, $comment, $chunk_size);
    $chunk_size = 72;
    # code that ends in a comment?
    if (/\$\s*\$.*$/) {
        # move the comment above the line
        ($code, $comment) = split(/\s*\$\s*\$/, $_);
        $_ = "\$\$$comment\n";
        if (length $code > $chunk_size) {
            # chunk the code
            $_ .= join("\$\n", chunk($code, $chunk_size));
        } else {
            $_ .= "$code";
        }
    } else {
        # chunk the statement
        $_ = join("\$\n", chunk($_, $chunk_size));
    }
}

# Given a string, and a chunk size, return a
# list of strings that size or less.
sub chunk {
    my ($i, @parts, $code, $chunk_size);
    ($code, $chunk_size) = @_;
    $chunk_size--;
    for ($i=0; $i<length $code; $i+=$chunk_size) {
        push(@parts,  substr($code, $i, $chunk_size));
    }
    return @parts;
}