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