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   264528 use strict;
  15         57  
  15         504  
9 15     15   70 use vars qw($VERSION $Debug %Skip_Basenames);
  15         22  
  15         808  
10 15     15   105 use Carp;
  15         23  
  15         813  
11 15     15   86 use IO::File;
  15         33  
  15         1935  
12 15     15   102 use File::Basename;
  15         25  
  15         1585  
13 15     15   109 use File::Spec;
  15         30  
  15         378  
14 15     15   89 use Cwd;
  15         58  
  15         66845  
15              
16             ######################################################################
17             #### Configuration Section
18              
19             $VERSION = '3.478';
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 95010 @_ >= 1 or croak 'usage: Verilog::Getopt->new ({options})';
38 752         1163 my $class = shift; # Class (Getopt Element)
39 752   50     1590 $class ||= "Verilog::Getopt";
40              
41 752         7717 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         1509 bless $self, $class;
57 752         4022 return $self;
58             }
59              
60             #######################################################################
61             # Option parsing
62              
63             sub _filedir {
64 3     3   4 my $self = shift;
65 3         4 my $path = shift;
66 3 50       22 $path =~ s![/\\][^/\\]*$!! # ~~== my @dirs = File::Spec->splitdir( $path );
67             or $path = ".";
68 3 50       10 return "." if $path eq '';
69 3         7 return $path
70             }
71              
72             sub parameter_file {
73 6     6 0 8 my $self = shift;
74 6         8 my $filename = shift;
75 6         6 my $relative = shift;
76              
77 6 50       59 print "*parameter_file $filename\n" if $Debug;
78 6         14 my $optdir = ".";
79 6 100       14 if ($relative) { $optdir = $self->_filedir($filename); }
  3         14  
80              
81 6 50       42 my $fh = IO::File->new("<$filename") or die "%Error: ".$self->fileline().": $! $filename\n";
82 6         510 my $hold_fileline = $self->fileline();
83 6         176 while (my $line = $fh->getline()) {
84 24         668 chomp $line;
85 24         51 $line =~ s/(?:^|\s)\/\/.*$//;
86 24 100       263 next if $line =~ /^\s*$/;
87 12         57 $self->fileline("$filename:$.");
88 12         50 my @p = (split /\s+/,"$line ");
89 12         29 $self->_parameter_parse($optdir, @p);
90             }
91 6         258 $fh->close();
92 6         102 $self->fileline($hold_fileline);
93             }
94              
95             sub parameter {
96 21     21 1 101 my $self = shift;
97             # Parse VCS like parameters, and perform standard setup based on it
98             # Return list of leftover parameters
99 21         33 @{$self->{unparsed}} = ();
  21         68  
100 21         79 $self->_parameter_parse('.', @_);
101 21         44 return @{$self->{unparsed}};
  21         70  
102             }
103              
104             sub _parameter_parse {
105 33     33   56 my $self = shift;
106 33         49 my $optdir = shift;
107             # Internal: Parse list of VCS like parameters, and perform standard setup based on it
108 33         71 foreach my $oparam (@_) {
109 129         224 my $param = "$oparam"; # Must quote to convert Getopt to string, bug298
110 129 50       448 next if ($param =~ /^\s*$/);
111 129 100       996 print " parameter($param)\n" if $Debug;
112              
113             ### GCC & VCS style
114 129 100 100     1778 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         16 $self->{_parameter_next} = $param;
117             }
118              
119             ### VCS style
120             elsif (($param eq '-v'
121             || $param eq '-y') && $self->{vcs_style}) {
122 22         53 $self->{_parameter_next} = $param;
123             }
124             elsif ($param =~ /^\+libext\+(.*)$/ && $self->{vcs_style}) {
125 3         8 my $ext = $1;
126 3         11 foreach (split /\+/, $ext) {
127 4         9 $self->libext($_);
128             }
129             }
130             elsif ($param =~ /^\+incdir\+(.*)$/ && $self->{vcs_style}) {
131 21         82 $self->incdir($self->_parse_file_arg($optdir, $1));
132             }
133             elsif ($param =~ /^\+define\+(.*)$/ && $self->{vcs_style}) {
134 21         80 foreach my $tok (split("\\+", $1)) {
135 23         98 my ($a, $b) = $tok =~ m/^([^=]*)=?(.*)$/;
136 23         67 $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         53 my $pn = $self->{_parameter_next};
158 28         46 $self->{_parameter_next} = undef;
159 28 100       117 if ($pn eq '-F') {
    100          
    100          
    50          
160 3         8 $self->parameter_file($self->_parse_file_arg($optdir,$param), 1);
161             }
162             elsif ($pn eq '-f') {
163 3         17 $self->parameter_file($self->_parse_file_arg($optdir,$param), 0);
164             }
165             elsif ($pn eq '-v') {
166 3         7 $self->library($self->_parse_file_arg($optdir,$param));
167             }
168             elsif ($pn eq '-y') {
169 19         46 $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     52 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         174  
191             }
192             }
193             }
194             }
195              
196             sub _parse_file_arg {
197 51     51   74 my $self = shift;
198 51         68 my $optdir = shift;
199 51         94 my $relfilename = shift;
200             # Parse filename on option line, expanding relative paths in -F's
201 51         120 my $filename = $self->file_substitute($relfilename);
202 51 100 66     166 if ($optdir ne "." && ! File::Spec->file_name_is_absolute($filename)) {
203 2         31 $filename = File::Spec->catfile($optdir,$filename);
204             }
205 51         139 return $filename;
206             }
207              
208             #######################################################################
209             # Accessors
210              
211             sub fileline {
212 8544     8544 0 11597 my $self = shift;
213 8544 100       14254 if (@_) { $self->{fileline} = shift; }
  8537         11286  
214 8544         11607 return ($self->{fileline});
215             }
216             sub incdir {
217 108     108 1 412 my $self = shift;
218 108 100       295 if (@_) {
219 50         84 my $token = shift;
220 50 100       153 print "incdir $token\n" if $Debug;
221 50 100 66     148 if (ref($token) && ref($token) eq 'ARRAY') {
222 1         2 @{$self->{incdir}} = @{$token};
  1         3  
  1         3  
223             } else {
224 49         58 push @{$self->{incdir}}, $self->file_abs($token);
  49         205  
225             }
226 50         122 $self->file_path_cache_flush();
227             }
228 108 100       226 return (wantarray ? @{$self->{incdir}} : $self->{incdir});
  58         230  
229             }
230             sub libext {
231 7     7 1 9 my $self = shift;
232 7 100       14 if (@_) {
233 4         6 my $token = shift;
234 4 50       34 print "libext $token\n" if $Debug;
235 4 50 33     22 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         11  
239             }
240 4         10 $self->file_path_cache_flush();
241             }
242 7 100       27 return (wantarray ? @{$self->{libext}} : $self->{libext});
  3         8  
