163 lines
3.9 KiB
Text
163 lines
3.9 KiB
Text
|
#!/usr/bin/perl
|
||
|
#
|
||
|
# This file is part of Cygwin.
|
||
|
#
|
||
|
# This software is a copyrighted work licensed under the terms of the
|
||
|
# Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
||
|
# details.
|
||
|
#
|
||
|
use File::Basename;
|
||
|
use Cwd;
|
||
|
my $cwd = getcwd;
|
||
|
|
||
|
use strict;
|
||
|
use integer;
|
||
|
sub devsort;
|
||
|
|
||
|
my $input = shift;
|
||
|
my $output = shift;
|
||
|
my $base = "/tmp/" . basename($input, '.in') . '.' . $$;
|
||
|
my $c = $base . '.c';
|
||
|
my $shilka = $base . '.shilka';
|
||
|
|
||
|
open(INPUT, $input) or die "$0: couldn't open '$input' - $!\n";
|
||
|
|
||
|
my @lines = ();
|
||
|
my $storage_ix = -1;
|
||
|
my @storage = ();
|
||
|
my %pointers = ();
|
||
|
my @patterns = ();
|
||
|
my $patterns_ix = -1;
|
||
|
while (<INPUT>) {
|
||
|
if (/%storage_here/) {
|
||
|
$storage_ix = @lines;
|
||
|
} elsif (/^"([^"]+)",\s*(.*)$/o) {
|
||
|
push(@patterns, [$1, $2]);
|
||
|
next;
|
||
|
}
|
||
|
if (@patterns) {
|
||
|
for my $f (sort devsort @patterns) {
|
||
|
my $x = $f->[0];
|
||
|
my $rest = $f->[1];
|
||
|
my ($dev, $devrest) = ($x =~ /([^%]+)(%.*)?$/o);
|
||
|
$rest .= ', ' . (($dev =~ m%/dev/%o) ? 'true' : 'false');
|
||
|
push(@lines, generate($dev, $devrest, $rest, []));
|
||
|
}
|
||
|
@patterns = ();
|
||
|
}
|
||
|
push(@lines, $_);
|
||
|
}
|
||
|
|
||
|
close INPUT;
|
||
|
# @storage = sort devsort @storage;
|
||
|
chop $storage[$#storage];
|
||
|
chop $storage[$#storage];
|
||
|
$storage[$#storage] .= "\n";
|
||
|
splice(@lines, $storage_ix, 1,
|
||
|
"const _RDATA _device dev_storage[] =\n", "{\n",
|
||
|
@storage, "};\n\n",
|
||
|
sort {$a cmp $b} values %pointers);
|
||
|
open(SHILKA, '>', $shilka);
|
||
|
print SHILKA @lines;
|
||
|
close SHILKA;
|
||
|
|
||
|
chdir '/tmp';
|
||
|
system qw'shilka -length -strip -no-definitions', $shilka;
|
||
|
if ($? == -1) {
|
||
|
die "$0: shilka command missing? - $!\n";
|
||
|
} else {
|
||
|
exit $? if $?;
|
||
|
}
|
||
|
chdir $cwd;
|
||
|
unlink $shilka;
|
||
|
open(C, '<', $c) or die "$0: couldn't open $c - $!\n";
|
||
|
@lines = <C>;
|
||
|
close C;
|
||
|
unlink $c;
|
||
|
splice(@lines, 0, 3);
|
||
|
my $ign_until_brace = 0;
|
||
|
for (my $i = 0; $i < @lines; $i++) {
|
||
|
$_ = $lines[$i];
|
||
|
$ign_until_brace = 1 if /(?:KR_reset|KR_output_statistics).*\)\s*$/o;
|
||
|
if ($ign_until_brace || /(?:#\s*line|(?:KR_reset|KR_output_statistics).*;)/) {
|
||
|
$ign_until_brace = 0 if $ign_until_brace && /}/o;
|
||
|
splice(@lines, $i, 1);
|
||
|
redo;
|
||
|
};
|
||
|
}
|
||
|
open(OUTPUT, '>', $output) or do {{
|
||
|
if (chmod(0664, $output)) {
|
||
|
open(OUTPUT, '>', $output);
|
||
|
last;
|
||
|
}
|
||
|
die "$0: couldn't open $output - $!\n";
|
||
|
}};
|
||
|
print OUTPUT @lines;
|
||
|
close OUTPUT;
|
||
|
|
||
|
sub generate {
|
||
|
my $dev = shift;
|
||
|
my $devrest = shift;
|
||
|
my $rest = shift;
|
||
|
my $vars = shift;
|
||
|
my $res;
|
||
|
my @lines = ();
|
||
|
if ($devrest) {
|
||
|
my ($a, $low, $high, $fmt, $b) = ($devrest =~ /%([\({])([^-]+)-([^\)}]+)[\)}](.)(.*)/o);
|
||
|
my ($middle, $devrest0) = ($b =~ /^([^%]*)(%.*)?$/);
|
||
|
$fmt = "%$fmt";
|
||
|
my $vars_ix = @{$vars};
|
||
|
for my $f ($low .. $high) {
|
||
|
$vars->[$vars_ix] = $f;
|
||
|
$#{$vars} = $vars_ix;
|
||
|
my $dev0 = $dev . sprintf($fmt, $f) . $middle;
|
||
|
push(@lines, generate($dev0, $devrest0, $rest, $vars));
|
||
|
}
|
||
|
} else {
|
||
|
my $fh = $dev;
|
||
|
$fh =~ s%/%_%og;
|
||
|
$fh =~ s%^:%__%o;
|
||
|
my $shilka_id = $fh;
|
||
|
my $storage_str = $fh . '_storage';
|
||
|
$fh =~ s/^_dev_/FH_/o;
|
||
|
$fh = uc $fh;
|
||
|
$shilka_id =~ s/^_dev_//o;
|
||
|
$storage_str =~ s/^_dev/dev/o;
|
||
|
my $storage_loc = "dev_storage + " . @storage;
|
||
|
@lines = ('"' . $dev . '"' . " = $shilka_id {return $storage_loc;}\n");
|
||
|
$rest = "$fh, $rest" if $rest =~ /^"/o;
|
||
|
$rest = fixup($rest, $vars);
|
||
|
if ($rest =~ /^(.*), =(\S*_dev)\b\s*(.*)$/) {
|
||
|
$pointers{$2} ||= "const _device *$2 = $storage_loc;\n";
|
||
|
$rest = $1 . $3;
|
||
|
}
|
||
|
push(@storage, " {\"$dev\", " . $rest . "},\n");
|
||
|
}
|
||
|
return @lines;
|
||
|
}
|
||
|
|
||
|
sub fixup {
|
||
|
my $rest = shift;
|
||
|
my $vars = shift;
|
||
|
0 while $rest =~ s/{([^}]*)}/evalit($1, $vars)/eg;
|
||
|
return $rest;
|
||
|
}
|
||
|
|
||
|
sub evalit {
|
||
|
my $what = shift;
|
||
|
my $vars = shift;
|
||
|
$what =~ s/\$(\d+)/'$vars->[$1-1]'/g;
|
||
|
my $res = eval $what;
|
||
|
return $res;
|
||
|
}
|
||
|
|
||
|
sub devsort {
|
||
|
my $a0 = $a->[0];
|
||
|
my $b0 = $b->[0];
|
||
|
$a0 =~ s/(\D)(\d+)/"$1" . sprintf "%05d", $2/e;
|
||
|
$b0 =~ s/(\D)(\d+)/"$1" . sprintf "%05d", $2/e;
|
||
|
$a0 =~ s%^//%:%o;
|
||
|
$b0 =~ s%^//%:%o;
|
||
|
return $a0 cmp $b0;
|
||
|
}
|