File Coverage

blib/lib/RPerl/Config.pm
Criterion Covered Total %
statement 564 644 87.5
branch 35 80 43.7
condition 15 45 33.3
subroutine 156 161 96.8
pod 0 11 0.0
total 770 941 81.8


line stmt bran cond sub pod time code
1             ## no critic qw(ProhibitUselessNoCritic PodSpelling ProhibitExcessMainComplexity) # DEVELOPER DEFAULT 1a: allow unreachable & POD-commented code, must be on line 1; SYSTEM SPECIAL 4: allow complex code outside subroutines, must be on line 1
2              
3             # NEED FIX: triplicate export code
4             package RPerl::Config;
5 7     7   43 use strict;
  7         13  
  7         186  
6 7     7   35 use warnings;
  7         13  
  7         318  
7             our $VERSION = 0.008_000;
8              
9             ## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls) # USER DEFAULT 1: allow numeric values & print operator
10             ## no critic qw(RequireInterpolationOfMetachars) # USER DEFAULT 2: allow single-quoted control characters & sigils
11             ## no critic qw(ProhibitUnreachableCode RequirePodSections RequirePodAtEnd) # DEVELOPER DEFAULT 1b: allow POD & unreachable or POD-commented code, must be after line 1
12             ## no critic qw(ProhibitStringyEval) # SYSTEM DEFAULT 1: allow eval()
13             ## no critic qw(ProhibitExplicitStdin) # USER DEFAULT 4: allow <STDIN> prompt
14             ## no critic qw(Capitalization ProhibitMultiplePackages ProhibitReusedNames) # SYSTEM DEFAULT 3: allow multiple & lower case package names
15             ## no critic qw(ProhibitAutomaticExportation) # SYSTEM SPECIAL 14: allow global exports from Config.pm
16              
17             # DEV NOTE: this package exists to serve as the header file for RPerl.pm itself,
18             # as well as for RPerl.pm dependencies such as Class.pm, HelperFunctions_cpp.pm, and rperltypes.pm
19              
20             # @ARG == @_, $OS_ERROR == $ERRNO == $!, $EVAL_ERROR == $@, $CHILD_ERROR == $?, $EXECUTABLE_NAME == $^X, $PROGRAM_NAME == $0, $OSNAME == $^O
21              
22             # export various subroutines and variables to all who call 'use RPerl::Config;'
23 7     7   2700 use Data::Dumper;
  7         42710  
  7         585  
24             $Data::Dumper::Sortkeys = 1; # Dumper() output must be sorted for lib/RPerl/Tests/Type_Types/* etc.
25 7     7   56 use Carp;
  7         15  
  7         455  
26 7     7   2091 use English qw(-no_match_vars);
  7         19050  
  7         50  
27 7     7   4668 use POSIX qw(ceil floor modf);
  7         32731  
  7         50  
28 7     7   9073 use Exporter 'import';
  7         17  
  7         541  
29              
30             # DEV NOTE, CORRELATION #rp008: can't include to_string(), type(), types(), name(), or scope_type_name_value() in @EXPORT here or in RPerl:: namespace below
31             # DEV NOTE, CORRELATION #rp034: enable @ARG in all packages (class & non-class)
32             our @EXPORT = qw(Dumper carp croak confess *ARG $OS_ERROR $EVAL_ERROR $CHILD_ERROR $EXECUTABLE_NAME $PROGRAM_NAME $OSNAME);
33              
34             1; # end of package
35              
36             # NEED FIX: triplicate export code
37             package RPerl::AfterSubclass;
38              
39             ## no critic qw(ProhibitAutomaticExportation) # SYSTEM SPECIAL 14: allow global exports from Config.pm
40              
41             # export various subroutines and variables to all who call 'use RPerl::AfterSubclass;'
42 7     7   52 use Data::Dumper;
  7         17  
  7         378  
43             $Data::Dumper::Sortkeys = 1; # Dumper() output must be sorted for lib/RPerl/Tests/Type_Types/* etc.
44 7     7   41 use Carp;
  7         11  
  7         392  
45 7     7   43 use English qw(-no_match_vars);
  7         13  
  7         46  
46 7     7   2322 use POSIX qw(ceil floor modf);
  7         16  
  7         49  
47 7     7   528 use Exporter 'import';
  7         12  
  7         432  
48              
49             # DEV NOTE, CORRELATION #rp008: can't include to_string(), type(), types(), name(), or scope_type_name_value() in @EXPORT here or in RPerl:: namespace below
50             # DEV NOTE, CORRELATION #rp034: enable @ARG in all packages (class & non-class)
51             our @EXPORT = qw(Dumper carp croak confess *ARG $OS_ERROR $EVAL_ERROR $CHILD_ERROR $EXECUTABLE_NAME $PROGRAM_NAME $OSNAME);
52              
53             1; # end of package
54              
55             # NEED FIX: triplicate export code
56             package RPerl;
57 7     7   39 use File::Find qw(find);
  7         14  
  7         480  
58 7     7   43 use File::Spec;
  7         13  
  7         187  
59 7     7   3819 use IPC::Cmd qw(can_run); # to check for `reset`
  7         305080  
  7         656  