243             }
244             sub library {
245 12     12 1 18 my $self = shift;
246 12 100       34 if (@_) {
247 3         3 my $token = shift;
248 3 50       28 print "library $token\n" if $Debug;
249 3 50 33     19 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         8  
253             }
254             }
255 12 100       44 return (wantarray ? @{$self->{library}} : $self->{library});
  9         29  
256             }
257             sub module_dir {
258 134     134 1 231 my $self = shift;
259 134 100       262 if (@_) {
260 46         59 my $token = shift;
261 46 100       161 print "module_dir $token\n" if $Debug;
262 46 100 66     120 if (ref($token) && ref($token) eq 'ARRAY') {
263 1         2 @{$self->{module_dir}} = @{$token};
  1         3  
  1         2  
264             } else {
265 45         55 push @{$self->{module_dir}}, $self->file_abs($token);
  45         97  
266             }
267 46         95 $self->file_path_cache_flush();
268             }
269 134 100       380 return (wantarray ? @{$self->{module_dir}} : $self->{module_dir});
  88         255  
270             }
271             sub depend_files {
272 563     563 1 1014 my $self = shift;
273 563 50       1434 if (@_) {
274             #@_ may be Getopt::Long::Parameters which aren't arrays, will stringify
275 563 50 33     1794 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         1286 foreach my $fn (@_) {
282 563 100       1149 print "depend_files $fn\n" if $Debug;
283 563         1669 $self->{depend_files}{$fn} = 1;
284             }
285             }
286             }
287 563         840 my @list = (sort (keys %{$self->{depend_files}}));
  563         3869  
