File Coverage

blib/lib/Verilog/Getopt.pm
Criterion Covered Total %
statement 294 351 83.7
branch 120 168 71.4
condition 61 101 60.4
subroutine 35 39 89.7
pod 23 29 79.3
total 533 688 77.4


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   266449 use strict;
  15         53  
  15         504  
9 15     15   73 use vars qw($VERSION $Debug %Skip_Basenames);
  15         22  
  15         841  
10 15     15   86 use Carp;
  15         29  
  15         925  
11 15     15   97 use IO::File;
  15         24  
  15         1997  
12 15     15   102 use File::Basename;
  15         24  
  15         1530  
13 15     15   94 use File::Spec;
  15         34  
  15         354  
14 15     15   72 use Cwd;
  15         25  
  15         64516  
15              
16             ######################################################################
17             #### Configuration Section
18              
19             $VERSION = '3.476';
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 120745 @_ >= 1 or croak 'usage: Verilog::Getopt->new ({options})';
38 752         1170 my $class = shift; # Class (Getopt Element)
39 752   50     1419 $class ||= "Verilog::Getopt";
40              
41 752         7032 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         1679 bless $self, $class;
57 752         3616 return $self;
58             }
59              
60             #######################################################################
61             # Option parsing
62              
63             sub _filedir {
64 3     3   4 my $self = shift;
65 3         6 my $path = shift;
66 3 50       25 $path =~ s![/\\][^/\\]*$!! # ~~== my @dirs = File::Spec->splitdir( $path );
67             or $path = ".";
68 3 50       10 return "." if $path eq '';
69 3         8 return $path
70             }
71              
72             sub parameter_file {
73 6     6 0 9 my $self = shift;
74 6         19 my $filename = shift;
75 6         8 my $relative = shift;
76              
77 6 50       616 print "*parameter_file $filename\n" if $Debug;
78 6         32 my $optdir = ".";
79 6 100       15 if ($relative) { $optdir = $self->_filedir($filename); }
  3         16  
80              
81 6 50       42 my $fh = IO::File->new("<$filename") or die "%Error: ".$self->fileline().": $! $filename\n";
82 6         521 my $hold_fileline = $self->fileline();
83 6         160 while (my $line = $fh->getline()) {
84 24         703 chomp $line;
85 24         58 $line =~ s/(?:^|\s)\/\/.*$//;
86 24 100       294 next if $line =~ /^\s*$/;
87 12         65 $self->fileline("$filename:$.");
88 12         50 my @p = (split /\s+/,"$line ");
89 12         31 $self->_parameter_parse($optdir, @p);
90             }
91 6         213 $fh->close();
92 6         101 $self->fileline($hold_fileline);
93             }
94              
95             sub parameter {
96 21     21 1 99 my $self = shift;
97             # Parse VCS like parameters, and perform standard setup based on it
98             # Return list of leftover parameters
99 21         34 @{$self->{unparsed}} = ();
  21         67  
100 21         70 $self->_parameter_parse('.', @_);
101 21         48 return @{$self->{unparsed}};
  21         68  
102             }
103              
104             sub _parameter_parse {
105 33     33   48 my $self = shift;
106 33         51 my $optdir = shift;
107             # Internal: Parse list of VCS like parameters, and perform standard setup based on it
108 33         68 foreach my $oparam (@_) {
109 129         241 my $param = "$oparam"; # Must quote to convert Getopt to string, bug298
110 129 50       507 next if ($param =~ /^\s*$/);
111 129 100       9039 print " parameter($param)\n" if $Debug;
112              
113             ### GCC & VCS style
114 129 100 100     2098 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         19 $self->{_parameter_next} = $param;
117             }
118              
119             ### VCS style
120             elsif (($param eq '-v'
121             || $param eq '-y') && $self->{vcs_style}) {
122 22         64 $self->{_parameter_next} = $param;
123             }
124             elsif ($param =~ /^\+libext\+(.*)$/ && $self->{vcs_style}) {
125 3         9 my $ext = $1;
126 3         10 foreach (split /\+/, $ext) {
127 4         10 $self->libext($_);
128             }
129             }
130             elsif ($param =~ /^\+incdir\+(.*)$/ && $self->{vcs_style}) {
131 21         79 $self->incdir($self->_parse_file_arg($optdir, $1));
132             }
133             elsif ($param =~ /^\+define\+(.*)$/ && $self->{vcs_style}) {
134 21         89 foreach my $tok (split("\\+", $1)) {
135 23         112 my ($a, $b) = $tok =~ m/^([^=]*)=?(.*)$/;
136 23         63 $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         19 $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         7 $self->incdir($self->_parse_file_arg($optdir, $1));
153             }
154              
155             # Second parameters
156             elsif ($self->{_parameter_next}) {
157 28         57 my $pn = $self->{_parameter_next};
158 28         50 $self->{_parameter_next} = undef;
159 28 100       119 if ($pn eq '-F') {
    100          
    100          
    50          
160 3         10 $self->parameter_file($self->_parse_file_arg($optdir,$param), 1);
161             }
162             elsif ($pn eq '-f') {
163 3         10 $self->parameter_file($self->_parse_file_arg($optdir,$param), 0);
164             }
165             elsif ($pn eq '-v') {
166 3         9 $self->library($self->_parse_file_arg($optdir,$param));
167             }
168             elsif ($pn eq '-y') {
169 19         57 $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     54 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         21 push @{$self->{unparsed}}, "$param";
  20         195  
191             }
192             }
193             }
194             }
195              
196             sub _parse_file_arg {
197 51     51   69 my $self = shift;
198 51         70 my $optdir = shift;
199 51         84 my $relfilename = shift;
200             # Parse filename on option line, expanding relative paths in -F's
201 51         106 my $filename = $self->file_substitute($relfilename);
202 51 100 66     193 if ($optdir ne "." && ! File::Spec->file_name_is_absolute($filename)) {
203 2         31 $filename = File::Spec->catfile($optdir,$filename);
204             }
205 51         143 return $filename;
206             }
207              
208             #######################################################################
209             # Accessors
210              
211             sub fileline {
212 8544     8544 0 9593 my $self = shift;
213 8544 100       14067 if (@_) { $self->{fileline} = shift; }
  8537         11049  
214 8544         11851 return ($self->{fileline});
215             }
216             sub incdir {
217 108     108 1 536 my $self = shift;
218 108 100       225 if (@_) {
219 50         73 my $token = shift;
220 50 100       906 print "incdir $token\n" if $Debug;
221 50 100 66     178 if (ref($token) && ref($token) eq 'ARRAY') {
222 1         2 @{$self->{incdir}} = @{$token};
  1         4  
  1         4  
223             } else {
224 49         65 push @{$self->{incdir}}, $self->file_abs($token);
  49         203  
225             }
226 50         132 $self->file_path_cache_flush();
227             }
228 108 100       333 return (wantarray ? @{$self->{incdir}} : $self->{incdir});
  58         251  
229             }
230             sub libext {
231 7     7 1 10 my $self = shift;
232 7 100       13 if (@_) {
233 4         5 my $token = shift;
234 4 50       465 print "libext $token\n" if $Debug;
235 4 50 33     23 if (ref($token) && ref($token) eq 'ARRAY') {
236 0         0 @{$self->{libext}} = @{$token};
  0         0  
  0         0  
237             } else {
238 4         5 push @{$self->{libext}}, $token;
  4         14  
239             }
240 4         13 $self->file_path_cache_flush();
241             }
242 7 100       23 return (wantarray ? @{$self->{libext}} : $self->{libext});
  3         7  
243             }
244             sub library {
245 12     12 1 22 my $self = shift;
246 12 100       42 if (@_) {
247 3         5 my $token = shift;
248 3 50       312 print "library $token\n" if $Debug;
249 3 50 33     16 if (ref($token) && ref($token) eq 'ARRAY') {
250 0         0 @{$self->{library}} = @{$token};
  0         0  
  0         0  
251             } else {
252 3         5 push @{$self->{library}}, $self->file_abs($token);
  3         11  
253             }
254             }
255 12 100       39 return (wantarray ? @{$self->{library}} : $self->{library});
  9         29  
256             }
257             sub module_dir {
258 134     134 1 261 my $self = shift;
259 134 100       278 if (@_) {
260 46         75 my $token = shift;
261 46 100       1201 print "module_dir $token\n" if $Debug;
262 46 100 66     172 if (ref($token) && ref($token) eq 'ARRAY') {
263 1         2 @{$self->{module_dir}} = @{$token};
  1         4  
  1         3  
264             } else {
265 45         58 push @{$self->{module_dir}}, $self->file_abs($token);
  45         107  
266             }
267 46         92 $self->file_path_cache_flush();
268             }
269 134 100       393 return (wantarray ? @{$self->{module_dir}} : $self->{module_dir});
  88         267  
270             }
271             sub depend_files {
272 563     563 1 1012 my $self = shift;
273 563 50       1290 if (@_) {
274             #@_ may be Getopt::Long::Parameters which aren't arrays, will stringify
275 563 50 33     1572 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         1223 foreach my $fn (@_) {
282 563 100       1183 print "depend_files $fn\n" if $Debug;
283 563         1477 $self->{depend_files}{$fn} = 1;
284             }
285             }
286             }
287 563         844 my @list = (sort (keys %{$self->{depend_files}}));
  563         3420  