60              
61             ## no critic qw(ProhibitUselessNoCritic ProhibitMagicNumbers RequireCheckedSyscalls) # USER DEFAULT 1: allow numeric values & print operator
62             ## no critic qw(RequireInterpolationOfMetachars) # USER DEFAULT 2: allow single-quoted control characters & sigils
63             ## no critic qw(ProhibitUnreachableCode RequirePodSections RequirePodAtEnd) # DEVELOPER DEFAULT 1b: allow POD & unreachable or POD-commented code, must be after line 1
64             ## no critic qw(ProhibitStringyEval) # SYSTEM DEFAULT 1: allow eval()
65             ## no critic qw(ProhibitExplicitStdin) # USER DEFAULT 4: allow <STDIN> prompt
66             ## no critic qw(Capitalization ProhibitMultiplePackages ProhibitReusedNames) # SYSTEM DEFAULT 3: allow multiple & lower case package names
67             ## no critic qw(ProhibitAutomaticExportation) # SYSTEM SPECIAL 14: allow global exports from Config.pm
68              
69             # export $RPerl::MODES, as well as various subroutines and variables to all who call 'use RPerl;'
70             our $MODES = { # see perl_modes.txt for more info
71             0 => { ops => 'PERL', types => 'PERL' }, # NEED FIX: should be types => 'PERL_STATIC'
72             1 => { ops => 'CPP', types => 'PERL' }, # NEED FIX: should be types => 'PERL_STATIC'
73             2 => { ops => 'CPP', types => 'CPP' }
74             };
75              
76 7     7   78 use Data::Dumper;
  7         16  
  7         390  
77             $Data::Dumper::Sortkeys = 1; # Dumper() output must be sorted for lib/RPerl/Tests/Type_Types/* etc.
78 7     7   43 use Carp;
  7         19  
  7         377  
79 7     7   205 use English qw(-no_match_vars);
  7         15  
  7         62  
80 7     7   2603 use POSIX qw(ceil floor modf);
  7         19  
  7         50  
81 7     7   553 use Exporter 'import';
  7         14  
  7         871  
82             # DEV NOTE, CORRELATION #rp034: enable @ARG in all packages (class & non-class)
83             our @EXPORT = qw(Dumper carp croak confess *ARG $OS_ERROR $EVAL_ERROR $CHILD_ERROR $EXECUTABLE_NAME $PROGRAM_NAME $OSNAME);
84              
85             # [[[ OO CLASS PROPERTIES SPECIAL ]]]
86              
87             # data type checking mode, disabled in RPerl system code which calls 'use RPerl;',
88             # changed on a per-file basis by preprocessor directive, see RPerl::CompileUnit::Module::Class::INIT
89             # NEED UPGRADE: enable in RPerl system code when bootstrapping compiler
90             our $CHECK = 'OFF';
91             our $DEBUG = 0; # $RPerl::DEBUG & env var RPERL_DEBUG are equivalent, default to off, see debug*() & diag*() below
92             our $VERBOSE = 0; # $RPerl::VERBOSE & env var RPERL_VERBOSE are equivalent, default to off, see verbose*() below
93             our $WARNINGS = 1; # $RPerl::WARNINGS & env var RPERL_WARNINGS are equivalent, default to on, see warn*() below
94             our $TYPES_CCFLAG = ' -D__CPP__TYPES'; # rperltypes_mode.h & here default to CPPTYPES if PERLTYPES not explicitly set in this variable via rperltypes::types_enable()
95             our $BASE_PATH = undef; # all target software lives below here
96             our $INCLUDE_PATH = undef; # all target system modules live here
97             our $SCRIPT_PATH = undef; # interpreted target system programs live here
98             our $CORE_PATH = undef; # all Perl core components (perl.h, etc) live here
99              
100             # DEV NOTE, CORRELATION #rp032: NEED UPGRADE: properly determine whether to use DBL_EPSILON or FLT_EPSILON below
101 7     7   42 use constant EPSILON => POSIX::DBL_EPSILON();
  7         16  
  7         14166  
