aboutsummaryrefslogtreecommitdiff
path: root/nls
diff options
context:
space:
mode:
Diffstat (limited to 'nls')
-rw-r--r--nls/nlsinfo291
1 files changed, 291 insertions, 0 deletions
diff --git a/nls/nlsinfo b/nls/nlsinfo
new file mode 100644
index 0000000..c7e5772
--- /dev/null
+++ b/nls/nlsinfo
@@ -0,0 +1,291 @@
1#!/usr/bin/perl -w
2
3# This perl script is intended to go through the fluxbox source
4# code searching for the special NLS strings. It then dumps
5# the requested details.
6#
7# I started trying to write it fairly generic, but it was difficult :-)
8# Should be fairly adaptable though
9#
10# It doesn't currently handle more than one NLS define per line
11# => If you get an "undefined" error, its probably 2 on one line
12
13$VERSION = "0.1";
14
15use strict;
16use Getopt::Std;
17
18$Getopt::Std::STANDARD_HELP_VERSION = 1;
19
20# the boolitem and focusitem is pretty dodgy, but it'll do for now
21my $match_re = "(?:_FB(?:TK)?TEXT|_BOOLITEM|_FOCUSITEM)";
22# regular expression for not a unquoted quote
23my $noquote = q'(?:[^\"]|\\")';
24
25my $fielddelim = "\0";
26my $recorddelim = "\0";
27
28#############################
29# Parse and validate arguments
30my %opts;
31
32my $command = $0;
33$command =~ s,^.*/,,;
34
35my $fullcommand = "$command " . join(" ", @ARGV);
36
37if (!getopts("d:fhn:pr:vFHN:R", \%opts)) {
38 HELP_MESSAGE("error");
39 exit(1);
40}
41
42sub HELP_MESSAGE {
43 my $arg = shift;
44 my $FD = *STDOUT;
45 if (defined($arg) && $arg eq "error") {
46 $FD = *STDERR;
47 }
48
49 print $FD "Usage: $command [options] directory\n";
50 print $FD " Where options can be:\n";
51 print $FD " -R\tDon't recurse into subdirectories.\n";
52 print $FD " -f\tThe argument is a file, not a directory\n";
53 print $FD " -F\tPrint full NLS names, not shorthand ones\n";
54 print $FD " -d delim\tUse delim as the default delimiter\n";
55 print $FD " -r delim\tUse delim as the record delimiter\n";
56 print $FD " -n\tHeader name, default FLUXBOX_NLS_HH\n";
57 print $FD " -N\tNamespace for header\n";
58 print $FD " -v\tverbose output\n";
59 print $FD " -h\tPrint this help message\n";
60 print $FD "\nPlus one of the following options that direct how to operate:\n";
61 print $FD " -H\tGenerate a header file for the strings encountered (-n implied).\n";
62 print $FD " -p\tPrint out a null-separated tuple of Set,String,Default,Description\n";
63 print $FD " \t\n";
64 print $FD "\n";
65
66}
67
68if (defined($opts{"h"})) {
69 HELP_MESSAGE();
70 exit(0);
71}
72
73my $num_modes = 0;
74my $mode;
75
76sub mode_opt {
77 my $opt = shift;
78 my $modename = shift;
79 return if (!defined($opts{$opt}));
80 $num_modes++;
81 $mode = $modename;
82}
83
84mode_opt("H", "header");
85mode_opt("p", "print");
86
87if ($num_modes == 0) {
88 print STDERR "Must give one mode of operation!\n";
89 HELP_MESSAGE("error");
90 exit(1);
91} elsif ($num_modes > 1) {
92 print STDERR "Too many modes of operation - must give exactly one!\n";
93 HELP_MESSAGE("error");
94 exit(1);
95}
96
97my $recurse = 1;
98$recurse = 0 if (defined($opts{"R"}));
99
100my $fullnames = 0;
101$fullnames = 1 if (defined($opts{"f"}) || $mode eq "header");
102
103my $headername = "FLUXBOX_NLS_HH";
104$headername = $opts{"n"} if (defined($opts{"n"}));
105
106my $namespace;
107$namespace = $opts{"N"} if (defined($opts{"N"}));
108
109my $verbose = 0;
110$verbose = 1 if (defined($opts{"v"}));
111
112if (defined($opts{"d"})) {
113 $fielddelim = $opts{"d"};
114 $recorddelim = $opts{"d"};
115}
116
117if (defined($opts{"r"})) {
118 $recorddelim = $opts{"r"};
119}
120
121
122if (scalar(@ARGV) == 0) {
123 print STDERR "Must give one more argument - the directory to scan\n";
124 exit(1);
125} elsif (scalar(@ARGV) > 1) {
126 print STDERR "Too many arguments, none expected after directory to scan\n";
127 exit(1);
128}
129
130
131my $dir = $ARGV[0];
132my $file;
133if (!defined($opts{"f"}) && ! -d $dir ) {
134 print STDERR "$dir is not a directory, aborting\n";
135 exit(2);
136} elsif (defined($opts{"f"})) {
137 $file = $dir;
138 undef $dir;
139 $recurse = 0;
140
141 if (! -r $file) {
142 print STDERR "$file is not a readable file, aborting\n";
143 exit(2);
144 }
145}
146
147
148#############################
149# Actually do stuff! (finally...)
150
151my %sets;
152
153if (defined($dir)) {
154 process_dir($dir);
155} else {
156 process_file($file);
157}
158
159# Now we have the data, we need to print it out
160eval "mode_$mode()";
161exit(0);
162
163# this function is given the fbtext arguments
164# But the first argument is the macro name...
165sub store {
166 my ($type, $set, $str, $default, $desc) = @_;
167
168 if ($type eq "_FBTKTEXT") {
169 $set = "FbTk$set";
170 }
171
172 if ($fullnames == 1) {
173 $str = $set . $str;
174 $set = $set . "Set";
175 }
176
177 $sets{$set}->{$str}{"default"} = $default;
178 $sets{$set}->{$str}{"desc"} = $desc;
179
180}
181
182# C strings can just be a bunch of quoted strings adjacent to
183# each other. This just puts them all together, removes the quotes
184# and unquotes anything we want to.
185# there may be newlines embedded... compare everything /s
186sub squish {
187 my $str = shift;
188
189 # remove first and last quote
190 $str =~ s/^\s*\"//s;
191 $str =~ s/\"\s*$//s;
192
193 # now remove any inner quotes and intervening spaces
194 $str =~ s/([^\\])\"\s*\"/$1/sg;
195
196 # finally, unescape any remaining quotes
197 $str =~ s/\\\"/\"/g;
198
199 return $str;
200}
201
202sub process_dir {
203 my $dir = shift;
204 print STDERR "Processing directory '$dir'\n" if ($verbose == 1);
205 opendir(DIR, $dir) || die "can't opendir $dir: $!";
206 my @files = grep { ( /\.(cc|hh)$/ && -f "$dir/$_" ) ||
207 ( -d "$dir/$_" && $_ !~ /^\.\.?$/ )
208 } readdir(DIR);
209 closedir DIR;
210
211 foreach my $file (@files) {
212 if (-d "$dir/$file") {
213 process_dir("$dir/$file") if ($recurse == 1);
214 } else {
215 process_file("$dir/$file");
216 }
217 }
218}
219
220# assumptions for now:
221# - no more than one NLS thing on any single line
222# - internal parenthesis are balanced
223# - one nls thing can span several lines
224sub process_file {
225 my $file = shift;
226
227 print STDERR "Processing file '$file'\n" if ($verbose == 1);
228 open(FILE, "<$file") || die "Can't open file $file: $!";
229
230 while (<FILE>) {
231 chomp;
232 if (/$match_re/ && $_ !~ /^\#(define|undef)/) {
233 my $tail = $_;
234 # strip away leading stuff
235 # note that this doesn't work with more than one match on a line
236 $tail =~ s/^.*($match_re)/$1/;
237 # now we just need to find the end, looking out for any
238 # quotes
239 my $end = 0;
240 my $full = $tail;
241 while ($end == 0) {
242 # match the defined macro, plus the first 4 arguments
243 # (ignore any more), then handle them
244 if ($full =~ /^($match_re)\(([^,]+),\s*([^,]+),((?:\s*\"$noquote*\")+),((?:\s*"$noquote*")+)\s*(?:,.*)?\)/s ) {
245 store($1, $2, $3, squish($4), squish($5));
246 $end++;
247 } else {
248 my $extra = <FILE>;
249 last if (!defined($extra));
250 $full .= $extra;
251 }
252 }
253 }
254 }
255 close(FILE);
256}
257
258
259sub mode_print {
260 foreach my $set (sort keys %sets) {
261 foreach my $str (sort keys %{$sets{$set}}) {
262 print $set . $fielddelim . $str . $fielddelim . $sets{$set}->{$str}{"default"} . $fielddelim . $sets{$set}->{$str}{"desc"} . $recorddelim;
263 }
264 }
265}
266
267sub mode_header {
268 print "// This file generated by $fullcommand, on " . localtime() . "\n\n";
269 print "#ifndef $headername\n";
270 print "#define $headername\n\n";
271 print "namespace $namespace {\n\n" if (defined($namespace));
272 print "enum {\n";
273
274 my $setnum = 0;
275 foreach my $set (sort keys %sets) {
276 $setnum++;
277 printf "\t%s = 0x%x,\n", $set, $setnum;
278
279 my $strnum = 0;
280 foreach my $str (sort keys %{$sets{$set}}) {
281 $strnum++;
282 printf "\t%s = 0x%x,\n", $str, $strnum;
283 }
284 print "\n";
285 }
286 print "\tdummy_not_used = 0 // just for the end\n\n";
287 print "}; // end enum\n\n";
288 print "}; // end namespace $namespace\n\n" if (defined($namespace));
289 print "#endif // $headername\n";
290}
291