[SPOILER] Re: [Israel.pm] What does this code do? (No. 3)
Shlomi Fish
shlomif at iglu.org.il
Sun Jul 11 06:45:33 PDT 2004
On Sunday 11 July 2004 14:50, Yosef Meller wrote:
> Shlomi Fish wrote:
> > Here is the next installment in the "What does this code do?" series of
> > quizzes. You can post solutions to the list, but mark them with a
>
> [SPOILER]
>
> > in the title. Other discussions are also welcome.
> >
> > The script in question is:
> >
> > <<<
> > #!/usr/bin/perl -w
> >
> > use strict;
> >
> > my %lines_to_extract;
> >
> > open DECLS, "bash analyze-globals.sh |";
> > while (<DECLS>)
> > {
> > chomp($_);
> > my ($file,$line_num,$text) = /^(\w+\.c):(\d+):(.*)$/;
> > push @{$lines_to_extract{$file}}, +{ 'l' => $line_num, 't' =>
>
> $text, };
>
> > }
> > close(DECLS);
> >
> > my @lines_to_put = ();
> > foreach my $file (keys(%lines_to_extract))
> > {
> > my $lines = $lines_to_extract{$file};
> > my $line_num = 1;
> > my $extracted_line_idx = 0;
> > open I, "<$file";
> > open O, ">$file.new";
> > while (<I>)
> > {
> > if (($extracted_line_idx < @$lines) &&
> > ($line_num == $lines->[$extracted_line_idx]->{l})
> > )
> > {
> > push @lines_to_put, $_;
> > $extracted_line_idx++;
> > }
> > else
> > {
> > print O $_;
> > }
> > }
> > continue
> > {
> > $line_num++;
> > }
> > close(I);
> > close(O);
> > rename("$file.new", "$file");
> > }
> > open GLOBALS, ">globals.c";
> > print GLOBALS @lines_to_put;
> > close(GLOBALS);
> >
> >
> > It makes use of the bash script analyze-globals.sh which is:
> >
> > <<<
> > #!/bin/bash
> > grep -nP '^\S.*;' *.c | grep -v static | grep -vP '^\w+\.c:\d+:}'
> >
> >
> > Regards,
> >
> > Shlomi Fish
>
> This time you chose revealing variable names, so it was easy.
Hmmm... yes. I wrote my script this way originally, and as I prepared to send
it to this list, I decided that I did not have the nerve to change the
variable names, and just sent it as is.
> The script removes global variables from a bunch of files and puts them
> in globals.c, for good order I guess (haven't used C for a while).
Correct. More accurately, it removes all the non-"static" C variables, that
occupy names in the linker namespace.
As for good order, this was part of the reason, but not all of it. The context
of this script was that I wanted to revamp a rather poorly-written code
(gimp's gimpressionist plug-in), which had used a bootload of global
variables like that and accessed them from different places. I wanted to put
them in one file, so I can later try to eliminate as many of them as I can.
Generally, accessing global variables from a different module is considered
bad style. It is usually a good idea to make these variables static and
create non-static functions that manipulate them. This is what I have done
for most of these variables, eventually.
>
> The program assumes that the line numberes are sorted, which should be
> true, considering the method of generation.
Right again.
>
> The perl version I suggest:
>
>
> #!/path/to/perl -w
> open DECLS, "bash analyze-globals.sh |";
> while (<DECLS>) {
> /^(\w+\.c):(\d+):(.*)\n$/ and push @{$lines_to_extract{$1}},
> +{ 'l' => $2, 't' => $3 };
> }
>
> foreach my $file (keys(%lines_to_extract)) {
> my @lines = @{$lines_to_extract{$file}};
> my $line_num = 1;
> open I, "<$file";
> open O, ">$file.new";
> while (($_ = <I>) && @$lines)
> {
> if ($line_num++ == $lines->[0]->{l}) {
> # We'll use STDOUT for better flexibility, and one less
> # filehandle to worry aboyut
> print;
> shift @$lines;
> } else {
> print O $_;
> }
> }
> close(I);
> close(O);
> rename("$file.new", "$file");
> }
> <<<<<<
>
> Invoke with:
> $ ./thescript.pl > myglobals.c
Nice. Albeit, it does not seem substantially different than the original.
Somewhat more brief, though, I suppose.
>
> I'm sure there must be a way to use the -i switch, but I can't think of
> it right now.
Well, you can open GLOBALS in the BEGIN { } and use the $ARGV variable to
determine the file, and do all kinds of trickery like that. But it would be
more trouble than it is worth, if you ask me. (although I would be glad to be
shown otherwise).
Regards,
Shlomi Fish
--
---------------------------------------------------------------------
Shlomi Fish shlomif at iglu.org.il
Homepage: http://shlomif.il.eu.org/
Knuth is not God! It took him two days to build the Roman Empire.
More information about the Perl
mailing list