1 | #!/usr/bin/perl -w
|
---|
2 | # I'm assuming that you're running this on some kind of ASCII system, but
|
---|
3 | # it will generate EDCDIC too. (TODO)
|
---|
4 | use strict;
|
---|
5 | use Encode;
|
---|
6 |
|
---|
7 | my @lines = grep {!/^#/} <DATA>;
|
---|
8 |
|
---|
9 | sub addline {
|
---|
10 | my ($arrays, $chrmap, $letter, $arrayname, $spare, $nocsum, $size,
|
---|
11 | $condition) = @_;
|
---|
12 | my $line = "/* $letter */ $size";
|
---|
13 | $line .= " | PACK_SIZE_SPARE" if $spare;
|
---|
14 | $line .= " | PACK_SIZE_CANNOT_CSUM" if $nocsum;
|
---|
15 | $line .= ",";
|
---|
16 | # And then the hack
|
---|
17 | $line = [$condition, $line] if $condition;
|
---|
18 | $arrays->{$arrayname}->[ord $chrmap->{$letter}] = $line;
|
---|
19 | # print ord $chrmap->{$letter}, " $line\n";
|
---|
20 | }
|
---|
21 |
|
---|
22 | sub output_tables {
|
---|
23 | my %arrays;
|
---|
24 |
|
---|
25 | my $chrmap = shift;
|
---|
26 | foreach (@_) {
|
---|
27 | my ($letter, $shriek, $spare, $nocsum, $size, $condition)
|
---|
28 | = /^([A-Za-z])(!?)\t(\S*)\t(\S*)\t([^\t\n]+)(?:\t+(.*))?$/;
|
---|
29 | die "Can't parse '$_'" unless $size;
|
---|
30 |
|
---|
31 | if (defined $condition) {
|
---|
32 | $condition = join " && ", map {"defined($_)"} split ' ', $condition;
|
---|
33 | }
|
---|
34 | unless ($size =~ s/^=//) {
|
---|
35 | $size = "sizeof($size)";
|
---|
36 | }
|
---|
37 |
|
---|
38 | addline (\%arrays, $chrmap, $letter, $shriek ? 'shrieking' : 'normal',
|
---|
39 | $spare, $nocsum, $size, $condition);
|
---|
40 | }
|
---|
41 |
|
---|
42 | my %earliest;
|
---|
43 | foreach my $arrayname (sort keys %arrays) {
|
---|
44 | my $array = $arrays{$arrayname};
|
---|
45 | die "No defined entries in $arrayname" unless $array->[$#$array];
|
---|
46 | # Find the first used entry
|
---|
47 | my $earliest = 0;
|
---|
48 | $earliest++ while (!$array->[$earliest]);
|
---|
49 | # Remove all the empty elements.
|
---|
50 | splice @$array, 0, $earliest;
|
---|
51 | print "unsigned char size_${arrayname}[", scalar @$array, "] = {\n";
|
---|
52 | my @lines;
|
---|
53 | foreach (@$array) {
|
---|
54 | # Remove the assumption here that the last entry isn't conditonal
|
---|
55 | if (ref $_) {
|
---|
56 | push @lines,
|
---|
57 | ["#if $_->[0]", " $_->[1]", "#else", " 0,", "#endif"];
|
---|
58 | } else {
|
---|
59 | push @lines, $_ ? " $_" : " 0,";
|
---|
60 | }
|
---|
61 | }
|
---|
62 | # remove the last, annoying, comma
|
---|
63 | my $last = $lines[$#lines];
|
---|
64 | my $got;
|
---|
65 | foreach (ref $last ? @$last : $last) {
|
---|
66 | $got += s/,$//;
|
---|
67 | }
|
---|
68 | die "Last entry had no commas" unless $got;
|
---|
69 | print map {"$_\n"} ref $_ ? @$_ : $_ foreach @lines;
|
---|
70 | print "};\n";
|
---|
71 | $earliest{$arrayname} = $earliest;
|
---|
72 | }
|
---|
73 |
|
---|
74 | print "struct packsize_t packsize[2] = {\n";
|
---|
75 |
|
---|
76 | my @lines;
|
---|
77 | foreach (qw(normal shrieking)) {
|
---|
78 | my $array = $arrays{$_};
|
---|
79 | push @lines, " {size_$_, $earliest{$_}, " . (scalar @$array) . "},";
|
---|
80 | }
|
---|
81 | # remove the last, annoying, comma
|
---|
82 | chop $lines[$#lines];
|
---|
83 | print "$_\n" foreach @lines;
|
---|
84 | print "};\n";
|
---|
85 | }
|
---|
86 |
|
---|
87 | my %asciimap = (map {chr $_, chr $_} 0..255);
|
---|
88 | my %ebcdicmap = (map {chr $_, Encode::encode ("posix-bc", chr $_)} 0..255);
|
---|
89 |
|
---|
90 | print <<'EOC';
|
---|
91 | #if 'J'-'I' == 1
|
---|
92 | /* ASCII */
|
---|
93 | EOC
|
---|
94 | output_tables (\%asciimap, @lines);
|
---|
95 | print <<'EOC';
|
---|
96 | #else
|
---|
97 | /* EBCDIC (or bust) */
|
---|
98 | EOC
|
---|
99 | output_tables (\%ebcdicmap, @lines);
|
---|
100 | print "#endif\n";
|
---|
101 |
|
---|
102 | __DATA__
|
---|
103 | #Symbol spare nocsum size
|
---|
104 | c char
|
---|
105 | C unsigned char
|
---|
106 | U char
|
---|
107 | s! short
|
---|
108 | s =SIZE16
|
---|
109 | S! unsigned short
|
---|
110 | v =SIZE16
|
---|
111 | n =SIZE16
|
---|
112 | S =SIZE16
|
---|
113 | v! =SIZE16 PERL_PACK_CAN_SHRIEKSIGN
|
---|
114 | n! =SIZE16 PERL_PACK_CAN_SHRIEKSIGN
|
---|
115 | i int
|
---|
116 | i! int
|
---|
117 | I unsigned int
|
---|
118 | I! unsigned int
|
---|
119 | j =IVSIZE
|
---|
120 | J =UVSIZE
|
---|
121 | l! long
|
---|
122 | l =SIZE32
|
---|
123 | L! unsigned long
|
---|
124 | V =SIZE32
|
---|
125 | N =SIZE32
|
---|
126 | V! =SIZE32 PERL_PACK_CAN_SHRIEKSIGN
|
---|
127 | N! =SIZE32 PERL_PACK_CAN_SHRIEKSIGN
|
---|
128 | L =SIZE32
|
---|
129 | p * char *
|
---|
130 | w * char
|
---|
131 | q Quad_t HAS_QUAD
|
---|
132 | Q Uquad_t HAS_QUAD
|
---|
133 | f float
|
---|
134 | d double
|
---|
135 | F =NVSIZE
|
---|
136 | D =LONG_DOUBLESIZE HAS_LONG_DOUBLE USE_LONG_DOUBLE
|
---|