288 563 50       2072 return (wantarray ? @list : \@list);
289             }
290              
291             sub get_parameters {
292 3     3 1 670 my $self = shift;
293 3         10 my %args = (gcc_stlyle => $self->{gcc_style},);
294             # Defines
295 3         5 my @params = ();
296 3         7 foreach my $def ($self->define_names_sorted) {
297 13         22 my $defvalue = $self->defvalue($def);
298 13 100 50     61 $defvalue = "=".($defvalue||"") if (defined $defvalue && $defvalue ne "");
      66        
299 13 50       22 if ($args{gcc_style}) {
300 0         0 push @params, "-D${def}${defvalue}";
301             } else {
302 13         27 push @params, "+define+${def}${defvalue}";
303             }
304             }
305             # Put all libexts on one line, else NC-Verilog will bitch
306 3         7 my $exts="";
307 3         6 foreach my $ext ($self->libext()) {
308 5 100       9 $exts = "+libext" if !$exts;
309 5         9 $exts .= "+$ext";
310             }
311 3 50       7 push @params, $exts if $exts;
312             # Includes...
313 3         7 foreach my $dir ($self->incdir()) {
314 7 50       11 if ($args{gcc_style}) {
315 0         0 push @params, "-I${dir}";
316             } else {
317 7         13 push @params, "+incdir+${dir}";
318             }
319             }
320 3         8 foreach my $dir ($self->module_dir()) {
321 9         15 push @params, "-y", $dir;
322             }
323 3         6 foreach my $dir ($self->library()) {
324 2         4 push @params, "-v", $dir;
325             }
326 3         18 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 68 my $self = shift;
341 33 50       79 if (@_) {
342 33         52 my $from_filename = shift;
343 33         46 my $inc_filename = shift;
344 33         124 $self->{includes}{$from_filename}{$inc_filename} = 1;
345             }
346 33         72 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 405 my $self = shift;
363 3         5 my $filename = shift;
364 3         13 $filename =~ s!.*[/\\]!!;
365 3         13 return $Skip_Basenames{$filename};
366             }
367              
368             sub file_abs {
369 97     97 1 134 my $self = shift;
370 97         150 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         237 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 854 my $self = shift;
387 370         448 my $filename = shift;
388 370         390 my $out = $filename;
389 370   66     1377 while ($filename =~ /\$([A-Za-z_0-9]+)\b/g
390             || $filename =~ /\$\{[A-Za-z_0-9]+\}\b/g) {
391 9         33 my $var = $1;
392 9 100       26 if (defined $ENV{$var}) {
393 8         107 $out =~ s/\$$var\b/$ENV{$var}/g;
394             }
395             }
396 370         513 $out =~ s!^~!$ENV{HOME}/!;
397 370         768 return $out;
398             }
399              
400             sub file_path_cache_flush {
401 100     100 0 128 my $self = shift;
402             # Clear out a file_path cache, needed if the incdir/module_dirs change
403 100         239 $self->{_file_path_cache} = {};
404             }
405              
406             sub file_path {
407 601     601 1 812 my $self = shift;
408 601         899 my $filename = shift;
409 601   100     1947 my $lookup_type = shift || 'all';
410             # return path to given filename using library directories & files, or undef
411             # locations are cached, because -r can be a very slow operation
412              
413 601 50       1289 defined $filename or carp "%Error: Undefined filename,";
414 601 100       1500 return $self->{_file_path_cache}{$filename} if defined $self->{_file_path_cache}{$filename};
415 576 100 66     20031 if (-r $filename && !-d $filename) {
416 492         2482 $self->{_file_path_cache}{$filename} = $filename;
417 492         1772 $self->depend_files($filename);
418 492         1848 return $filename;
419             }
420             # Try expanding environment
421 84         408 $filename = $self->file_substitute($filename);
422 84 50 33     1554 if (-r $filename && !-d $filename) {
423 0         0 $self->{_file_path_cache}{$filename} = $filename;
424 0         0 $self->depend_files($filename);
425 0         0 return $filename;
426             }
427              
428             # What paths to use?
429 84         176 my @dirlist;
430 84 100       259 if ($lookup_type eq 'module') {
    50          
431 30         108 @dirlist = $self->module_dir();
432             } elsif ($lookup_type eq 'include') {
433 0         0 @dirlist = $self->incdir();
434             } else { # all
435             # Might be more obvious if -y had priority, but we'll remain back compatible
436 54         154 @dirlist = ($self->incdir(), $self->module_dir());
437             }
438             # Expand any envvars in incdir/moduledir
439 84         184 @dirlist = map {$self->file_substitute($_)} @dirlist;
  234         349  
440              
441             # Check each search path
442             # We use both the incdir and moduledir. This isn't strictly correct,
443             # but it's fairly silly to have to specify both all of the time.
444 84         128 my %checked_dir = ();
445 84         111 my %checked_file = ();
446 84         151 foreach my $dir (@dirlist) {
447 168 100       364 next if $checked_dir{$dir}; $checked_dir{$dir}=1; # -r can be quite slow
  165         305  
448             # Check each postfix added to the file
449 165         181 foreach my $postfix ("", @{$self->{libext}}) {
  165         300  
450 283         667 my $found = "$dir/$filename$postfix";
451 283 50       482 next if $checked_file{$found}; $checked_file{$found}=1; # -r can be quite slow
  283         472  
452 283 100 66     4138 if (-r $found && !-d $found) {
453 71         286 $self->{_file_path_cache}{$filename} = $found;
454 71         196 $self->depend_files($found);
455 71         395 return $found;
456             }
457             }
458             }
459              
460 13         74 return $filename; # Let whoever needs it discover it doesn't exist
461             }
462              
463             sub libext_matches {
464 0     0 1 0 my $self = shift;
465 0         0 my $filename = shift;
466 0 0       0 return undef if !$filename;
467 0         0 foreach my $postfix (@{$self->{libext}}) {
  0         0  
468 0         0 my $re = quotemeta($postfix) . "\$";
469 0 0       0 return $filename if ($filename =~ /$re/);
470             }
471 0         0 return undef;
472             }
473              
474             sub map_directories {
475 1     1 0 707 my $self = shift;
476 1         3 my $func = shift;
477             # Execute map function on all directories listed in self.
478             {
479 1         3 my @newdir = $self->incdir();
480 1         3 @newdir = map {&{$func}} @newdir;
  3         13  
  3         6  
481 1         9 $self->incdir(\@newdir);
482             }
483             {
484 1         2 my @newdir = $self->module_dir();
  1         2  
  1         4  
485 1         3 @newdir = map {&{$func}} @newdir;
  4         16  
  4         7  
486 1         7 $self->module_dir(\@newdir);
487             }
488             }
489              
490             #######################################################################
491             # Getopt functions
492              
493             sub define_names_sorted {
494 3     3 1 4 my $self = shift;
495 3         5 return (sort (keys %{$self->{defines}}));
  3         19  
496             }
497              
498             sub defcmdline {
499 1186     1186 0 1172 my $self = shift;
500 1186         1130 my $token = shift;
501 1186         1333 my $val = $self->{defines}{$token};
502 1186 100       1506 if (ref $val) {
503 702         1382 return $val->[2];
504             } else {
505 484         763 return undef;
506             }
507             }
508              
509             sub defparams {
510 2529     2529 1 2865 my $self = shift;
511 2529         2950 my $token = shift;
512 2529         3722 my $val = $self->{defines}{$token};
513 2529 100 100     7481 if (!defined $val) {
    100          
514 606         1359 return undef;
515             } elsif (ref $val && defined $val->[1]) {
516 828         2173 return $val->[1]; # Has parameters hash, return param list or undef
517             } else {
518 1095         2344 return 0;
519             }
520             }
521             sub defvalue {
522 1730     1730 1 2750 my $self = shift;
523 1730         1973 my $token = shift;
524 1730         2263 my $val = $self->{defines}{$token};
525 1730 50       2719 (defined $val) or carp "%Warning: ".$self->fileline().": No definition for $token,";
526 1730 100       2652 if (ref $val) {
527 926         14555 return $val->[0]; # Has parameters, return just value
528             } else {
529 804         6389 return $val;
530             }
531             }
532             sub defvalue_nowarn {
533 555     555 1 766 my $self = shift;
534 555         700 my $token = shift;
535 555         965 my $val = $self->{defines}{$token};
536 555 50       1232 if (ref $val) {
537 0         0 return $val->[0]; # Has parameters, return just value
538             } else {
539 555         1337 return $val;
540             }
541             }
542             sub define {
543 8548     8548 1 9836 my $self = shift;
544 8548 50       12901 if (@_) {
545 8548         9419 my $token = shift;
546 8548         8849 my $value = shift;
547 8548         8851 my $params = shift;
548 8548         8613 my $cmdline = shift;
549 8548 100 50     14109 print "Define $token ".($params||'')."= $value\n" if $Debug;
550 8548         11239 my $oldval = $self->{defines}{$token};
551 8548         8021 my $oldparams;
552 8548 100       12685 if (ref $oldval eq 'ARRAY') {
553 415         400 ($oldval, $oldparams) = @{$oldval};
  415         706  
554             }
555 8548 50 66     13785 if (defined $oldval
      100        
      66        
556             && (($oldval ne $value)
557             || (($oldparams||'') ne ($params||'')))
558             && $self->{define_warnings}) {
559 1 50 33     4 warn "%Warning: ".$self->fileline().": Redefining `$token"
560             # Don't make errors too long or have strange chars
561             .((length($oldval)<40 && $oldval =~ /^[^\n\r\f]$/
562             && length($value)<40 && $value =~ /^[^\n\r\f]$/)
563             ? "to '$value', was '$oldval'\n" : "\n");
564             }
565 8548 100 100     21655 if ($params || $cmdline) {
566 7985         25802 $self->{defines}{$token} = [$value, $params, $cmdline];
567             } else {
568 563         5881 $self->{defines}{$token} = $value;
569             }
570             }
571             }
572             sub undef {
573 140     140 1 206 my $self = shift;
574 140         165 my $token = shift;
575 140         203 my $oldval = $self->{defines}{$token};
576             # We no longer warn about undefing something that doesn't exist, as other compilers don't
577             #(defined $oldval or !$self->{define_warnings})
578             # or carp "%Warning: ".$self->fileline().": No definition to undef for $token,";
579 140         1535 delete $self->{defines}{$token};
580             }
581              
582             sub undefineall {
583 19     19 1 36 my $self = shift;
584 19         20 foreach my $def (keys %{$self->{defines}}) {
  19         192  
585 1186 100       1516 if (!$self->defcmdline($def)) {
586 876         1444 delete $self->{defines}{$def};
587             }
588             }
589             }
590              
591             sub remove_defines {
592 0     0 1   my $self = shift;
593 0           my $sym = shift;
594 0           my $val = "x";
595 0           while (defined $val) {
596 0 0         last if $sym eq $val;
597 0           (my $xsym = $sym) =~ s/^\`//;
598 0           $val = $self->defvalue_nowarn($xsym); #Undef if not found
599 0 0         $sym = $val if defined $val;
600             }
601 0           return $sym;
602             }
603              
604             ######################################################################
605             ### Package return
606             1;
607             __END__