perlop: fix documentation for s/// "false" return value
[perl.git] / regen / genpacksizetables.pl
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 EBCDIC too. (TODO)
4 use strict;
5 use Encode;
6 require './regen/regen_lib.pl';
7
8 sub make_text {
9     my ($chrmap, $letter, $unpredictable, $nocsum, $size, $condition) = @_;
10     my $text = "    /* $letter */ $size";
11     $text .= " | PACK_SIZE_UNPREDICTABLE" if $unpredictable;
12     $text .= " | PACK_SIZE_CANNOT_CSUM"   if $nocsum;
13     $text .= ",";
14
15     if ($condition) {
16         $text = "#if $condition
17 $text
18 #else
19     0,
20 #endif";
21     }
22     return $text;
23 }
24
25 sub make_tables {
26     my %arrays;
27
28     my $chrmap = shift;
29     foreach (@_) {
30         my ($letter, $shriek, $unpredictable, $nocsum, $size, $condition) =
31             /^([A-Za-z])(!?)\t(\S*)\t(\S*)\t([^\t\n]+)(?:\t+(.*))?$/ or
32             die "Can't parse '$_'";
33
34         $size = "sizeof($size)" unless $size =~ s/^=//;
35
36         $arrays{$shriek ? 'shrieking' : 'normal'}{ord $chrmap->{$letter}} =
37             make_text($chrmap, $letter,
38                       $unpredictable, $nocsum, $size, $condition);
39     }
40
41     my $text = "STATIC const packprops_t packprops[512] = {\n";
42     foreach my $arrayname (qw(normal shrieking)) {
43         my $array = $arrays{$arrayname} ||
44             die "No defined entries in $arrayname";
45         $text .= "    /* $arrayname */\n";
46         for my $ch (0..255) {
47             $text .= $array->{$ch} || "    0,";
48             $text .= "\n";
49         }
50     }
51     # Join "0," entries together
52     1 while $text =~ s/\b0,\s*\n\s*0,/0, 0,/g;
53     # But split them up again if the sequence gets too long
54     $text =~ s/((?:\b0, ){15}0,) /$1\n    /g;
55     # Clean up final ,
56     $text =~ s/,$//;
57     $text .= "};";
58     return $text;
59 }
60
61 my @lines = grep {
62     s/#.*//;
63     /\S/;
64 } <DATA>;
65
66 my %asciimap  = map {chr $_, chr $_} 0..255;
67
68 # Currently, all things generated by this on EBCDIC are alphabetics, whose
69 # positions are all the same regardless of code page, so any EBCDIC encoding
70 # will work; just choose one
71 my %ebcdicmap = map {chr $_, Encode::encode("posix-bc", chr $_)} 0..255;
72
73 my $fh = open_new('packsizetables.inc', '>', { by => $0, from => 'its data'});
74
75 print $fh <<"EOC";
76 #if TYPE_IS_SHRIEKING != 0x100
77    ++++shriek offset should be 256
78 #endif
79
80 typedef U8 packprops_t;
81 #if 'J'-'I' == 1
82 /* ASCII */
83 @{[make_tables (\%asciimap, @lines)]}
84 #else
85 /* EBCDIC (or bust) */
86 @{[make_tables (\%ebcdicmap, @lines)]}
87 #endif
88 EOC
89
90 read_only_bottom_close_and_rename($fh);
91
92 __DATA__
93 #Symbol unpredictable
94 #               nocsum  size
95 c                       char
96 C                       unsigned char
97 W       *               unsigned char
98 U       *               char
99 s!                      short
100 s                       =SIZE16
101 S!                      unsigned short
102 v                       =SIZE16
103 n                       =SIZE16
104 S                       =SIZE16
105 v!                      =SIZE16
106 n!                      =SIZE16
107 i                       int
108 i!                      int
109 I                       unsigned int
110 I!                      unsigned int
111 j                       =IVSIZE
112 J                       =UVSIZE
113 l!                      long
114 l                       =SIZE32
115 L!                      unsigned long
116 V                       =SIZE32
117 N                       =SIZE32
118 V!                      =SIZE32
119 N!                      =SIZE32
120 L                       =SIZE32
121 p               *       char *
122 w       *       *       char
123 q                       Quad_t  IVSIZE >= 8
124 Q                       Uquad_t IVSIZE >= 8
125 f                       float
126 d                       double
127 F                       =NVSIZE
128 D                       =LONG_DOUBLESIZE        defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)