#!/usr/bin/perl # # Routine to read define'd constants from a Verilog or C header # If expressions are used, they need to be defined with care to # be able to evaluate them. Conditionals are NOT processed. # use strict; use Math::BigInt; sub header_const($) { my($file) = @_; my %bases = ('d' => 10, 'b' => 2, 'o' => 8, 'q' => 8, 'h' => 16, 'x' => 16, '0' => 8, '0x' => 16, '' => 10); my %syms = (); open(my $f, '<', $file) or die "$0: $file: $!\n"; while (defined(my $l = <$f>)) { chomp $l; while ($l =~ /\/$/) { my $ll = <$f>; last unless (defined($ll)); chomp $ll; $l = substr($l,0,-1) . $ll; } $l =~ s/\/\/.*$//; $l =~ s/\/\*.*?\*\///g; if ($l =~ /^\s*[\`\#]\s*define\s+\`?([[:alpha:]_]\w*)\s+(.*?)\s*$/) { $syms{$1} = $2; } elsif ($l =~ /^\s*[\`\#]\s*undef\s+\`?([[:alpha:]_]\w*)/) { delete $syms{$1}; } } close($f); foreach my $s (keys %syms) { my $e = $syms{$s}; my $o = ''; # Don't try to evaluate if... next if ($e =~ /[\"\$\@\[\{\\]/); $e =~ s/\`//g; while ($e =~ /^(.*?)\b[0-9]*\'([bhod])([0-9a-f_]+)\b(.*)$/i || $e =~ /^(.*?)\b()(0[0-7_]+|0b[0-1_]+|0x[0-9a-f_]+)\b(.*)$/i) { $e = $4; $o .= $1; my $base = lc($2); my $dig = $3; $dig =~ s/_//g; if ($base ne '') { $base = $bases{$base}; } elsif ($dig =~ /^0x/i) { $base = 16; } elsif ($dig =~ /^0b/i) { $base = 2; } elsif ($dig =~ /^0/) { $base = 8; } $o .= Math::BigInt::from_base($dig, $base)->bstr(); } $syms{$s} = $o.$e; } foreach my $s (keys %syms) { my $e = $syms{$s}; my $o = ''; while ($e =~ /^(.*?)\b\`?([[:alpha:]_]\w*)\b(.*)$/) { $e = $3; $o .= $1; if (defined($syms{$2})) { $e = $syms{$2} . $e; } else { $o .= $2; } } $syms{$s} = eval("{ use bigint; return Math::BigInt->new($o$e)->numify(); }"); } return %syms; } 1;