Reputation: 155
I am developing a perl script that generates Verilog templates based on command line arguments. To that, i need to write the same header to multiple files in a loop. here is my code.
format MODULE_TOP=
// --------------------------------------------------------------------
// RELEASE HISTORY
// VERSION DATE AUTHOR DESCRIPTION
// @<<<<<< @<<<<<<<<<<<<<< @<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<
$VERSION,$DATE,$AUTHOR,$DESCRIPTION
// --------------------------------------------------------------------
// KEYWORDS :
// --------------------------------------------------------------------
// PURPOSE :
// --------------------------------------------------------------------
.
format MODULE=
module @<<<<<< (
$module_name
);
//signal declarations
//main body of the module
endmodule
foreach (@modules) {
$file_name = "$_.v";
open MODULE,'>',$file_name or die "$!";
$FILENAME = $file_name;
$module_name = $_;
write MODULE;
close MODULE;
}
But the header in getting written to only the first file, The rest of the modules contain only the body. Is there any way to write the header in all the files.
Upvotes: 0
Views: 340
Reputation: 52354
It's not writing the header to each file because closing and re-opening the MODULE
handle doesn't reset $-
($FORMAT_LINES_LEFT
with use English;
), the variable that tracks how many lines are left in the current page. If you reset that variable to 0 each time you reopen the file handle with a new file, it'll make the format reset to a new page. It's not clear from the documentation, but you ALSO have to re-select
the file handle before doing that. Reusing file handles is tricky; one of many reasons it's good style to use autovivified ones instead of bare handles (Though that doesn't save you from having to use select
when using formats).
#!/usr/bin/perl
use warnings;
use strict;
use autodie;
our $file;
format FOO_TOP =
Header line
-----------
.
format FOO =
Body of @<<<<<<
$file
.
for $file ("a.txt", "b.txt") {
open FOO, ">", $file;
my $oldfd = select FOO;
$- = 0;
select $oldfd;
write FOO;
close FOO;
}
The loop in the above can be written in a more modern style like so:
for $file ("a.txt", "b.txt") {
open my $foo, ">", $file;
my $oldfd = select $foo;
$^ = "FOO_TOP";
$~ = "FOO";
select $oldfd;
write $foo;
close $foo;
}
Another, cleaner looking approach is to use the methods in the IO::Handle module:
for $file ("a.txt", "b.txt") {
open FOO, ">", $file;
format_lines_left FOO 0;
write FOO;
close FOO;
}
or
for $file ("a.txt", "b.txt") {
open my $foo, ">", $file;
$foo->format_name("FOO");
$foo->format_top_name("FOO_TOP");
write $foo;
close $foo;
}
which does the select
wrapping for you.
Upvotes: 1