1e1051a39Sopenharmony_ci#! /usr/bin/env perl
2e1051a39Sopenharmony_ci#
3e1051a39Sopenharmony_ci# C source compressor.  This:
4e1051a39Sopenharmony_ci#
5e1051a39Sopenharmony_ci# - merges continuation lines
6e1051a39Sopenharmony_ci# - removes comments (not in strings)
7e1051a39Sopenharmony_ci# - removes empty lines (not in strings)
8e1051a39Sopenharmony_ci
9e1051a39Sopenharmony_ciuse strict;
10e1051a39Sopenharmony_ciuse warnings;
11e1051a39Sopenharmony_ci
12e1051a39Sopenharmony_cimy $debug = defined $ENV{DEBUG};
13e1051a39Sopenharmony_cimy $lang = shift @ARGV;
14e1051a39Sopenharmony_ci
15e1051a39Sopenharmony_ci# Slurp the file
16e1051a39Sopenharmony_ci$/ = undef;
17e1051a39Sopenharmony_ci$_ = <>;
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ciif ($lang eq 'C') {
20e1051a39Sopenharmony_ci    # Merge continuation lines
21e1051a39Sopenharmony_ci    s{\\\n}{}g;
22e1051a39Sopenharmony_ci
23e1051a39Sopenharmony_ci    # Regexp for things that should be preserved
24e1051a39Sopenharmony_ci    my $preserved =
25e1051a39Sopenharmony_ci        qr{
26e1051a39Sopenharmony_ci              (?:
27e1051a39Sopenharmony_ci                  "                 # String start
28e1051a39Sopenharmony_ci                  (?: \\. | [^\"])* # Any character, including escaped ones
29e1051a39Sopenharmony_ci                  "                 # String end
30e1051a39Sopenharmony_ci              )
31e1051a39Sopenharmony_ci
32e1051a39Sopenharmony_ci          |                         # OR
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ci              (?:
35e1051a39Sopenharmony_ci                  '                 # Character start (multi-chars supported)
36e1051a39Sopenharmony_ci                  (?: \\. | [^\'])+ # Any character, including escaped ones
37e1051a39Sopenharmony_ci                  '                 # String end
38e1051a39Sopenharmony_ci              )
39e1051a39Sopenharmony_ci        }x;
40e1051a39Sopenharmony_ci
41e1051a39Sopenharmony_ci    # Remove comments while preserving strings
42e1051a39Sopenharmony_ci    s{
43e1051a39Sopenharmony_ci         (?|                        # All things preserved end up in $1
44e1051a39Sopenharmony_ci
45e1051a39Sopenharmony_ci             /\*                    # C comment start
46e1051a39Sopenharmony_ci             .*?                    # Contents up until
47e1051a39Sopenharmony_ci             \*/                    # C comment end
48e1051a39Sopenharmony_ci
49e1051a39Sopenharmony_ci         |                          # OR
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_ci             (                      # Grouping for the replacement
52e1051a39Sopenharmony_ci                 $preserved
53e1051a39Sopenharmony_ci             )
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci         )
56e1051a39Sopenharmony_ci    }{
57e1051a39Sopenharmony_ci        if ($debug) {
58e1051a39Sopenharmony_ci            print STDERR "DEBUG: '$&' => '$1'\n" if defined $1;
59e1051a39Sopenharmony_ci            print STDERR "DEBUG: '$&' removed\n" unless defined $1;
60e1051a39Sopenharmony_ci        }
61e1051a39Sopenharmony_ci        defined $1 ? $1 : ""
62e1051a39Sopenharmony_ci    }gsxe;
63e1051a39Sopenharmony_ci
64e1051a39Sopenharmony_ci    # Remove empty lines
65e1051a39Sopenharmony_ci    s{
66e1051a39Sopenharmony_ci         (?|                        # All things preserved end up in $1
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_ci             (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_ci         |                          # OR
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ci             (                      # Grouping for the replacement
73e1051a39Sopenharmony_ci                 $preserved
74e1051a39Sopenharmony_ci             )
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ci         )
77e1051a39Sopenharmony_ci    }{$1}gsx;
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci    # Remove extra spaces
80e1051a39Sopenharmony_ci    s{
81e1051a39Sopenharmony_ci         (?|                        # All things preserved end up in $1
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_ci             \h+                    # Horizontal spaces replaced with one
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci         |                          # OR
86e1051a39Sopenharmony_ci
87e1051a39Sopenharmony_ci             (                      # Grouping for the replacement
88e1051a39Sopenharmony_ci                 $preserved
89e1051a39Sopenharmony_ci             )
90e1051a39Sopenharmony_ci
91e1051a39Sopenharmony_ci         )
92e1051a39Sopenharmony_ci    }{
93e1051a39Sopenharmony_ci        if ($debug) {
94e1051a39Sopenharmony_ci            print STDERR "DEBUG: '$&' => '$1'\n" if defined $1;
95e1051a39Sopenharmony_ci            print STDERR "DEBUG: '$&' => ' '\n" unless defined $1;
96e1051a39Sopenharmony_ci        }
97e1051a39Sopenharmony_ci        defined $1 ? $1 : " "
98e1051a39Sopenharmony_ci    }gsxe;
99e1051a39Sopenharmony_ci
100e1051a39Sopenharmony_ci    # Clean up spaces at start and end of lines
101e1051a39Sopenharmony_ci    s/^ //mg;
102e1051a39Sopenharmony_ci    s/ $//mg;
103e1051a39Sopenharmony_ci} elsif ($lang eq 'S') {
104e1051a39Sopenharmony_ci    # Because we use C++ style comments in our .S files, all we can do
105e1051a39Sopenharmony_ci    # is to drop them
106e1051a39Sopenharmony_ci    s{
107e1051a39Sopenharmony_ci         ^([^\n]*?)//[^\n]*?$   # Any line with a // comment
108e1051a39Sopenharmony_ci    }{
109e1051a39Sopenharmony_ci        if ($debug) {
110e1051a39Sopenharmony_ci            print STDERR "DEBUG: '$&' => '$1'\n" if defined $1;
111e1051a39Sopenharmony_ci            print STDERR "DEBUG: '$&' removed\n" unless defined $1;
112e1051a39Sopenharmony_ci        }
113e1051a39Sopenharmony_ci        defined $1 ? $1 : ""
114e1051a39Sopenharmony_ci    }mgsxe;
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci    # Drop all empty lines
117e1051a39Sopenharmony_ci    s{
118e1051a39Sopenharmony_ci         (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline
119e1051a39Sopenharmony_ci    }{$1}gsx;
120e1051a39Sopenharmony_ci} elsif ($lang eq 'perl') {
121e1051a39Sopenharmony_ci    # Merge continuation lines
122e1051a39Sopenharmony_ci    s{\\\n}{}g;
123e1051a39Sopenharmony_ci
124e1051a39Sopenharmony_ci    # Regexp for things that should be preserved
125e1051a39Sopenharmony_ci    my $preserved =
126e1051a39Sopenharmony_ci        qr{
127e1051a39Sopenharmony_ci              (?:
128e1051a39Sopenharmony_ci                  <<["']?(\w+)["']? # HERE document start
129e1051a39Sopenharmony_ci                  .*?               # Its contents
130e1051a39Sopenharmony_ci                  ^\g{-1}$
131e1051a39Sopenharmony_ci              )
132e1051a39Sopenharmony_ci          |
133e1051a39Sopenharmony_ci              (?:
134e1051a39Sopenharmony_ci                  "                 # Double quoted string start
135e1051a39Sopenharmony_ci                  (?: \\. | [^\"])* # Any character, including escaped ones
136e1051a39Sopenharmony_ci                  "                 # Double quoted string end
137e1051a39Sopenharmony_ci              )
138e1051a39Sopenharmony_ci
139e1051a39Sopenharmony_ci          |                         # OR
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci              (?:
142e1051a39Sopenharmony_ci                  '                 # Single quoted string start
143e1051a39Sopenharmony_ci                  [^\']*            # Any character
144e1051a39Sopenharmony_ci                  '                 # Single quoted string end
145e1051a39Sopenharmony_ci              )
146e1051a39Sopenharmony_ci        }msx;
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ci    # Remove comments while preserving strings
149e1051a39Sopenharmony_ci    s{
150e1051a39Sopenharmony_ci         (?|                        # All things preserved end up in $1
151e1051a39Sopenharmony_ci
152e1051a39Sopenharmony_ci             \#.*?(\n|$)            # Perl comments
153e1051a39Sopenharmony_ci
154e1051a39Sopenharmony_ci         |                          # OR
155e1051a39Sopenharmony_ci
156e1051a39Sopenharmony_ci             (                      # Grouping for the replacement
157e1051a39Sopenharmony_ci                 $preserved
158e1051a39Sopenharmony_ci             )
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci         )
161e1051a39Sopenharmony_ci    }{
162e1051a39Sopenharmony_ci        if ($debug) {
163e1051a39Sopenharmony_ci            print STDERR "DEBUG: '$&' => '$1'\n" if defined $1;
164e1051a39Sopenharmony_ci            print STDERR "DEBUG: '$&' removed\n" unless defined $1;
165e1051a39Sopenharmony_ci        }
166e1051a39Sopenharmony_ci        defined $1 ? $1 : ""
167e1051a39Sopenharmony_ci    }gsxe;
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    # Remove empty lines
170e1051a39Sopenharmony_ci    s{
171e1051a39Sopenharmony_ci         (?|                        # All things preserved end up in $1
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci             (^|\n)(?:\s*(?:\n|$))+ # Empty lines, preserve one newline
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ci         |                          # OR
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci             (                      # Grouping for the replacement
178e1051a39Sopenharmony_ci                 $preserved
179e1051a39Sopenharmony_ci             )
180e1051a39Sopenharmony_ci
181e1051a39Sopenharmony_ci         )
182e1051a39Sopenharmony_ci    }{$1}gsx;
183e1051a39Sopenharmony_ci}
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ciprint;
186