File Coverage

blib/lib/Verilog/Getopt.pm
Criterion Covered Total %
statement 294 353 83.2
branch 120 170 70.5
condition 59 98 60.2
subroutine 35 39 89.7
pod 23 29 79.3
total 531 689 77.0


line stmt bran cond sub pod time code
1             # See copyright, etc in below POD section.
2             ######################################################################
3              
4             package Verilog::Getopt;
5             require 5.000;
6             require Exporter;
7              
8 15     15   214808 use strict;
  15         41  
  15         439  
9 15     15   73 use vars qw($VERSION $Debug %Skip_Basenames);
  15         18  
  15         630  
10 15     15   73 use Carp;
  15         22  
  15         685  
11 15     15   75 use IO::File;
  15         26  
  15         1607  
12 15     15   88 use File::Basename;
  15         18  
  15         1231  
13 15     15   94 use File::Spec;
  15         21  
  15         299  
14 15     15   61 use Cwd;
  15         17  
  15         53481  
15              
16             ######################################################################
17             #### Configuration Section
18              
19             $VERSION = '3.480';
20              
21             # Basenames we should ignore when recursing directories,
22             # Because they contain large files of no relevance
23             foreach ( '.', '..',
24             'CVS',
25             '.svn',
26             '.snapshot',
27             'blib',
28             ) {
29             $Skip_Basenames{$_} = 1;
30             }
31              
32             #######################################################################
33             #######################################################################
34             #######################################################################
35              
36             sub new {
37 752 50   752 1 76644 @_ >= 1 or croak 'usage: Verilog::Getopt->new ({options})';
38 752         1054 my $class = shift; # Class (Getopt Element)
39 752   50     1306 $class ||= "Verilog::Getopt";
40              
41 752         6300 my $self = {defines => {},
42             incdir => ['.', ],
43             includes => {},
44             module_dir => ['.', ],
45             libext => ['.v', ],
46             library => [ ],
47             gcc_style => 1,
48             vcs_style => 1,
49             filename_expansion => 0,
50             fileline => 'Command_Line',
51             unparsed => [],
52             define_warnings => 1,
53             depend_files => {},
54             @_
55             };
56 752         1385 bless $self, $class;
57 752         3281 return $self;
58             }
59              
60             #######################################################################
61             # Option parsing
62              
63             sub _filedir {
64 3     3   4 my $self = shift;
65 3         3 my $path = shift;
66 3 50       16 $path =~ s![/\\][^/\\]*$!! # ~~== my @dirs = File::Spec->splitdir( $path );
67             or $path = ".";
68 3 50       6 return "." if $path eq '';
69 3         6 return $path
70             }
71              
72             sub parameter_file {
73 6     6 0 7 my $self = shift;
74 6         5 my $filename = shift;
75 6         5 my $relative = shift;
76              
77 6 50       50 print "*parameter_file $filename\n" if $Debug;
78 6         12 my $optdir = ".";
79 6 100       11 if ($relative) { $optdir = $self->_filedir($filename); }
  3         9  
80              
81 6 50       30 my $fh = IO::File->new("<$filename") or die "%Error: ".$self->fileline().": $! $filename\n";
82 6         405 my $hold_fileline = $self->fileline();
83 6         140 while (my $line = $fh->getline()) {
84 24         544 chomp $line;
85 24         47 $line =~ s/(?:^|\s)\/\/.*$//;
86 24 100       223 next if $line =~ /^\s*$/;
87 12         49 $self->fileline("$filename:$.");
88 12         41 my @p = (split /\s+/,"$line ");
89 12         21 $self->_parameter_parse($optdir, @p);
90             }
91 6         175 $fh->close();
92 6         88 $self->fileline($hold_fileline);
93             }
94              
95             sub parameter {
96 21     21 1 89 my $self = shift;
97             # Parse VCS like parameters, and perform standard setup based on it
98             # Return list of leftover parameters
99 21         25 @{$self->{unparsed}} = ();
  21         54  
100 21         61 $self->_parameter_parse('.', @_);
101 21         37 return @{$self->{unparsed}};
  21         61  
102             }
103              
104             sub _parameter_parse {
105 33     33   39 my $self = shift;
106 33         40 my $optdir = shift;
107             # Internal: Parse list of VCS like parameters, and perform standard setup based on it
108 33         55 foreach my $oparam (@_) {
109 129         188 my $param = "$oparam"; # Must quote to convert Getopt to string, bug298
110 129 50       390 next if ($param =~ /^\s*$/);
111 129 100       757 print " parameter($param)\n" if $Debug;
112              
113             ### GCC & VCS style
114 129 100 100     1467 if ($param eq '-F'
    100 100        
    100 66        
    100 66        
    100 66        
    50 66        
    100 33        
    50 66        
    100 66        
    100 33        
      66        
115             || $param eq '-f') {
116 6         13 $self->{_parameter_next} = $param;
117             }
118              
119             ### VCS style
120             elsif (($param eq '-v'
121             || $param eq '-y') && $self->{vcs_style}) {
122 22         44 $self->{_parameter_next} = $param;
123             }
124             elsif ($param =~ /^\+libext\+(.*)$/ && $self->{vcs_style}) {
125 3         7 my $ext = $1;
126 3         6 foreach (split /\+/, $ext) {
127 4         8 $self->libext($_);
128             }
129             }
130             elsif ($param =~ /^\+incdir\+(.*)$/ && $self->{vcs_style}) {
131 21         66 $self->incdir($self->_parse_file_arg($optdir, $1));
132             }
133             elsif ($param =~ /^\+define\+(.*)$/ && $self->{vcs_style}) {
134 21         58 foreach my $tok (split("\\+", $1)) {
135 23         80 my ($a, $b) = $tok =~ m/^([^=]*)=?(.*)$/;
136 23         47 $self->define($a,$b,undef,1);
137             }
138             }
139             # Ignored
140             elsif ($param =~ /^\+librescan$/ && $self->{vcs_style}) {
141             }
142              
143             ### GCC style
144             elsif (($param =~ /^-D([^=]*)=(.*)$/
145             || $param =~ /^-D([^=]*)()$/) && $self->{gcc_style}) {
146 6         13 $self->define($1,$2,undef,1);
147             }
148             elsif (($param =~ /^-U([^=]*)$/) && $self->{gcc_style}) {
149 0         0 $self->undef($1);
150             }
151             elsif ($param =~ /^-I(.*)$/ && $self->{gcc_style}) {
152 2         4 $self->incdir($self->_parse_file_arg($optdir, $1));
153             }
154              
155             # Second parameters
156             elsif ($self->{_parameter_next}) {
157 28         47 my $pn = $self->{_parameter_next};
158 28         36 $self->{_parameter_next} = undef;
159 28 100       93 if ($pn eq '-F') {
    100          
    100          
    50          
160 3         7 $self->parameter_file($self->_parse_file_arg($optdir,$param), 1);
161             }
162             elsif ($pn eq '-f') {
163 3         6 $self->parameter_file($self->_parse_file_arg($optdir,$param), 0);
164             }
165             elsif ($pn eq '-v') {
166 3         6 $self->library($self->_parse_file_arg($optdir,$param));
167             }
168             elsif ($pn eq '-y') {
169 19         47 $self->module_dir($self->_parse_file_arg($optdir,$param));
170             }
171             else {
172 0         0 die "%Error: ".$self->fileline().": Bad internal next param ".$pn;
173             }
174             }
175              
176             else { # Unknown.
177 20 50 33     39 if ($self->{filename_expansion}
      33        
178             && $param !~ /^-.*$/ # Presume not a file
179             && $optdir ne '.') {
180             # If it is a filename, we should ensure it is
181             # relative to $optdir. We assume anything without a leading '-'
182             # is a file, bug 444.
183 0         0 my $fn = $self->_parse_file_arg($optdir,$param);
184 0 0       0 if (-e $fn) {
185 0         0 push @{$self->{unparsed}}, "$fn";
  0         0  
186             } else {
187 0         0 push @{$self->{unparsed}}, "$param";
  0         0  
188             }
189             } else {
190 20         16 push @{$self->{unparsed}}, "$param";
  20         136  
191             }
192             }
193             }
194             }
195              
196             sub _parse_file_arg {
197 51     51   52 my $self = shift;
198 51         56 my $optdir = shift;
199 51         68 my $relfilename = shift;
200             # Parse filename on option line, expanding relative paths in -F's
201 51         82 my $filename = $self->file_substitute($relfilename);
202 51 100 66     128 if ($optdir ne "." && ! File::Spec->file_name_is_absolute($filename)) {
203 2         19 $filename = File::Spec->catfile($optdir,$filename);
204             }
205 51         108 return $filename;
206             }
207              
208             #######################################################################
209             # Accessors
210              
211             sub fileline {
212 8544     8544 0 8200 my $self = shift;
213 8544 100       12287 if (@_) { $self->{fileline} = shift; }
  8537         9503  
214 8544         10122 return ($self->{fileline});
215             }
216             sub incdir {
217 108     108 1 338 my $self = shift;
218 108 100       296 if (@_) {
219 50         56 my $token = shift;
220 50 100       119 print "incdir $token\n" if $Debug;
221 50 100 66     118 if (ref($token) && ref($token) eq 'ARRAY') {
222 1         1 @{$self->{incdir}} = @{$token};
  1         3  
  1         2  
223             } else {
224 49         58 push @{$self->{incdir}}, $self->file_abs($token);
  49         117  
225             }
226 50         89 $self->file_path_cache_flush();
227             }
228 108 100       226 return (wantarray ? @{$self->{incdir}} : $self->{incdir});
  58         194  
229             }
230             sub libext {
231 7     7 1 8 my $self = shift;
232 7 100       12 if (@_) {
233 4         5 my $token = shift;
234 4 50       22 print "libext $token\n" if $Debug;
235 4 50 33     13 if (ref($token) && ref($token) eq 'ARRAY') {
236 0         0 @{$self->{libext}} = @{$token};
  0         0  
  0         0  
237             } else {
238 4         3 push @{$self->{libext}}, $token;
  4         9  
239             }
240 4         14 $self->file_path_cache_flush();
241             }
242 7 100       16 return (wantarray ? @{$self->{libext}} : $self->{libext});
  3         7  
243             }
244             sub library {
245 12     12 1 16 my $self = shift;
246 12 100       26 if (@_) {
247 3         3 my $token = shift;
248 3 50       21 print "library $token\n" if $Debug;
249 3 50 33     15 if (ref($token) && ref($token) eq 'ARRAY') {
250 0         0 @{$self->{library}} = @{$token};
  0         0  
  0         0  
251             } else {
252 3         3 push @{$self->{library}}, $self->file_abs($token);
  3         7  
253             }
254             }
255 12 100       28 return (wantarray ? @{$self->{library}} : $self->{library});
  9         22  
256             }
257             sub module_dir {
258 134     134 1 182 my $self = shift;
259 134 100       250 if (@_) {
260 46         52 my $token = shift;
261 46 100       126 print "module_dir $token\n" if $Debug;
262 46 100 66     109 if (ref($token) && ref($token) eq 'ARRAY') {
263 1         1 @{$self->{module_dir}} = @{$token};
  1         3  
  1         2  
264             } else {
265 45         57 push @{$self->{module_dir}}, $self->file_abs($token);
  45         93  
266             }
267 46         70 $self->file_path_cache_flush();
268             }
269 134 100       296 return (wantarray ? @{$self->{module_dir}} : $self->{module_dir});
  88         223  
270             }
271             sub depend_files {
272 563     563 1 846 my $self = shift;
273 563 50       1285 if (@_) {
274             #@_ may be Getopt::Long::Parameters which aren't arrays, will stringify
275 563 50 33     1334 if (ref($_[0]) && ref($_[0]) eq 'ARRAY') {
276 0         0 $self->{depend_files} = {};
277 0         0 foreach my $fn (@{$_[0]}) {
  0         0  
278 0         0 $self->{depend_files}{$fn} = 1;
279             }
280             } else {
281 563         916 foreach my $fn (@_) {
282 563 100       1147 print "depend_files $fn\n" if $Debug;
283 563         1314 $self->{depend_files}{$fn} = 1;
284             }
285             }
286             }
287 563         691 my @list = (sort (keys %{$self->{depend_files}}));
  563         2872  
288 563 50       1565 return (wantarray ? @list : \@list);
289             }
290              
291             sub get_parameters {
292 3     3 1 303 my $self = shift;
293 3         7 my %args = (gcc_stlyle => $self->{gcc_style},);
294             # Defines
295 3         4 my @params = ();
296 3         4 foreach my $def ($self->define_names_sorted) {
297 13         18 my $defvalue = $self->defvalue($def);
298 13 100 50     53 $defvalue = "=".($defvalue||"") if (defined $defvalue && $defvalue ne "");
      66        
299 13 50       19 if ($args{gcc_style}) {
300 0         0 push @params, "-D${def}${defvalue}";
301             } else {
302 13         21 push @params, "+define+${def}${defvalue}";
303             }
304             }
305             # Put all libexts on one line, else NC-Verilog will bitch
306 3         4 my $exts="";
307 3         6 foreach my $ext ($self->libext()) {
308 5 100       7 $exts = "+libext" if !$exts;
309 5         7 $exts .= "+$ext";
310             }
311 3 50       6 push @params, $exts if $exts;
312             # Includes...
313 3         5 foreach my $dir ($self->incdir()) {
314 7 50       9 if ($args{gcc_style}) {
315 0         0 push @params, "-I${dir}";
316             } else {
317 7         10 push @params, "+incdir+${dir}";
318             }
319             }
320 3         5 foreach my $dir ($self->module_dir()) {
321 9         11 push @params, "-y", $dir;
322             }
323 3         5 foreach my $dir ($self->library()) {
324 2         3 push @params, "-v", $dir;
325             }
326 3         16 return (@params);
327             }
328              
329             sub write_parameters_file {
330 0     0 1 0 my $self = shift;
331 0         0 my $filename = shift;
332             # Write get_parameters to a file
333 0 0       0 my $fh = IO::File->new(">$filename") or croak "%Error: $! writing $filename,";
334 0         0 my @opts = $self->get_parameters();
335 0         0 print $fh join("\n",@opts);
336 0         0 $fh->close;
337             }
338              
339             sub includes {
340 33     33 1 46 my $self = shift;
341 33 50       93 if (@_) {
342 33         44 my $from_filename = shift;
343 33         53 my $inc_filename = shift;
344 33         105 $self->{includes}{$from_filename}{$inc_filename} = 1;
345             }
346 33         58 return $self->{includes};
347             }
348              
349             #######################################################################
350             # Utility functions
351              
352             sub remove_duplicates {
353 0   0 0 0 0 my $self = ref $_[0] && shift;
354             # return list in same order, with any duplicates removed
355 0         0 my @rtn;
356             my %hit;
357 0 0       0 foreach (@_) { push @rtn, $_ unless $hit{$_}++; }
  0         0  
358 0         0 return @rtn;
359             }
360              
361             sub file_skip_special {
362 3     3 1 240 my $self = shift;
363 3         3 my $filename = shift;
364 3         10 $filename =~ s!.*[/\\]!!;
365 3         11 return $Skip_Basenames{$filename};
366             }
367              
368             sub file_abs {
369 97     97 1 97 my $self = shift;
370 97         93 my $filename = shift;
371             # return absolute filename
372             # If the user doesn't want this absolutification, they can just
373             # make their own derived class and override this function.
374             #
375             # We don't absolutify files that don't have any path,
376             # as file_path() will probably be used to resolve them.
377 97         181 return $filename;
378 0 0       0 return $filename if ("" eq dirname($filename));
379 0 0       0 return $filename if File::Spec->file_name_is_absolute($filename);
380             # Cwd::abspath() requires files to exist. Too annoying...
381 0         0 $filename = File::Spec->canonpath(File::Spec->catdir(Cwd::getcwd(),$filename));
382 0         0 return $filename;
383             }
384              
385             sub file_substitute {
386 370     370 1 597 my $self = shift;
387 370         342 my $filename = shift;
388 370         328 my $out = $filename;
389 370         676 while ($filename =~ /\$([A-Za-z_0-9]+)\b/g) {
390 9         26 my $var = $1;
391 9 100       73 $out =~ s/\$$var\b/$ENV{$var}/g if defined $ENV{$var};
392             }
393 370         535 while ($filename =~ /\$\{([A-Za-z_0-9]+)\}/g) {
394 0         0 my $var = $1;
395 0 0       0 $out =~ s/\$\{$var\}/$ENV{$var}/g if defined $ENV{$var};
396             }
397 370         381 $out =~ s!^~!$ENV{HOME}/!;
398 370         638 return $out;
399             }
400              
401             sub file_path_cache_flush {
402 100     100 0 98 my $self = shift;
403             # Clear out a file_path cache, needed if the incdir/module_dirs change
404 100         185 $self->{_file_path_cache} = {};
405             }
406              
407             sub file_path {
408 601     601 1 742 my $self = shift;
409 601         704 my $filename = shift;
410 601   100     1723 my $lookup_type = shift || 'all';
411             # return path to given filename using library directories & files, or undef
412             # locations are cached, because -r can be a very slow operation
413              
414 601 50       1118 defined $filename or carp "%Error: Undefined filename,";
415 601 100       1243 return $self->{_file_path_cache}{$filename} if defined $self->{_file_path_cache}{$filename};
416 576 100 66     15324 if (-r $filename && !-d $filename) {
417 492         2089 $self->{_file_path_cache}{$filename} = $filename;
418 492         1558 $self->depend_files($filename);
419 492         1428 return $filename;
420             }
421             # Try expanding environment
422 84         309 $filename = $self->file_substitute($filename);
423 84 50 33     559 if (-r $filename && !-d $filename) {
424 0         0 $self->{_file_path_cache}{$filename} = $filename;
425 0         0 $self->depend_files($filename);
426 0         0 return $filename;
427             }
428              
429             # What paths to use?
430 84         148 my @dirlist;
431 84 100       192 if ($lookup_type eq 'module') {
    50          
432 30         90 @dirlist = $self->module_dir();
433             } elsif ($lookup_type eq 'include') {
434 0         0 @dirlist = $self->incdir();
435             } else { # all
436             # Might be more obvious if -y had priority, but we'll remain back compatible
437 54         125 @dirlist = ($self->incdir(), $self->module_dir());
438             }
439             # Expand any envvars in incdir/moduledir
440 84         173 @dirlist = map {$self->file_substitute($_)} @dirlist;
  234         271  
441              
442             # Check each search path
443             # We use both the incdir and moduledir. This isn't strictly correct,
444             # but it's fairly silly to have to specify both all of the time.
445 84         116 my %checked_dir = ();
446 84         89 my %checked_file = ();
447 84         131 foreach my $dir (@dirlist) {
448 168 100       313 next if $checked_dir{$dir}; $checked_dir{$dir}=1; # -r can be quite slow
  165         274  
449             # Check each postfix added to the file
450 165         171 foreach my $postfix ("", @{$self->{libext}}) {
  165         262  
451 283         594 my $found = "$dir/$filename$postfix";
452 283 50       411 next if $checked_file{$found}; $checked_file{$found}=1; # -r can be quite slow
  283         423  
453 283 100 66     3157 if (-r $found && !-d $found) {
454 71         237 $self->{_file_path_cache}{$filename} = $found;
455 71         176 $self->depend_files($found);
456 71         337 return $found;
457             }
458             }
459             }
460              
461 13         68 return $filename; # Let whoever needs it discover it doesn't exist
462             }
463              
464             sub libext_matches {
465 0     0 1 0 my $self = shift;
466 0         0 my $filename = shift;
467 0 0       0 return undef if !$filename;
468 0         0 foreach my $postfix (@{$self->{libext}}) {
  0         0  
469 0         0 my $re = quotemeta($postfix) . "\$";
470 0 0       0 return $filename if ($filename =~ /$re/);
471             }
472 0         0 return undef;
473             }
474              
475             sub map_directories {
476 1     1 0 478 my $self = shift;
477 1         1 my $func = shift;
478             # Execute map function on all directories listed in self.
479             {
480 1         2 my @newdir = $self->incdir();
481 1         3 @newdir = map {&{$func}} @newdir;
  3         10  
  3         4  
482 1         7 $self->incdir(\@newdir);
483             }
484             {
485 1         2 my @newdir = $self->module_dir();
  1         1  
  1         3  
486 1         2 @newdir = map {&{$func}} @newdir;
  4         12  
  4         5  
487 1         6 $self->module_dir(\@newdir);
488             }
489             }
490              
491             #######################################################################
492             # Getopt functions
493              
494             sub define_names_sorted {
495 3     3 1 3 my $self = shift;
496 3         4 return (sort (keys %{$self->{defines}}));
  3         14  
497             }
498              
499             sub defcmdline {
500 1186     1186 0 935 my $self = shift;
501 1186         940 my $token = shift;
502 1186         1120 my $val = $self->{defines}{$token};
503 1186 100       1219 if (ref $val) {
504 702         1151 return $val->[2];
505             } else {
506 484         670 return undef;
507             }
508             }
509              
510             sub defparams {
511 2529     2529 1 2466 my $self = shift;
512 2529         2653 my $token = shift;
513 2529         3046 my $val = $self->{defines}{$token};
514 2529 100 100     6128 if (!defined $val) {
    100          
515 606         1109 return undef;
516             } elsif (ref $val && defined $val->[1]) {
517 828         1772 return $val->[1]; # Has parameters hash, return param list or undef
518             } else {
519 1095         1863 return 0;
520             }
521             }
522             sub defvalue {
523 1730     1730 1 2146 my $self = shift;
524 1730         1604 my $token = shift;
525 1730         1865 my $val = $self->{defines}{$token};
526 1730 50       2193 (defined $val) or carp "%Warning: ".$self->fileline().": No definition for $token,";
527 1730 100       2457 if (ref $val) {
528 926         11354 return $val->[0]; # Has parameters, return just value
529             } else {
530 804         4754 return $val;
531             }
532             }
533             sub defvalue_nowarn {
534 555     555 1 653 my $self = shift;
535 555         921 my $token = shift;
536 555         879 my $val = $self->{defines}{$token};
537 555 50       951 if (ref $val) {
538 0         0 return $val->[0]; # Has parameters, return just value
539             } else {
540 555         1336 return $val;
541             }
542             }
543             sub define {
544 8548     8548 1 8741 my $self = shift;
545 8548 50       10975 if (@_) {
546 8548         8366 my $token = shift;
547 8548         7976 my $value = shift;
548 8548         7459 my $params = shift;
549 8548         7506 my $cmdline = shift;
550 8548 100 50     10611 print "Define $token ".($params||'')."= $value\n" if $Debug;
551 8548         9838 my $oldval = $self->{defines}{$token};
552 8548         7313 my $oldparams;
553 8548 100       11234 if (ref $oldval eq 'ARRAY') {
554 415         356 ($oldval, $oldparams) = @{$oldval};
  415         630  
555             }
556 8548 50 66     11669 if (defined $oldval
      100        
      66        
557             && (($oldval ne $value)
558             || (($oldparams||'') ne ($params||'')))
559             && $self->{define_warnings}) {
560 1 50 33     3 warn "%Warning: ".$self->fileline().": Redefining `$token"
561             # Don't make errors too long or have strange chars
562             .((length($oldval)<40 && $oldval =~ /^[^\n\r\f]$/
563             && length($value)<40 && $value =~ /^[^\n\r\f]$/)
564             ? "to '$value', was '$oldval'\n" : "\n");
565             }
566 8548 100 100     17231 if ($params || $cmdline) {
567 7985         22014 $self->{defines}{$token} = [$value, $params, $cmdline];
568             } else {
569 563         5125 $self->{defines}{$token} = $value;
570             }
571             }
572             }
573             sub undef {
574 140     140 1 143 my $self = shift;
575 140         133 my $token = shift;
576 140         162 my $oldval = $self->{defines}{$token};
577             # We no longer warn about undefing something that doesn't exist, as other compilers don't
578             #(defined $oldval or !$self->{define_warnings})
579             # or carp "%Warning: ".$self->fileline().": No definition to undef for $token,";
580 140         1197 delete $self->{defines}{$token};
581             }
582              
583             sub undefineall {
584 19     19 1 19 my $self = shift;
585 19         24 foreach my $def (keys %{$self->{defines}}) {
  19         149  
586 1186 100       1282 if (!$self->defcmdline($def)) {
587 876         1505 delete $self->{defines}{$def};
588             }
589             }
590             }
591              
592             sub remove_defines {
593 0     0 1   my $self = shift;
594 0           my $sym = shift;
595 0           my $val = "x";
596 0           while (defined $val) {
597 0 0         last if $sym eq $val;
598 0           (my $xsym = $sym) =~ s/^\`//;
599 0           $val = $self->defvalue_nowarn($xsym); #Undef if not found
600 0 0         $sym = $val if defined $val;
601             }
602 0           return $sym;
603             }
604              
605             ######################################################################
606             ### Package return
607             1;
608             __END__