On Mon, Jan 14, 2002 at 07:32:15PM -0500, Aaron D. Marasco wrote:
> OK, here is a problem I ran into (well, created) at work. I would like to
> be able to paste an as-short-as-possible perl script at the end of a VHDL
> file so that people can run it to change the interfaces (don't worry if you
> don't get this).
>
> Anyway, here is the data going in (VHDL comments outlining what the
> interface does):
>
> -- SUN:
> -- S_RSTb out
> -- S_INTb in
> -- CMX INTERFACE:
> -- CMX_CSb in
> -- CMX_D inout 7
> -- CMX_A inout 7
>
> Here is the desired output VHDL:
>
> --== SUN ==--
> S_RSTb : out std_logic;
> S_INTb : in std_logic;
> --== CMX INTERFACE ==--
> CMX_CSb : in std_logic;
> CMX_D : inout std_logic_vector(7 downto 0);
> CMX_A : inout std_logic_vector(7 downto 0);
>
> The colons are aligned vertically with the length of the longest signal
> name plus a space.
>
> Please explain if you are doing anything "complicated" so we can all learn.
> ;)
>
> The double hyphen in front of the incoming text is optional and could have
> spaces on either side of it. The spaces between "fields" is arbitrary (but
> never tabs). The signal fields always have at least one space on the left,
> and the comments always have the colon at the end (makes script a lot
> simpler). The overall length of the script is the most important, speed is
> no concern. Lines are limited to 78 characters too. :(
>
> Here is my attempt, at 7 lines (need to count #! line)...
>
> #!/cygdrive/r/perl/bin/perl -n
> if(/[\s-]*([^:]*)\s*:/){$a[$.]="--== $1 ==--\n";next}
> ($a[$.],$b[$.],$c[$.])=/\s+(\w+)\s*(\w*)\s*(\d*)/;
> $l=length$1;$m=$l if($l>$m);
> END{foreach$i(1..$.){$r=$a[$i];print$r;if($r!~/=/){
> print" "x($m-length$r)." : $b[$i] std_logic";
> print (($c[$i]!='')?"_vector($c[$i] downto 0);\n":"\n")}}}
-- SUN:
-- S_RSTb out
-- S_INTb in
-- CMX INTERFACE:
-- CMX_CSb in
-- CMX_D inout 7
-- CMX_A inout 7
SUN:
S_RSTb out
S_INTb in
CMX INTERFACE:
CMX_CSb in
CMX_D inout 7
CMX_A inout 7
#!/usr/bin/perl # run this file with perl -x
seek(DATA,0,0);
foreach (<DATA>) {
last if /^#!/;
/(\w+):/ && do { print "--== $1 ==--\n"; next; };
/(\w+)[ ]+ (\w+)(?:[ ]+(\d+))?/ &&
do { $sl = length $3 ? "_vector($3 downto 0);" : ';';
printf "%-8s: %s std_logic%s\n", $1, $2, $sl; next; };
}
__DATA__
This is literally the whole script, including the VHDL. Run with perl
-x (the "ignore everything before the first #! line" switch) and it'll
parse out the VHDL above it. The only real tricks are -x and the
seek(DATA,0,0) trick. The DATA filehandle is for the current file
(you have to have the __DATA__ there), so you just seek to the top
(ie. the VHDL) and start reading. The for loop ends itself when it
sees a #!.
I made sure to use [ ]+ in favor of \s+ since you mentioned tabs are
not allowed.
I cheated a little using printf instead of actually calculating the
length of the longest first field.
And here's a compressed version.
-- SUN:
-- S_RSTb out
-- S_INTb in
-- CMX INTERFACE:
-- CMX_CSb in
-- CMX_D inout 7
-- CMX_A inout 7
SUN:
S_RSTb out
S_INTb in
CMX INTERFACE:
CMX_CSb in
CMX_D inout 7
CMX_A inout 7
#!/usr/bin/perl # run this file with perl -x
seek(DATA,0,0);for(<DATA>){/^#!/&&last;/(\w+):/&&print("--== $1 ==--\n")
&&next;/(\w+)[ ]+ (\w+)(?:[ ]+(\d+))?/&&($sl = length $3 ? "_vector($3 ".
"downto 0);":';')&&printf("%-8s: %s std_logic%s\n",$1,$2,$sl)&&next}
__DATA__
--
Michael G. Schwern <[EMAIL PROTECTED]> http://www.pobox.com/~schwern/
Perl Quality Assurance <[EMAIL PROTECTED]> Kwalitee Is Job One
A tickle of paste
Teases down my sweaty thigh
Oh, plug it again!
-- ignatz