288 563 50       2169 return (wantarray ? @list : \@list);
289             }
290              
291             sub get_parameters {
292 3     3 1 401 my $self = shift;
293 3         8 my %args = (gcc_stlyle => $self->{gcc_style},);
294             # Defines
295 3         6 my @params = ();
296 3         15 foreach my $def ($self->define_names_sorted) {
297 13         22 my $defvalue = $self->defvalue($def);
298 13 100 50     52 $defvalue = "=".($defvalue||"") if (defined $defvalue && $defvalue ne "");
      66        
299 13 50       21 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         6 my $exts="";
307 3         8 foreach my $ext ($self->libext()) {
308 5 100       10 $exts = "+libext" if !$exts;
309 5         8 $exts .= "+$ext";
310             }
311 3 50       9 push @params, $exts if $exts;
312             # Includes...
313 3         7 foreach my $dir ($self->incdir()) {
314 7 50       13 if ($args{gcc_style}) {
315 0         0 push @params, "-I${dir}";
316             } else {
317 7         12 push @params, "+incdir+${dir}";
318             }
319             }
320 3         7 foreach my $dir ($self->module_dir()) {
321 9         24 push @params, "-y", $dir;
322             }
323 3         7 foreach my $dir ($self->library()) {
324 2         4 push @params, "-v", $dir;
325             }
326 3         19 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 76 my $self = shift;
341 33 50       86 if (@_) {
342 33         46 my $from_filename = shift;
343 33         49 my $inc_filename = shift;
344 33         129 $self->{includes}{$from_filename}{$inc_filename} = 1;
345             }
346 33         67 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 300 my $self = shift;
363 3         4 my $filename = shift;
364 3         13 $filename =~ s!.*[/\\]!!;
365 3         12 return $Skip_Basenames{$filename};
366             }
367              
368             sub file_abs {
369 97     97 1 120 my $self = shift;
370 97         118 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         212 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 716 my $self = shift;
387 370         413 my $filename = shift;
388 370         396 my $out = $filename;
389 370         935 while ($filename =~ /\$([A-Za-z_0-9]+)\b/g) {
390 9         33 my $var = $1;
391 9 100       89 $out =~ s/\$$var\b/$ENV{$var}/g if defined $ENV{$var};
392             }
393 370         635 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         512 $out =~ s!^~!$ENV{HOME}/!;
398 370         798 return $out;
399             }
400              
401             sub file_path_cache_flush {
402 100     100 0 124 my $self = shift;
403             # Clear out a file_path cache, needed if the incdir/module_dirs change
404 100         211 $self->{_file_path_cache} = {};
405             }
406              
407             sub file_path {
408 601     601 1 842 my $self = shift;
409 601         764 my $filename = shift;
410 601   100     2223 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       1500 defined $filename or carp "%Error: Undefined filename,";
415 601 100       1653 return $self->{_file_path_cache}{$filename} if defined $self->{_file_path_cache}{$filename};
416 576 100 66     21862 if (-r $filename && !-d $filename) {
417 492         2548 $self->{_file_path_cache}{$filename} = $filename;
418 492         2159 $self->depend_files($filename);
419 492         1809 return $filename;
420             }
421             # Try expanding environment
422 84         1164 $filename = $self->file_substitute($filename);
423 84 50 33     758 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         184 my @dirlist;
431 84 100       228 if ($lookup_type eq 'module') {
    50          
432 30         105 @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         163 @dirlist = ($self->incdir(), $self->module_dir());
438             }
439             # Expand any envvars in incdir/moduledir
440 84         185 @dirlist = map {$self->file_substitute($_)} @dirlist;
  234         341  
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         136 my %checked_dir = ();
446 84         118 my %checked_file = ();
447 84         153 foreach my $dir (@dirlist) {
448 168 100       359 next if $checked_dir{$dir}; $checked_dir{$dir}=1; # -r can be quite slow
  165         316  
449             # Check each postfix added to the file
450 165         201 foreach my $postfix ("", @{$self->{libext}}) {
  165         310  
451 283         722 my $found = "$dir/$filename$postfix";
452 283 50       523 next if $checked_file{$found}; $checked_file{$found}=1; # -r can be quite slow
  283         513  
453 283 100 66     4445 if (-r $found && !-d $found) {
454 71         314 $self->{_file_path_cache}{$filename} = $found;
455 71         226 $self->depend_files($found);
456 71         420 return $found;
457             }
458             }
459             }
460              
461 13         78 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 610 my $self = shift;
477 1         3 my $func = shift;
478             # Execute map function on all directories listed in self.
479             {
480 1         3 my @newdir = $self->incdir();
481 1         3 @newdir = map {&{$func}} @newdir;
  3         13  
  3         6  
482 1         7 $self->incdir(\@newdir);
483             }
484             {
485 1         1 my @newdir = $self->module_dir();
  1         3  
  1         3  
486 1         2 @newdir = map {&{$func}} @newdir;
  4         16  
  4         7  
487 1         6 $self->module_dir(\@newdir);
488             }
489             }
490              
491             #######################################################################
492             # Getopt functions
493              
494             sub define_names_sorted {
495 3     3 1 5 my $self = shift;
496 3         5 return (sort (keys %{$self->{defines}}));
  3         22  
497             }
498              
499             sub defcmdline {
500 1186     1186 0 1205 my $self = shift;
501 1186         1168 my $token = shift;
502 1186         1381 my $val = $self->{defines}{$token};
503 1186 100       1502 if (ref $val) {
504 702         1361 return $val->[2];
505             } else {
506 484         783 return undef;
507             }
508             }
509              
510             sub defparams {
511 2529     2529 1 2804 my $self = shift;
512 2529         3004 my $token = shift;
513 2529         3712 my $val = $self->{defines}{$token};
514 2529 100 100     7426 if (!defined $val) {
    100          
515 606         1367 return undef;
516             } elsif (ref $val && defined $val->[1]) {
517 828         2110 return $val->[1]; # Has parameters hash, return param list or undef
518             } else {
519 1095         2305 return 0;
520             }
521             }
522             sub defvalue {
523 1730     1730 1 2571 my $self = shift;
524 1730         1849 my $token = shift;
525 1730         2283 my $val = $self->{defines}{$token};
526 1730 50       2718 (defined $val) or carp "%Warning: ".$self->fileline().": No definition for $token,";
527 1730 100       2637 if (ref $val) {
528 926         14570 return $val->[0]; # Has parameters, return just value
529             } else {
530 804         6213 return $val;
531             }
532             }
533             sub defvalue_nowarn {
534 555     555 1 890 my $self = shift;
535 555         789 my $token = shift;
536 555         1071 my $val = $self->{defines}{$token};
537 555 50       1188 if (ref $val) {
538 0         0 return $val->[0]; # Has parameters, return just value
539             } else {
540 555         1591 return $val;
541             }
542             }
543             sub define {
544 8548     8548 1 10287 my $self = shift;
545 8548 50       12569 if (@_) {
546 8548         9806 my $token = shift;
547 8548         8784 my $value = shift;
548 8548         8924 my $params = shift;
549 8548         8437 my $cmdline = shift;
550 8548 100 50     12594 print "Define $token ".($params||'')."= $value\n" if $Debug;
551 8548         11223 my $oldval = $self->{defines}{$token};
552 8548         8247 my $oldparams;
553 8548 100       13203 if (ref $oldval eq 'ARRAY') {
554 415         419 ($oldval, $oldparams) = @{$oldval};
  415         758  
555             }
556 8548 50 66     13637 if (defined $oldval
      100        
      66        
557             && (($oldval ne $value)
558             || (($oldparams||'') ne ($params||'')))
559             && $self->{define_warnings}) {
560 1 50 33     4 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     20973 if ($params || $cmdline) {
567 7985         26808 $self->{defines}{$token} = [$value, $params, $cmdline];
568             } else {
569 563         5905 $self->{defines}{$token} = $value;
570             }
571             }
572             }
573             sub undef {
574 140     140 1 149 my $self = shift;
575 140         192 my $token = shift;
576 140         212 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         1493 delete $self->{defines}{$token};
581             }
582              
583             sub undefineall {
584 19     19 1 31 my $self = shift;
585 19         23 foreach my $def (keys %{$self->{defines}}) {
  19         182  
586 1186 100       1509 if (!$self->defcmdline($def)) {
587 876         1500 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__