102             #use constant EPSILON => POSIX::FLT_EPSILON();
103              
104             # [[[ SUBROUTINES SPECIAL ]]]
105              
106             # use a possibly-compiled RPerl package during runtime
107             sub eval_use {
108 129     129 0 436 (my $package_name, my $display_errors) = @ARG;
109             # RPerl::debug('in RPerl::eval_use(), received $package_name = ', $package_name, "\n");
110              
111 129         283 my $INC_ref_pre = {};
112 129         66673 foreach my $INC_key_pre (keys %INC) { $INC_ref_pre->{$INC_key_pre} = 1; }
  98258         159516  
113             # RPerl::debug('in RPerl::eval_use(), have $INC_ref_pre = ', Dumper($INC_ref_pre), "\n");
114              
115 129         6004 my $eval_string .=<<"EOL";
116             use $package_name;
117             # detect compiled C++ code and call cpp_load() accordingly
118             if (defined \&$package_name\:\:cpp_load) {
119             # RPerl::debug('in RPerl::eval_use() eval, $package_name\:\:cpp_load() is defined, calling...', "\\n");
120             $package_name\:\:cpp_load();
121             # RPerl::debug('in RPerl::eval_use() eval, $package_name\:\:cpp_load() is defined, returned from call', "\\n");
122             }
123             # else {
124             # RPerl::debug('in RPerl::eval_use() eval, $package_name\:\:cpp_load() is NOT defined, skipping...', "\\n");
125             # }
126             EOL
127              
128             # RPerl::debug('in RPerl::eval_use(), have $eval_string = ', "\n\n", $eval_string, "\n\n");
129              
130 129         356 $eval_string .=<<'EOL';
131             my $INC_ref_post = {};
132             foreach my $INC_key_post (keys %INC) {
133             if (not exists $INC_ref_pre->{$INC_key_post}) {
134             $INC_ref_post->{$INC_key_post} = $INC{$INC_key_post};
135             }
136             }
137             # RPerl::debug('in RPerl::eval_use() eval, have $INC_ref_post = ', Dumper($INC_ref_post), "\n");
138             RPerl::CompileUnit::Module::Class::create_symtab_entries_and_accessors_mutators($INC_ref_post);
139             EOL
140              
141 129     1   12571 my $eval_retval = eval $eval_string;
  1     1   7  
  1     1   3  
  1     1   99  
  1     1   22  
  1     1   7  
  1     1   162  
  1     1   28  
  1     1   7  
  1     1   190  
  1     1   16  
  1     1   4  
  1     1   121  
  1     1   18  
  1     1   3  
  1     1   119  
  1     1   19  
  1     1   3  
  1     1   116  
  1     1   21  
  1     1   6  
  1     1   148  
  1     1   16  
  1     1   4  
  1     1   117  
  1     1   24  
  1     1   5  
  1     1   122  
  1     1   17  
  1     1   4  
  1     1   157  
  1     1   16  
  1     1   4  
  1     1   130  
  1     1   20  
  1     1   4  
  1     1   129  
  1     1   20  
  1     1   3  
  1     1   118  
  1     1   582  
  1     1   5  
  1     1   5  
  1     1   594  
  1     1   6  
  1     1   10  
  1     1   6  
  1     1   3  
  1     1   10  
  1     1   16  
  1     1   5  
  1     1   165  
  1     1   16  
  1     1   3  
  1     1   116  
  1     1   17  
  1     1   4  
  1     1   119  
  1     1   594  
  1     1   4  
  1     1   5  
  1     1   7  
  1     1   6  
  1     1   91  
  1     1   18  
  1     1   4  
  1     1   115  
  1     1   19  
  1     1   4  
  1     1   22  
  1     1   10  
  1     1   3  
  1     1   91  
  1     1   17  
  1     1   4  
  1     1   136  
  1     1   17  
  1     1   4  
  1     1   137  
  1     1   13  
  1     1   2  
  1     1   134  
  1     1   599  
  1     1   4  
  1     1   111  
  1     1   7  
  1     1   2  
  1     1   83  
  1     1   21  
  1     1   5  
  1     1   133  
  1     1   630  
  1     1   5  
  1     1   108  
  1     1   6  
  1     1   6  
  1     1   74  
  1     1   19  
  1     1   4  
  1     1   140  
  1     1   684  
  1     1   6  
  1     1   117  
  1     1   8  
  1     1   6  
  1     1   98  
  1     1   582  
  1     1   5  
  1     1   8  
  1     1   691  
  1     1   4  
  1     1   12  
  1     1   716  
  1     1   4  
  1     1   96  
  1     1   611  
  1     1   3  
  1     1   9  
  1     1   739  
  1     1   6  
  1     1   11  
  1     1   560  
  1     1   4  
  1     1   96  
  1     1   634  
  1     1   4  
  1     1   9  
  1     1   837  
  1     1   13  
  1         15  
  1         646  
  1         6  
  1         101  
  1         611  
  1         8  
  1         9  
  1         689  
  1         8  
  1         11  
  1         632  
  1         7  
  1         101  
  1         687  
  1         7  
  1         10  
  1         17  
  1         4  
  1         121  
  1         705  
  1         4  
  1         109  
  1         7  
  1         3  
  1         92  
  1         17  
  1         4  
  1         153  
  1         693  
  1         5  
  1         104  
  1         8  
  1         2  
  1         94  
  1         19  
  1         4  
  1         108  
  1         649  
  1         4  
  1         118  
  1         7  
  1         2  
  1         99  
  1         15  
  1         4  
  1         109  
  1         678  
  1         8  
  1         111  
  1         10  
  1         3  
  1         79  
  1         18  
  1         3  
  1         110  
  1         589  
  1         5  
  1         118  
  1         10  
  1         2  
  1         78  
  1         15  
  1         4  
  1         114  
  1         640  
  1         3  
  1         117  
  1         7  
  1         6  
  1         82  
  1         132  
  1         10  
  1         178  
  1         885  
  1         6  
  1         109  
  1         7  
  1         3  
  1         75  
  1         23  
  1         4  
  1         204  
  1         662  
  1         7  
  1         129  
  1         8  
  1         2  
  1         141  
  1         170  
  0         0  
  0         0  
  1         7  
  1         3  
  1         116  
  1         45  
  1         5  
  1         113  
  1         602  
  1         5  
  1         95  
  1         7  
  1         2  
  1         91  
  1         558  
  1         5  
  1         89  
  1         553  
  1         6  
  1         96  
  1         532  
  1         4  
  1         91  
  1         561  
  1         4  
  1         91  
  1         532  
  1         4  
  1         93  
  1         538  
  1         7  
  1         97  
  1         547  
  1         3  
  1         92  
  1         617  
  1         4  
  1         99  
  1         529  
  1         5  
  1         91  
  1         629  
  1         4  
  1         91  
  1         529  
  1         4  
  1         95  
  1         792  
  1         4  
  1         94  
  1         953  
  1         4  
  1         90  
  1         525  
  1         5  
  1         87  
  1         577  
  1         4  
  1         96  
  1         649  
  1         7  
  1         94  
  1         16  
  1         5  
  1         122  
  1         729  
  1         5  
  1         106  
  1         10  
  1         2  
  1         90  
  1         20  
  1         5  
  1         12  
  1         19  
  1         4  
  1         12  
  1         11  
  1         3  
  1         11  
  1         17  
  1         3  
  1         122  
  1         643  
  1         7  
  1         111  
  1         11  
  1         3  
  1         109  
  1         21  
  1         4  
  1         122  
  1         585  
  1         6  
  1         101  
  1         10  
  1         3  
  1         74  
  1         20  
  1         3  
  1         123  
  1         21  
  1         4  
  1         12  
  1         11  
  1         4  
  1         80  
  1         18  
  1         4  
  1         9  
  1         9  
  1         4  
  1         72  
  1         15  
  1         3  
  1         114  
  1         649  
  1         6  
  1         8  
  1         13  
  1         3  
  1         8  
  1         10  
  1         4  
  1         82  
  1         16  
  1         4  
  1         10  
  1         11  
  1         4  
  1         73  
  1         16  
  1         4  
  1         103  
  1         567  
  1         4  
  1         6  
  1         8  
  1         2  
  1         9  
  1         6  
  1         3  
  1         89  
  1         16  
  1         4  
  1         105  
  1         597  
  1         4  
  1         119  
  1         8  
  1         2  
  1         101  
  1         214  
  0         0  
  0         0  
  1         6  
  1         2  
  1         118  
  1         134  
  0         0  
  0         0  
  1         6  
  1         2  
  1         112  
  1         111  
  0         0  
  0         0  
  1         6  
  1         19  
  1         89  
142             # if (defined $eval_retval) { print 'have $eval_retval = ', $eval_retval, "\n"; }
143             # else { print 'have $eval_retval = undef, have $EVAL_ERROR = ', $EVAL_ERROR, "\n"; }
144 129 0 33     646 if ($display_errors and (defined $EVAL_ERROR) and ($EVAL_ERROR ne q{})) {
      33        
145 0         0 RPerl::warning( 'WARNING WCOEU00, EVAL USE: Failed to eval-use package ' . q{'}
146             . $package_name . q{'} . ', fatal error trapped and delayed' . "\n" );
147 0         0 RPerl::diag( ' Trapped the following error message...' . "\n\n" . $EVAL_ERROR . "\n" );
148 0         0 RPerl::warning("\n");
149             }
150              
151 129         530 return $eval_retval;
152             }
153              
154             # NEED UPGRADE: replace Data::Dumper with pure-RPerl equivalent?
155             #sub DUMPER {
156             # ( my $dumpee ) = @ARG;
157             # die ('in RPerl::DUMPER(), received undef argument, dying') if (not(defined($_[0])));
158             # return '**UNDEF**' if ( not( defined $dumpee ) );
159             # return $dumpee->DUMPER()
160             # if ( defined( eval( q{$} . ref($dumpee) . q{::DUMPER} ) ) );
161             # return Dumper($dumpee);
162             #}
163              
164             # DEV NOTE: to make diag*() & debug*() & verbose*() & warning() truly variadic, do not accept args as first line in subroutine
165              
166             # DEV NOTE: diag() is simply a wrapper around debug(), they are 100% equivalent; likewise diag_pause() and debug_pause()
167 105     105 0 294 sub diag { return debug(@ARG); }
168 0     0 0 0 sub diag_pause { return debug_pause(@ARG); }
169              
170             # print debugging AKA diagnostic message to STDERR, if either RPERL_DEBUG environmental variable or $RPerl::DEBUG global variable are true
171             sub debug {
172             # print {*STDERR} 'in debug(), have $ENV{RPERL_DEBUG} = ' . $ENV{RPERL_DEBUG} . "\n";
173              
174             # DEV NOTE, CORRELATION #rp017: default to off; if either variable is set to true, then do emit messages
175 105 50 33 105 0 608 if ( $ENV{RPERL_DEBUG} or $RPerl::DEBUG ) { print {*STDERR} @ARG; }
  0         0  
  0         0  
176              
177             # if ( $ENV{RPERL_DEBUG} or $RPerl::DEBUG ) { print {*STDERR} "\e[1;31m $message \e[0m"; } # print in red
178 105         1618 return 1; # DEV NOTE: this must be here to avoid 'at -e line 0. INIT failed--call queue aborted.'... BUT WHY???
179             }
180              
181             # same as debug(), except require <ENTER> to continue
182             sub debug_pause {
183 0 0 0 0 0 0 if ( $ENV{RPERL_DEBUG} or $RPerl::DEBUG ) {
184 0         0 print {*STDERR} @ARG;
  0         0  
185 0         0 my $stdin_ignore = <STDIN>;
186             }
187 0         0 return 1;
188             }
189              
190             # print verbose user-friendly message to STDOUT, if either RPERL_VERBOSE environmental variable or $RPerl::VERBOSE global variable are true
191             sub verbose {
192             # DEV NOTE, CORRELATION #rp017: default to off; if either variable is set to true, then do emit messages
193 12320 50 33 12320 0 95286 if ( $ENV{RPERL_VERBOSE} or $RPerl::VERBOSE ) {
194 0         0 print {*STDOUT} @ARG;
  0         0  
195             }
196 12320         2000077 return 1;
197             }
198              
199             # same as verbose(), except require <ENTER> to continue
200             sub verbose_pause {
201 0 0 0 0 0 0 if ( $ENV{RPERL_VERBOSE} or $RPerl::VERBOSE ) {
202 0         0 print {*STDOUT} @ARG;
  0         0  
203 0         0 my $stdin_ignore = <STDIN>;
204             }
205 0         0 return 1;
206             }
207              
208             # clear STDOUT, if either RPERL_VERBOSE environmental variable or $RPerl::VERBOSE global variable are true
209             sub verbose_clear_screen {
210 0 0 0 0 0 0 if ( $ENV{RPERL_VERBOSE} or $RPerl::VERBOSE ) {
211 0 0       0 if ( $OSNAME eq 'linux' ) {
    0          
212 0         0 my $reset_path = can_run('reset');
213 0 0       0 if ( defined $reset_path ) {
214 0         0 system $reset_path;
215             }
216             }
217             elsif ( $OSNAME eq 'MSWin32' ) {
218              
219             # cls is a shell builtin, not a command which can be found by can_run()
220 0         0 system 'cls';
221             }
222             else {
223 0         0 RPerl::warning(
224             q{WARNING WOSCLSC00: Unknown operating system '} . $OSNAME . q{' where 'linux' or 'Win32' expected, skipping screen clearing} . "\n" );
225 0         0 return 0;
226             }
227             }
228 0         0 return 1;
229             }
230              
231             # print non-fatal warning message to STDERR, unless either RPERL_WARNINGS environmental variable or $RPerl::WARNINGS global variable are false
232             sub warning {
233             # default to on; if either variable is set to false, then do not emit messages
234 56 0 33 56 0 133090 if ( ( ( not defined $ENV{RPERL_WARNINGS} ) or $ENV{RPERL_WARNINGS} )
      33        
235             and $RPerl::WARNINGS )
236             {
237             # NEED ADDRESS? the two following lines should be equivalent, but warn causes false ECOPAPL03
238 0         0 print {*STDERR} @ARG;
  0         0  
239              
240             # warn $message . "\n";
241             }
242 56         380 return 1;
243             }
244              
245             sub analyze_class_symtab_entries {
246 0     0 0 0 ( my $class ) = @ARG;
247 0         0 my $retval = q{};
248 0         0 my @isa_array = eval q{@} . $class . q{::ISA};
249              
250             #print Dumper(\@isa_array);
251 0         0 my $isa_string = join ', ', @isa_array;
252 0         0 $retval .= '<<<<< BEGIN SYMTAB ENTRIES >>>>>' . "\n";
253 0         0 $retval .= $class . ' ISA (' . $isa_string . ')' . "\n\n";
254              
255             #foreach my $entry ( sort keys %RPerl::CompileUnit::Module::Header:: ) {
256 0         0 my @keys = eval q{sort keys %} . $class . q{::};
257 0         0 foreach my $entry (@keys) {
258              
259             # my $glob = $RPerl::CompileUnit::Module::Header::{$entry};
260 0         0 my $glob = eval q{$} . $class . q{::{$entry}};
261              
262 0         0 $retval .= q{-} x 50;
263 0         0 $retval .= "\n";
264 0         0 $retval .= $entry . "\n";
265              
266             # $retval .= ref \$glob, "\n"; # always says GLOB
267              
268 0 0       0 if ( defined ${$glob} ) {
  0         0  
269 0         0 $retval .= "\t" . 'scalar';
270 0         0 my $ref_type = ref ${$glob};
  0         0  
271 0 0       0 if ( $ref_type ne q{} ) {
272 0         0 $retval .= "\t" . $ref_type . 'ref';
273             }
274             }
275 0 0       0 if ( @{$glob} ) {
  0         0  
276 0         0 $retval .= "\t" . 'array';
277             }
278 0 0       0 if ( %{$glob} ) {
  0         0  
279 0         0 $retval .= "\t" . 'hash';
280             }
281 0 0       0 if ( defined &{$glob} ) {
  0         0  
282 0         0 $retval .= "\t" . 'code';
283             }
284              
285 0         0 $retval .= "\n";
286             }
287 0         0 $retval .= '<<<<< END SYMTAB ENTRIES >>>>>' . "\n";
288 0         0 return $retval;
289             }
290              
291             # [ AUTOMATICALLY SET SYSTEM-DEPENDENT PATH VARIABLES ]
292             sub set_system_paths {
293 7     7 0 19 ( my $target_file_name_config, my $target_package_name_config, my $target_file_name_pm, my $target_file_name_script ) = @ARG;
294 7 50 33     86 if (( not exists $INC{$target_file_name_config} )
295             or ( not defined $INC{$target_file_name_config} )
296             )
297             {
298 0         0 Carp::croak 'BIZARRE ERROR EINPL00: Non-existent or undefined Perl %INC path entry for '
299             . $target_file_name_config
300             . ', reported from within '
301             . $target_package_name_config
302             . ', croaking';
303             }
304 7         22 my $target_config_pm_loaded = $INC{$target_file_name_config};
305 7 50       268 if ( not -e $target_config_pm_loaded ) {
306 0         0 Carp::croak 'BIZARRE ERROR EINPL01: Non-existent file ',
307             $target_config_pm_loaded,
308             ' supposedly loaded in %INC, reported from within ' . $target_package_name_config . ', croaking';
309             }
310 7         226 ( my $volume_loaded, my $directories_loaded, my $file_loaded ) = File::Spec->splitpath( $target_config_pm_loaded, my $no_file = 0 );
311 7         104 my @directories_loaded_split = File::Spec->splitdir($directories_loaded);
312              
313             #print {*STDERR} 'in ' . $target_package_name_config . ', have pre-pop @directories_loaded_split = ', "\n", Dumper(@directories_loaded_split), "\n";
314              
315             # pop twice if empty entry on top
316 7 50       29 if ( pop @directories_loaded_split eq q{} ) { pop @directories_loaded_split; }
  7         13  
317 7         188 my $target_pm_wanted = File::Spec->catpath( $volume_loaded, ( File::Spec->catdir(@directories_loaded_split) ), $target_file_name_pm );
318              
319             #print {*STDERR} 'in ' . $target_package_name_config . ', have post-pop @directories_loaded_split = ', "\n", Dumper(@directories_loaded_split), "\n";
320             #print {*STDERR} 'in ' . $target_package_name_config . ', have $target_config_pm_loaded = ', $target_config_pm_loaded, "\n";
321             #print {*STDERR} 'in ' . $target_package_name_config . ', have $target_pm_wanted = ', $target_pm_wanted, "\n";
322              
323 7         19 my $target_pm_loaded = undef;
324 7 50 33     43 if ( ( exists $INC{$target_file_name_pm} ) and ( defined $INC{$target_file_name_pm} ) ) {
325 0         0 $target_pm_loaded = $INC{$target_file_name_pm};
326              
327             # BULK88 20150608 2015.159: Win32 Bug Fix
328             # if ( not -e $target_pm_loaded ) {
329 0 0       0 if ( not -f $target_pm_loaded ) {
330 0         0 Carp::croak 'BIZARRE ERROR EINPL02: Non-existent file ', $target_pm_loaded,
331             ' supposedly loaded in %INC, reported from within ' . $target_package_name_config . ', croaking';
332             }
333             }
334              
335             # strip trailing '/'
336 7 50       26 if ( ( substr $directories_loaded, -1, 1 ) eq q{/} ) {
337 7         20 $directories_loaded = substr $directories_loaded, 0, -1;
338             }
339              
340             #print {*STDERR} 'in ' . $target_package_name_config . ', have $directories_loaded = ', $directories_loaded, "\n";
341             #print {*STDERR} 'in ' . $target_package_name_config . ', have $target_pm_loaded = ', ( $target_pm_loaded or '<undef>' ), "\n";
342              
343 7         15 my $target_scripts_found = [];
344 7         13 my $target_pms_found = [];
345              
346             # BULK88 20150608 2015.159: Win32 Bug Fix
347             #foreach my $inc_path ( $directories_loaded, @INC ) { # this doesn't work with Win32
348             # DEV NOTE: search order precedence for script command is OS paths, path of loaded TARGET/Config.pm (this file), Perl INC paths
349 7         73 foreach my $inc_path ( ( split ':', $ENV{PATH} ), File::Spec->catpath( $volume_loaded, $directories_loaded, '' ), @INC ) {
350              
351             # print {*STDERR} 'in ' . $target_package_name_config . ', top of main foreach() loop, have $inc_path = ', $inc_path, "\n";
352 147         260 my $sub_inc_paths = [];
353              
354             # push @{$sub_inc_paths}, $inc_path;
355 147         638 ( my $inc_volume, my $inc_directories, my $inc_file ) = File::Spec->splitpath( $inc_path, my $no_file = 1 );
356              
357 147         236 push @{$sub_inc_paths}, $inc_directories;
  147         269  
358              
359 147         508 my @directories_split = File::Spec->splitdir($inc_directories);
360 147         218 pop @directories_split;
361 147         192 push @{$sub_inc_paths}, File::Spec->catdir(@directories_split);
  147         593  
362 147         257 pop @directories_split;
363 147         187 push @{$sub_inc_paths}, File::Spec->catdir(@directories_split);
  147         490  
364              
365             # print {*STDERR} 'in ' . $target_package_name_config . ', in main foreach() loop, have $sub_inc_paths = ', "\n", Dumper($sub_inc_paths), "\n";
366             # print {*STDERR} 'in ' . $target_package_name_config . ', in main foreach() loop, have $inc_volume = ', "\n", Dumper($inc_volume), "\n";
367             # print {*STDERR} 'in ' . $target_package_name_config . ', in main foreach() loop, have $inc_directories = ', "\n", Dumper($inc_directories), "\n";
368             # print {*STDERR} 'in ' . $target_package_name_config . ', in main foreach() loop, have $inc_file = ', "\n", Dumper($inc_file), "\n";
369              
370 147         270 my $possible_target_scripts = [];
371 147         193 foreach my $sub_inc_path ( @{$sub_inc_paths} ) {
  147         226  
372 441         594 push @{$possible_target_scripts}, File::Spec->catpath( $inc_volume, $sub_inc_path, $target_file_name_script );
  441         1624  
373 441 100       859 if ( $sub_inc_path ne q{} ) {
374 406         461 push @{$possible_target_scripts}, File::Spec->catpath( $inc_volume, File::Spec->catdir( $sub_inc_path, 'script' ), $target_file_name_script );
  406         2341  
375 406         737 push @{$possible_target_scripts}, File::Spec->catpath( $inc_volume, File::Spec->catdir( $sub_inc_path, 'bin' ), $target_file_name_script );
  406         2466  
376             }
377             else {
378 35         60 push @{$possible_target_scripts}, File::Spec->catpath( $inc_volume, 'script', $target_file_name_script );
  35         124  
379 35         53 push @{$possible_target_scripts}, File::Spec->catpath( $inc_volume, 'bin', $target_file_name_script );
  35         133  
380             }
381             }
382              
383 147         238 foreach my $possible_target_script ( @{$possible_target_scripts} ) {
  147         221  
384              
385             # print {*STDERR} 'in ' . $target_package_name_config . ', have $possible_target_script = ', $possible_target_script, "\n";
386             # BULK88 20150608 2015.159: Win32 Bug Fix
387             # if ( ( -e $possible_target_script ) and ( -x $possible_target_script ) ) {
388 1323 50 66     6801 if ( ( -f $possible_target_script ) and ( $OSNAME eq 'MSWin32' ? 1 : -x $possible_target_script ) ) {
    50          
389 133         221 my $is_unique = 1;
390 133         160 foreach my $target_script_found ( @{$target_scripts_found} ) {
  133         211  
391 371 100       637 if ( $target_script_found eq $possible_target_script ) { $is_unique = 0; }
  105         154  
392             }
393 133 100       529 if ($is_unique) { push @{$target_scripts_found}, $possible_target_script; }
  28         40  
  28         61  
394             }
395             }
396              
397 147 50       302 if ( not defined $target_pm_loaded ) {
398 147         1095 my $possible_target_pm = File::Spec->catfile( $inc_path, $target_file_name_pm );
399              
400             # BULK88 20150608 2015.159: Win32 Bug Fix
401             # if ( -e $possible_target_pm ) {
402 147 100       1138 if ( -f $possible_target_pm ) {
403 21         39 my $is_unique = 1;
404 21         28 foreach my $target_pm_found ( @{$target_pms_found} ) {
  21         41  
405 14 100       44 if ( $target_pm_found eq $possible_target_pm ) {
406 7         15 $is_unique = 0;
407             }
408             }
409 21 100       59 if ($is_unique) { push @{$target_pms_found}, $possible_target_pm; }
  14         21  
  14         51  
410             }
411             }
412             }
413              
414             #print {*STDERR} 'in ' . $target_package_name_config . ', have $target_scripts_found = ', "\n", Dumper($target_scripts_found), "\n";
415             #print {*STDERR} 'in ' . $target_package_name_config . ', have $target_pms_found = ', "\n", Dumper($target_pms_found), "\n";
416              
417 7 50       23 if ( scalar @{$target_scripts_found} == 0 ) {
  7         27  
418 0         0 die 'ERROR EEXRP00: Failed to find `' . $target_file_name_script . '` executable, dying' . "\n";
419             }
420 7         25 my $target_script_found = $target_scripts_found->[0];
421 7 50       14 if ( scalar @{$target_scripts_found} > 1 ) {
  7         23  
422 7         44 RPerl::warning( 'WARNING WEXRP00: Found multiple `'
423             . $target_file_name_script
424             . '` executables, using first located, ' . q{`}
425             . $target_script_found . q{`}
426             . "\n" );
427             }
428              
429 7         16 my $target_pm_found = undef;
430 7 50       28 if ( defined $target_pm_loaded ) {
431 0         0 $target_pm_found = $target_pm_loaded;
432             }
433             else {
434              
435 7 50       18 if ( scalar @{$target_pms_found} == 0 ) {
  7         22  
436 0         0 Carp::croak 'ERROR EINRP00: Failed to find ' . $target_file_name_pm . ' module, croaking';
437             }
438 7         15 foreach my $target_pm_found_single ( @{$target_pms_found} ) {
  7         17  
439             # strip leading './' and '.\', for matching purposes only, do not actually save stripped filename
440 14         27 my $target_pm_found_single_stripped = $target_pm_found_single;
441 14 50 33     95 if (((substr $target_pm_found_single, 0, 2) eq './') or ((substr $target_pm_found_single, 0, 2) eq '.\\')) {
442 0         0 substr $target_pm_found_single_stripped, 0, 2, q{};
443             }
444 14 100       42 if ( $target_pm_found_single_stripped eq $target_pm_wanted ) {
445 7         17 $target_pm_found = $target_pm_found_single;
446             }
447             }
448 7 50       28 if ( not defined $target_pm_found ) {
449 0         0 Carp::croak 'ERROR EINRP01: Expected to find ', $target_pm_wanted, ' but instead found ', "\n", Dumper($target_pms_found), ', croaking';
450             }
451             }
452              
453             #print {*STDERR} 'in ' . $target_package_name_config . ', have $target_pm_found = ', $target_pm_found, "\n";
454             #print {*STDERR} 'in ' . $target_package_name_config . ', have $target_script_found = ', $target_script_found, "\n";
455              
456             #( my $volume_target_pm, my $directories_target_pm, my $file_target_pm ) = File::Spec->splitpath( $target_pm_found, $no_file = 0 );
457             #( my $volume_target_script, my $directories_target_script, my $file_target_script ) = File::Spec->splitpath( $target_script_found, $no_file = 0 );
458 7         123 ( undef, my $directories_target_pm, my $file_target_pm ) = File::Spec->splitpath( $target_pm_found, $no_file = 0 );
459 7         58 ( undef, my $directories_target_script, my $file_target_script ) = File::Spec->splitpath( $target_script_found, $no_file = 0 );
460              
461             #print {*STDERR} 'in ' . $target_package_name_config . ', have $volume_target_pm = ', $volume_target_pm, "\n";
462             #print {*STDERR} 'in ' . $target_package_name_config . ', have $directories_target_pm = ', $directories_target_pm, "\n";
463             #print {*STDERR} 'in ' . $target_package_name_config . ', have $file_target_pm = ', $file_target_pm, "\n";
464             #print {*STDERR} 'in ' . $target_package_name_config . ', have $volume_target_script = ', $volume_target_script, "\n";
465             #print {*STDERR} 'in ' . $target_package_name_config . ', have $directories_target_script = ', $directories_target_script, "\n";
466             #print {*STDERR} 'in ' . $target_package_name_config . ', have $file_target_script = ', $file_target_script, "\n";
467              
468 7         109 my @directories_target_pm_split = File::Spec->splitdir($directories_target_pm);
469 7         44 my @directories_target_script_split = File::Spec->splitdir($directories_target_script);
470 7         17 my @directories_base_split = ();
471              
472 7         34 for my $i ( 0 .. ( ( scalar @directories_target_pm_split ) - 1 ) ) {
473 14 100       38 if ( $directories_target_pm_split[$i] eq $directories_target_script_split[$i] ) {
474 7         22 push @directories_base_split, $directories_target_pm_split[$i];
475             }
476             else {
477 7         24 for my $j ( 0 .. ( $i - 1 ) ) {
478 7         190 shift @directories_target_pm_split;
479 7         24 shift @directories_target_script_split;
480             }
481 7         21 last;
482             }
483             }
484              
485             #print {*STDERR} 'in ' . $target_package_name_config . ', have @directories_base_split = ', "\n", Dumper(\@directories_base_split), "\n";
486             #print {*STDERR} 'in ' . $target_package_name_config . ', have @directories_target_pm_split = ', "\n", Dumper(\@directories_target_pm_split), "\n";
487             #print {*STDERR} 'in ' . $target_package_name_config . ', have @directories_target_script_split = ', "\n", Dumper(\@directories_target_script_split), "\n";
488              
489 7         33 my $MY_BASE_PATH;
490             my $MY_INCLUDE_PATH;
491 7         0 my $MY_SCRIPT_PATH;
492 7         0 my $MY_CORE_PATH;
493              
494             # NEED FIX: how do we catpath() with some $volume instead of catdir() below, without breaking relative paths?
495 7         68 $MY_BASE_PATH = File::Spec->catpath( $volume_loaded, File::Spec->catdir(@directories_base_split), '' );
496 7 50       32 if ( $MY_BASE_PATH eq q{} ) {
497 0         0 $MY_INCLUDE_PATH = File::Spec->catpath( $volume_loaded, File::Spec->catdir(@directories_target_pm_split), '' );
498 0         0 $MY_SCRIPT_PATH = File::Spec->catpath( $volume_loaded, File::Spec->catdir(@directories_target_script_split), '' );
499             #print {*STDERR} 'in ' . $target_package_name_config . ', have $MY_BASE_PATH eq q{} = ', $MY_BASE_PATH, "\n";
500             }
501             else {
502 7         40 $MY_INCLUDE_PATH = File::Spec->catdir( $MY_BASE_PATH, @directories_target_pm_split );
503 7         39 $MY_SCRIPT_PATH = File::Spec->catdir( $MY_BASE_PATH, @directories_target_script_split );
504             #print {*STDERR} 'in ' . $target_package_name_config . ', have $MY_BASE_PATH ne q{} ', $MY_BASE_PATH, "\n";
505             }
506              
507 7         21 foreach my $inc_path (@INC) {
508 63         256 $MY_CORE_PATH = File::Spec->catdir( $inc_path, 'CORE' );
509 63         333 my $inc_core_perl_h_path = File::Spec->catfile( $MY_CORE_PATH, 'perl.h' );
510 63 100 66     621 if ( ( -e $inc_core_perl_h_path ) and ( -r $inc_core_perl_h_path ) and ( -f $inc_core_perl_h_path ) ) { last; }
  7   66     22  
511 56         126 else { $MY_CORE_PATH = q{}; }
512             }
513              
514             #print {*STDERR} 'in ' . $target_package_name_config . ', have $MY_BASE_PATH = ', $MY_BASE_PATH, "\n";
515             #print {*STDERR} 'in ' . $target_package_name_config . ', have $MY_INCLUDE_PATH = ', $MY_INCLUDE_PATH, "\n";
516             #print {*STDERR} 'in ' . $target_package_name_config . ', have $MY_SCRIPT_PATH = ', $MY_SCRIPT_PATH, "\n";
517             #print {*STDERR} 'in ' . $target_package_name_config . ', have $MY_CORE_PATH = ', $MY_CORE_PATH, "\n";
518            
519 7         76 return [$MY_BASE_PATH, $MY_INCLUDE_PATH, $MY_SCRIPT_PATH, $MY_CORE_PATH];
520             }
521              
522             # [[[ OPERATIONS SPECIAL ]]]
523              
524             my $file_name_config = 'RPerl/Config.pm'; # this file name
525             my $package_name_config = 'RPerl::Config'; # this file's primary package name
526             my $file_name_pm = 'RPerl.pm';
527             my $file_name_script = 'rperl';
528             ($BASE_PATH, $INCLUDE_PATH, $SCRIPT_PATH, $CORE_PATH) = @{set_system_paths($file_name_config, $package_name_config, $file_name_pm, $file_name_script)};
529              
530             1; # end of package
531              
532              
533             # export system paths to main:: namespace for use by PMC files
534             package main;
535              
536             # [[[ OO CLASS PROPERTIES SPECIAL ]]]
537             # DEV NOTE: duplicate lines to avoid 'used only once' warnings
538             our $BASE_PATH = $RPerl::BASE_PATH;
539             $BASE_PATH = $RPerl::BASE_PATH;
540             our $INCLUDE_PATH = $RPerl::INCLUDE_PATH;
541             $INCLUDE_PATH = $RPerl::INCLUDE_PATH;
542             our $SCRIPT_PATH = $RPerl::SCRIPT_PATH;
543             $SCRIPT_PATH = $RPerl::SCRIPT_PATH;
544              
545             1; # end of package