File Coverage

MIBLoadOrder.pm
Criterion Covered Total %
statement 10 351 2.8
branch 0 166 0.0
condition 0 9 0.0
subroutine 3 18 16.6
pod 1 6 16.6
total 14 550 2.5


line stmt bran cond sub pod time code
1             # Perl Module
2             #
3             # Purpose: Determine load order of a group of MIB files
4             #
5             # Written: 9/2/2003, sparsons@cpan.org
6             #
7             # Look at end of file for all POD
8             #
9             #
10             # 8/5/2004 v1.0.0 (sparsons)
11             # - changed the DEFINITION and IMPORT parser
12             # - grab DEF and IMPORT as chunks, then parse the chunck
13             # - took out -singlefile option
14             # - if a DEF is found in more than one file, function errors out
15             #
16             # 8/11/2004 v1.0.1 (sparsons)
17             # - changed MIB filehandle to be $_MIB, reason being install failure
18             # on some platforms, MIB filehandle treated as bareword
19             #
20             # 8/26/2004 v1.1.0 (sparsons)
21             # - do not error when DEFINITION found in multiple files
22             # just do warning, keep first file
23             # - account for multiple BEGIN/END blocks
24             # - allow for no extensions --ext noExt
25             #
26              
27              
28             package Net::Dev::Tools::MIB::MIBLoadOrder;
29              
30 1     1   27707 use strict;
  1         2  
  1         46  
31              
32             BEGIN {
33 1     1   5 use Exporter();
  1         1  
  1         71  
34 1     1   3 our $VERSION = '1.1.0';
35 1         21 our @ISA = qw(Exporter);
36              
37 1         16 our @EXPORT = qw(
38             mib_load
39             mib_load_order
40             mib_load_definitions
41             mib_load_trace
42             mib_load_warnings
43             mib_load_error
44             );
45              
46 1         6216 our @EXPORT_OK = qw();
47              
48             }
49              
50             our %ARGS;
51             our $ERROR;
52             our $WARNING;
53             our @WARNINGS;
54             our %DEFINITIONS;
55             our @STD_MIB_FILES;
56             our @ENT_MIB_FILES;
57             our %FILE_EXT;
58             our @WEIGHTS_SORTED;
59             our @LOAD_ORDER;
60             our $DEBUG = 0;
61             our $ORDER_LOOPS = 0;
62             our $_TRACK_FLAG = 0;
63             our $_TRACK_INDEX = 0;
64             our %TRACK_HASH = ();
65             our $_TYPE ='';
66             our $_PRIORITY = 0;
67             our $_SINGLE = 1;
68             our @_EXCLUDE = ();
69              
70              
71              
72              
73             ##############################################################################
74             #
75             # Functions
76             #
77             ##############################################################################
78             #
79             #
80             sub mib_load {
81 0     0 1   %ARGS = @_;
82 0           %FILE_EXT = ();
83 0           %DEFINITIONS = ();
84 0           $ERROR = undef;
85 0           @WARNINGS = ();
86 0           $WARNING = undef;
87 0           @STD_MIB_FILES = ();
88 0           @ENT_MIB_FILES = ();
89 0           @WEIGHTS_SORTED = ();
90 0           $ORDER_LOOPS = 0;
91              
92 0           my ($_arg, $_ext, $_file,
93             $_parsed, $_sorted, $_def, $_loop,
94             );
95 0           my %_extensions;
96 0           my $_files_found = undef;
97 0           my $_max_loops = '1000';
98              
99             # check arguments
100 0           foreach $_arg (keys %ARGS) {
101 0 0         if ($_arg =~ /^-?StandardMIBs$/i) {next;}
  0 0          
  0 0          
    0          
    0          
    0          
    0          
    0          
102 0           elsif ($_arg =~ /^-?EnterpriseMIBs$/i) {next;}
103 0           elsif ($_arg =~ /^-?Extensions$/i) {next;}
104 0           elsif ($_arg =~ /^-?exclude$/i) {next;}
105 0           elsif ($_arg =~ /^-?track$/i) {$_TRACK_FLAG = delete($ARGS{$_arg});}
106 0           elsif ($_arg =~ /^-?prioritize$/i) {$_PRIORITY = delete($ARGS{$_arg});}
107 0           elsif ($_arg =~ /^-?maxloops$/i) {$_max_loops = delete($ARGS{$_arg});}
108             elsif ($_arg =~ /^-?debug$/i) {$DEBUG = delete($ARGS{$_arg});}
109             else {
110 0           $ERROR = "unsupported argument: [$_arg]";
111 0 0         return wantarray ? (undef, undef, $ERROR) : undef;
112             }
113             }
114              
115             # see what extensions to check for
116 0 0         if (defined($ARGS{Extensions})) {
117 0           foreach $_ext ( @{$ARGS{Extensions}} ) {
  0            
118 0           $FILE_EXT{$_ext} = 1;
119 0           _myprintf("File Extension check: %s [%s]\n", $_ext, $FILE_EXT{$_ext});
120             }
121             }
122             else {
123 0           $FILE_EXT{mib} = 1;
124 0           _myprintf("File Extension check: %s [%s], default\n", 'mib', $FILE_EXT{mib});
125             }
126              
127             # see what dirs and/or files are given
128 0           _myprintf("Examine StandardMIBs list\n");
129 0 0         if (defined($ARGS{StandardMIBs})) {
130 0           foreach $_file ( @{$ARGS{StandardMIBs}} ) {
  0            
131 0           $_files_found = _scan_file_list('Standard', $_file);
132 0 0         if ($_files_found) {
133 0           _myprintf("Files found: %s contains %s files\n", $_file, $_files_found);
134             }
135             else {
136 0 0         return wantarray ? (undef, undef, $ERROR) : undef;
137             }
138             }
139             }
140 0           _myprintf("Examine EnterpriseMIBs list\n");
141 0 0         if (defined($ARGS{EnterpriseMIBs})) {
142 0           foreach $_file ( @{$ARGS{EnterpriseMIBs}} ) {
  0            
143 0           $_files_found = _scan_file_list('Enterprise', $_file);
144 0 0         if ($_files_found) {
145 0           _myprintf("Files found: %s contains %s files\n", $_file, $_files_found);
146             }
147             else {
148 0 0         return wantarray ? (undef, undef, $ERROR) : undef;
149             }
150             }
151             }
152              
153             # parse the files
154 0           foreach $_file ('TYPE::STD', @STD_MIB_FILES, 'TYPE::ENT', @ENT_MIB_FILES ) {
155             # determine type
156 0 0         if ($_file eq "TYPE::STD") {$_TYPE = 'Standard'; next;}
  0            
  0            
157 0 0         if ($_file eq "TYPE::ENT") {$_TYPE = 'Enterprise'; next;}
  0            
  0            
158              
159 0           $_parsed = _parse_mib_file($_file);
160 0 0         unless ($_parsed) {
161 0 0         return wantarray ? (undef, undef, $ERROR) : undef;
162             }
163             }
164              
165             # compute the weights for the definitions
166 0           _compute_definition_weights();
167              
168             # prioritize
169             # look at enterprise weights, make all standard weights higher
170 0 0         if ($_PRIORITY) { _prioritize(); }
  0            
171              
172             # find the warnings
173 0           _find_warnings();
174              
175              
176             # sort weights and sort definitions until the
177             # &_sort_definitions() returns true
178              
179 0           do {
180 0           ++$ORDER_LOOPS;
181              
182 0 0         if ($ORDER_LOOPS == $_max_loops) {
183 0           $ERROR = "max loops $_max_loops excedded";
184 0 0         return wantarray ? (undef, undef, $ERROR) : undef;
185             }
186              
187 0           foreach $_def (sort keys %DEFINITIONS) {
188 0           _track_it("$_def", "SORTING Weights and DEFINITIONS, loop $_loop");
189             }
190             # sort the values for the weight
191 0           _sort_weights();
192              
193             # from sorted weights, make list
194 0           $_sorted = _sort_definitions();
195             } until $_sorted;
196              
197 0 0         return wantarray ? (\@LOAD_ORDER, scalar(@WARNINGS), $ERROR) : \@LOAD_ORDER;
198             } # end sub new
199              
200              
201             ##############################################################################
202             #
203             # Return Reference Functions
204             #
205             ##############################################################################
206             #
207             # functions to return variables or references to variables
208              
209 0     0 0   sub mib_load_order { return(\@LOAD_ORDER); }
210 0     0 0   sub mib_load_definitions { return(\%DEFINITIONS); }
211 0     0 0   sub mib_load_trace { return(\%TRACK_HASH); }
212 0     0 0   sub mib_load_warnings { return(\@WARNINGS); }
213 0     0 0   sub mib_load_error { return($ERROR); }
214              
215              
216              
217             ##############################################################################
218             #
219             # Private Functions
220             #
221             ##############################################################################
222             #
223             # Purpose: function to scan file list
224             #
225             # Arguments:
226             # $_[0] = Source (Standard or Enterprise)
227             # $_[1] = file
228             #
229             # Return
230             # Integer indicating how many files found
231             # or undef on error
232             #
233             sub _scan_file_list {
234              
235 0     0     my $_tag = $_[0];
236 0           my $_chk_file = $_[1];
237 0           my $_match = undef;
238 0           my ($_f, $_chk_ext, $_fullname, $_separator);
239 0           my @_mib_files = ();
240              
241 0           $ERROR = "$_chk_file: no files";
242              
243 0           _myprintf(" Examining %s list item: [%s]\n", $_tag, $_chk_file);
244             # see what our dir separator is
245             # store it and strip it off the end
246             #
247 0 0         if ($_chk_file =~/\//) {$_separator = '/'; $_chk_file =~ s/\/$//;}
  0 0          
  0            
  0            
248 0           elsif ($_chk_file =~/\\/) {$_separator = '\\'; $_chk_file =~ s/\\$//;}
249              
250 0           $_chk_file =~ s/\/$//;
251             # see if its a directory
252 0 0 0       if (-e $_chk_file and -d $_chk_file) {
    0 0        
253 0           _myprintf(" Determined %s list item: [%s] to be dir\n",
254             $_tag, $_chk_file
255             ) ;
256 0 0         if (!-r $_chk_file) {
257 0           $ERROR = "$_tag: $_chk_file not readable";
258 0           _myprintf(" $_tag: $_chk_file not readable");
259 0           return(undef);
260             }
261             # read the files in the directory
262 0           opendir(DIR, $_chk_file);
263 0           while ($_f = readdir(DIR)) {
264 0 0         next if $_f =~ /^\.$/;
265 0 0         next if $_f =~ /^\..$/;
266             # check the file extension
267 0 0         if ($_f =~ /\.(.+)$/) {
    0          
268 0           $_chk_ext = $1;
269 0 0         if (defined($FILE_EXT{$_chk_ext})) {
270 0           $_fullname = sprintf("%s%s%s", $_chk_file, $_separator, $_f);
271 0           $_match++;
272 0           push(@_mib_files, $_fullname);
273 0           _myprintf(" MIB file: %s: found: [%s] [%s] \n",
274             $_tag, $_f, $_fullname
275             ) ;
276             }
277             }
278             # allow for no extensions
279             elsif ($FILE_EXT{'noExt'}) {
280 0           $_fullname = sprintf("%s%s%s", $_chk_file, $_separator, $_f);
281 0           $_match++;
282 0           push(@_mib_files, $_fullname);
283 0           _myprintf(" MIB file: %s: found: noExt [%s] [%s] \n",
284             $_tag, $_f, $_fullname
285             ) ;
286             }
287             }
288 0           closedir(DIR);
289             }
290             # see if its a file
291             elsif (-e $_chk_file and -f $_chk_file) {
292 0           _myprintf(" Determined %s list item: [%s] to be file\n", $_tag, $_chk_file) ;
293 0 0         if (!-r $_chk_file) {
294 0           $ERROR = "$_tag: $_chk_file not readable";
295 0           return(undef);
296             }
297             # check the file extension
298 0 0         if ($_chk_file =~ /\w+\.(.+)$/) {
    0          
299 0           $_chk_ext = $1;
300 0 0         if (defined($FILE_EXT{$_chk_ext})) {
301 0           _myprintf(" MIB file: %s: found: %s\n", $_tag, $_chk_file) ;
302 0           $_match++;
303 0           push(@_mib_files, $_chk_file);
304             }
305             }
306             elsif ($FILE_EXT{'noExt'}) {
307 0           _myprintf(" MIB file: %s: found: noExt %s\n", $_tag, $_chk_file);
308 0           $_match++;
309 0           push(@_mib_files, $_chk_file);
310             }
311             }
312 0 0         if (scalar(@_mib_files)) {
313 0 0         if ($_tag =~ /Standard/) {push(@STD_MIB_FILES, @_mib_files);}
  0            
314 0 0         if ($_tag =~ /Enterprise/) {push(@ENT_MIB_FILES, @_mib_files);}
  0            
315             }
316              
317 0           return($_match);
318             } # end _scan_file_list
319              
320             #
321             #.............................................................................
322             #
323             # function to parse the MIB file
324             # populate global hashes
325             #
326             # Arguments
327             # $_[0] = file
328             #
329             # Return
330             # (success, error)
331             # success = 1 or undef
332             #
333             sub _parse_mib_file {
334 0     0     my ($_def, $_import, $_lastline);
335 0           my $_begin_count = 0;
336 0           my $_definition_count = 0;
337 0           my $_definition = undef;
338 0           my $_import_flag = 0;
339 0           my $_end_count = 0;
340 0           my $_excl;
341 0           my $_match = 0;
342 0           my %_DEF = ();
343 0           my $_MIB;
344              
345 0           $ERROR = "$_[0]: failed to parse mib file";
346              
347 0           _myprintf("PARSING: %s\n", $_[0]) ;
348              
349             # see if we are excluding, check filename for pattern
350 0 0         if ( defined($ARGS{exclude})) {
351 0           foreach $_excl ( @{$ARGS{exclude}} ) {
  0            
352 0 0         if ($_[0] =~ /$_excl/) {
353 0           $_match++;
354 0           $WARNING = "exclusion match [$_excl] on [$_[0]]";
355 0           push(@WARNINGS, ['_EXCL_', "$WARNING"]);
356 0           _myprintf("Exclusion: %s\n", $WARNING);
357             }
358             }
359 0 0         return(1) if $_match;
360             }
361              
362             # open and parse the file
363 0           undef $_MIB;
364 0 0         open($_MIB, "$_[0]") || return (undef, "can not open $_[0]: $!");
365 0           while(<$_MIB>) {
366 0 0         if (/^$/) {next;}
  0            
367 0 0         if (/^\s+$/) {next;}
  0            
368 0 0         if (/^--/) {next;}
  0            
369 0 0         if (/^\s+--/) {next;}
  0            
370            
371            
372 0 0         $_begin_count++ if /\bBEGIN\s/;
373 0 0         $_end_count++ if /^END\b/;
374             # parse out definitions
375 0 0         if (/DEFINITIONS/) {
376 0 0         if (/\b([A-Z][\-?\w]{0,63})\b\s+DEFINITIONS\s+::=\s+BEGIN/ )
  0            
377             {$_def = $1;}
378             else {
379 0 0         if (join(' ', $_lastline, $_) =~ /\b([A-Z][\-?\w]{0,63})\b\s+DEFINITIONS\s+::=\s+BEGIN/m)
  0            
380             {$_def= $1;}
381             }
382 0 0         unless ($_def =~ /--/) {
383 0           $_definition = $_def;
384 0           $_definition_count++;
385 0           $_import_flag = 0;
386 0           _myprintf(" DEFINITION parsed: line %-4s count: %3s %s [%s]\n",
387             $., $_definition_count, $_TYPE, $_definition
388             );
389 0           _track_it("$_definition", "defined in [$_[0]], line: $. type: $_TYPE");
390             # see if DEF already known in other file
391 0 0         if (defined($DEFINITIONS{$_definition}{file})) {
392 0           $WARNING = sprintf("DEF: %s previously defined in: %s",
393             $_definition, $DEFINITIONS{$_definition}{file}
394             );
395 0           push(@WARNINGS, [$_[0], $WARNING] );
396 0           _myprintf(" %s\n", $WARNING);
397 0           return(1);
398             }
399              
400             # set warning if more than one DEF per file
401 0 0         if ($_definition_count > 1) {
402 0           $WARNING = "multiple DEFINITIONs in $_[0]";
403 0           push(@WARNINGS, ['_FILE_', $WARNING] );
404             }
405 0           $DEFINITIONS{$_definition}{file} = $_[0];
406 0           $DEFINITIONS{$_definition}{type} = $_TYPE;
407              
408 0           _track_it("$_definition", "adding $_TYPE [$_[0]] to file list");
409              
410             }
411             }
412             # we only want to extract IMPORT chunk
413             # so detect when the construct is on the current lines
414 0 0         if (/IMPORTS\s+/) {$_import_flag = 1;}
  0            
415              
416             # find end of DEFINITIONS
417 0 0         if (/^END\s*$/) {
418             # make sure we have hash entry for those with no imports
419 0 0         if (!exists($_DEF{$_definition})) {$_DEF{$_definition} = '';}
  0            
420 0           _myprintf(" END parsed: %s begins %s ends\n", $_begin_count, $_end_count);
421 0 0         if ($_begin_count == $_end_count) {
422 0           _myprintf(" END DEFINITION: %s begins %s ends %s\n",
423             $_definition,$_begin_count, $_end_count
424             );
425 0           $_definition = undef;
426 0           $_import_flag = 0;
427             }
428             }
429              
430             # $_DEF{$_definition} will be a chunk that has the IMPORTS
431 0 0 0       if ($_definition && $_import_flag == 1) {
432 0           $_DEF{$_definition} = join('', $_DEF{$_definition}, $_);
433 0 0         $_import_flag = 0 if /;/;
434             }
435              
436 0           $_lastline = $_;
437             }
438 0           close($_MIB);
439              
440             # if no definition found, issue warning
441 0 0         if ($_definition_count == 0) {
442 0           $WARNING = sprintf("No DEFINITION parsed in: [%s]", $_[0]);
443 0           push(@WARNINGS, ['_FILE_', $WARNING] );
444 0           return(1);
445             }
446              
447             # get the IMPORTS
448 0           foreach $_definition (sort keys %_DEF) {
449 0           _myprintf(" IMPORT check check [%s] for imports\n", $_definition);
450             # check to see if import block was parsed
451 0 0         if ($_DEF{$_definition} eq "") {
452 0           $WARNING = sprintf("No IMPORTS parsed in: [%s]", $_[0]);
453 0           push(@WARNINGS, ['_FILE_', $WARNING] );
454 0           _myprintf(" IMPORT parsed: WARN: no imports parsed\n");
455             }
456             # extract info from import block
457             else {
458 0           $_DEF{$_definition} =~ /IMPORTS\s+(.+[A-Z][\w\-?]{0,63})\s*;/s;
459 0           $_ = $1;
460             # parse out moduleIdentifier (after 'FROM')
461 0           @{$DEFINITIONS{$_definition}{imports}} = m/FROM\s+([A-Z][\w\-]{0,63})/sg;
  0            
462 0           _myprintf(" IMPORT parsed: count: %s def: %s block size: %s\n",
463 0           scalar(@{$DEFINITIONS{$_definition}{imports}}),
464             $_definition,
465             length($_DEF{$_definition}),
466             );
467 0 0         if (@{$DEFINITIONS{$_definition}{imports}}) {
  0            
468 0           _myprintf(" IMPORT parsed: [%s]\n",
469 0           join(', ', @{$DEFINITIONS{$_definition}{imports}})
470             );
471 0 0         if ($_TRACK_FLAG) {
472 0           foreach $_import (@{$DEFINITIONS{$_definition}{imports}}) {
  0            
473 0           _track_it("$_definition", "requires IMPORT $_import");
474 0           _track_it("$_import", "required import for $_definition");
475             }
476             }
477             }
478             else {
479 0           _myprintf(" IMPORT parsed: NONE: [%s] in chunk\n", $_definition);
480 0           $WARNING = sprintf("No IMPORTS parsed from IMPORT chunk: [%s]", $_definition);
481 0           push(@WARNINGS, ['_FILE_', $WARNING]);
482 0           _track_it("$_definition", "no IMPORTS parsed from IMPORT chunk");
483             }
484             }
485              
486              
487             }
488 0           return(1);
489             } # end _parse_mib_file
490              
491             #
492             #.............................................................................
493             #
494             #
495             # function to compute the weights of the DEFINITIONS
496             #
497             # Arguments
498             # none, work on global hash
499             #
500             # Return
501             # none, populate global hash
502             sub _compute_definition_weights {
503              
504 0     0     my $_base_weight = 2; # all definitions get this
505 0           my $_import_required = '-1'; # if definition requires imports
506 0           my $_import_weight = 5; # apply to all imports
507 0           my $_import2_weight = 1000; # apply to all imports required by prev import
508              
509 0           my ($_def, $_imp, $_imp2);
510              
511             # loop thru each definition
512             # add $_base_weight for each definition
513 0           my $_c = 0;
514 0           foreach $_def (sort keys %DEFINITIONS) {
515 0           $DEFINITIONS{$_def}{weight} = $DEFINITIONS{$_def}{weight} + $_base_weight;
516 0           _myprintf("Weight \(%s\): %s defined, incr %s, weight = %s\n",
517             ++$_c, $_def, $_base_weight, $DEFINITIONS{$_def}{weight}
518             );
519 0           _track_it($_def, "adding base weight: $_base_weight, now $DEFINITIONS{$_def}{weight}");
520             # if this definition requires imports, add $_import_required (subtraction)
521 0 0         if (scalar($DEFINITIONS{$_def}{imports})) {
522 0           $DEFINITIONS{$_def}{weight} = $DEFINITIONS{$_def}{weight} + $_import_required;
523 0           _myprintf(" Weight: requires IMPORTs, decr %s, weight = %s\n",
524             $_import_required, $DEFINITIONS{$_def}{weight}
525             );
526 0           _track_it($_def,
527             "requires imports, decr $_import_required, now $DEFINITIONS{$_def}{weight}"
528             );
529             # foreach import required, add $_import_weight to the import's definition
530 0           foreach $_imp (@{$DEFINITIONS{$_def}{imports}}) {
  0            
531 0           $DEFINITIONS{$_imp}{weight} = $DEFINITIONS{$_imp}{weight} + $_import_weight;
532 0           $DEFINITIONS{$_imp}{'import'}++;
533 0           _myprintf(" Weight: required IMPORT: [%s] incr %s, weight = %s\n",
534             $_imp, $_import_weight, $DEFINITIONS{$_imp}{weight}
535             );
536 0           _track_it($_imp,
537             "required IMPORT for $_def, incr $_import_weight, now $DEFINITIONS{$_imp}{weight}"
538             );
539             # if import requires import, add $_import2_weight to what it imports
540 0 0         if (scalar($DEFINITIONS{$_imp}{imports})) {
541 0           foreach $_imp2 (@{$DEFINITIONS{$_imp}{imports}}) {
  0            
542 0           $DEFINITIONS{$_imp2}{weight} = $DEFINITIONS{$_imp2}{weight} + $_import2_weight;
543 0           _myprintf(" Weight: IMPORT requires: [%s], incr %s, weight = %s\n",
544             $_imp2, $_import2_weight, $DEFINITIONS{$_imp2}{weight}
545             );
546 0           _track_it($_imp2,
547             "required by import $_imp, incr $_import2_weight, now $DEFINITIONS{$_imp2}{weight}"
548             );
549             }
550             }
551             }
552             }
553             }
554 0           1;
555             }
556             #
557             #.............................................................................
558             #
559             # function to prioritize standard mibs over enterprise mibs
560             # look at all enterprise mib definitions, find highest weight
561             # look at all standard mibs, if weight is lower, make it '1' more than
562             # highest enterprise
563             #
564             # Arguments
565             # none, works on global hash
566             #
567             # Return
568             # none, works on global hash
569             #
570             sub _prioritize {
571              
572 0     0     my $_ent_max = 0;
573 0           my ($_def, $_prev_weight);
574              
575             # find highest enterprise weight
576 0           foreach $_def (keys %DEFINITIONS) {
577 0 0         if ($DEFINITIONS{$_def}{type} eq "Enterprise") {
578 0 0         if ($DEFINITIONS{$_def}{weight} > $_ent_max)
  0            
579             {$_ent_max = $DEFINITIONS{$_def}{weight};}
580             }
581             }
582 0           _myprintf("highest Enterprise MIB weight = %s\n", $_ent_max);
583              
584             # check each standard mib, if weight is less than or equal to highest
585             # enterprise mib, change standard weight to +1 of highest enterprise
586             # this will not corrupt order, another filter will assure proper order
587             # this will only get as many standared mibs in front of enterprise mibs
588             # as possible
589 0           foreach $_def (keys %DEFINITIONS) {
590 0 0         if ( $DEFINITIONS{$_def}{type} eq "Standard") {
591 0 0         if ($DEFINITIONS{$_def}{weight} <= $_ent_max ) {
592 0           $_prev_weight = $DEFINITIONS{$_def}{weight};
593 0           $DEFINITIONS{$_def}{weight} = $_ent_max + 1;
594 0           _myprintf("%s %s [%s] weight less than highest enterprise, change to %s\n",
595             $DEFINITIONS{$_def}{type},
596             $_def,
597             $_prev_weight,
598             $DEFINITIONS{$_def}{weight},
599             );
600 0           _track_it("$_def",
601             "priority change, $_prev_weight <= $_ent_max, change to $DEFINITIONS{$_def}{weight}"
602             );
603             }
604             }
605             }
606 0           1;
607             }
608             #
609             #.............................................................................
610             #
611             # function to sort the weights
612             #
613             # Arguments
614             # none, get info from global hash
615             #
616             # Return
617             # none, make global array, sorted weight
618             #
619              
620             sub _sort_weights {
621              
622 0     0     my @_weights_unsorted = ();
623 0           my %_weights = ();
624 0           my $_def_count = 0;
625 0           my ($_d);
626              
627 0           @WEIGHTS_SORTED = ();
628              
629             # extract and index the weights
630 0           foreach $_d (keys %DEFINITIONS) {
631 0           $_def_count++;
632 0           $_weights{$DEFINITIONS{$_d}{weight}} = $_weights{$DEFINITIONS{$_d}{weight}} + 1;
633 0           _myprintf("sorting: weight %s, [%s] %s DEFINITIONs\n",
634             $DEFINITIONS{$_d}{weight}, $_d, $_weights{$DEFINITIONS{$_d}{weight}},
635             );
636 0           _track_it("$_d", "sorted weight is $DEFINITIONS{$_d}{weight}");
637             }
638 0           @_weights_unsorted = keys %_weights;
639              
640 0           @WEIGHTS_SORTED = reverse sort {$a <=> $b} @_weights_unsorted;
  0            
641              
642 0 0         if ($DEBUG) {
643 0           foreach (@WEIGHTS_SORTED)
  0            
644             {_myprintf("weight sort summary: weight %8s %s definitions\n", $_, $_weights{$_});}
645             }
646 0           _myprintf("%s sorted definitions\n", $_def_count);
647 0           1;
648             }
649             #
650             #.............................................................................
651             #
652             # function to make a sorted list of definitions based on sorted weight list
653             #
654             # Arguments
655             # none, read from global hash
656             #
657             # Return
658             # none, make global list
659              
660             sub _sort_definitions {
661              
662 0     0     my ($_w, $_def, $_imp, $_d);
663 0           my $_ok = undef;
664              
665 0           @LOAD_ORDER = ();
666              
667 0           _myprintf("### Sorting DEFINITIONs, loop: %s ###\n", $ORDER_LOOPS);
668             # cycle through each weight
669 0           foreach $_w (@WEIGHTS_SORTED) {
670 0           _myprintf("weight: %8s\n", $_w);
671             # find DEFs with this weight
672 0           foreach $_def (keys %DEFINITIONS) {
673 0 0         if ($DEFINITIONS{$_def}{weight} == $_w) {
674 0           push(@LOAD_ORDER, $_def);
675 0           _myprintf(" [%s] = %s, added to load ordered, %s loaded\n",
676             $_def, $DEFINITIONS{$_def}{weight}, scalar(@LOAD_ORDER),
677             );
678 0           _track_it("$_def",
679             "sorting definition, pushing on load order list, $DEFINITIONS{$_def}{weight}"
680             );
681             # check that its imports are loaded, based on weight
682 0           foreach $_imp (@{$DEFINITIONS{$_def}{imports}}) {
  0            
683 0           _myprintf(" IMPORT [%s] required, ", $_imp);
684             # check weights of any imports are greater than definition weight
685 0 0         if ($DEFINITIONS{$_imp}{weight} <= $_w) {
686 0 0         printf("not loaded, changing weight %s => ",
687             $DEFINITIONS{$_imp}{weight}
688             ) if $DEBUG;
689 0           _track_it("$_imp",
690             "required IMPORT has lower weight: $DEFINITIONS{$_imp}{weight}"
691             );
692 0           $DEFINITIONS{$_imp}{weight} = $_w + 1;
693 0 0         printf("%s\n", $DEFINITIONS{$_imp}{weight}) if $DEBUG;
694 0           _track_it("$_imp",
695             "changed weight to $DEFINITIONS{$_imp}{weight} for requirements"
696             );
697             # update the tracking that we are resorting
698 0 0         unless ($_TRACK_FLAG) {
699 0           foreach $_d (keys %DEFINITIONS)
  0            
700             {_track_it("$_d","re-sort, $_def requires $_imp to be loaded");}
701             }
702 0           return(undef);
703             }
704             # all imports have higher weights
705             else {
706 0 0         printf("loaded, %s\n", $DEFINITIONS{$_imp}{weight})
707             if $DEBUG;
708             }
709             }
710             }
711             }
712             }
713 0           _myprintf("DEFINITIONs sorted, %s loops needed\n", $ORDER_LOOPS);
714 0           1;
715             }
716             #
717             #.............................................................................
718             #
719             # function to find the warnings
720             #
721             # loop thru all definitions, if no files exist for def, issue warning
722             #
723             # Arguments
724             # none, operate on global hash
725             #
726             # Return
727             # none, populate globah hash
728             # @WARNINGS = ([DEFINITION, cuase], [], []
729             #
730             sub _find_warnings {
731              
732 0     0     my $_no_file = 'No file found for DEFINITION';
733 0           my $_multi_files = 'DEFINITION found in multiple files';
734 0           my $_def;
735             my $_keep;
736 0           my @_dump;
737 0           my $_f;
738            
739 0           foreach $_def (sort keys %DEFINITIONS) {
740 0 0         if ( !defined($DEFINITIONS{$_def}{file}) ) {
741 0           push(@WARNINGS, ["$_def", "$_no_file"]);
742 0           _track_it("$_def", "issue warning: $_no_file");
743             }
744             }
745 0           1;
746             }
747             #
748             #.............................................................................
749             #
750             #
751             sub _myprintf {
752              
753 0 0   0     return unless $DEBUG;
754              
755 0           my $_format = shift;
756 0           my ($_pkg, $_line) = (caller)[0,2];
757 0           my $_func = (caller(1))[3];
758 0           $_pkg =~ s/.+://;
759 0           $_func =~ s/.+://;
760              
761 0           printf("%s: %s: [%s]: $_format", $_pkg, $_func, $_line, @_);
762             }
763              
764             #
765             #.............................................................................
766             #
767             # function to track events per DEFINITION
768             #
769             # Argument
770             # $_[0] = DEFINITION
771             # $_[1] = event
772             #
773             # Return
774             # none, populate global hash
775             # %TRACK{definition} = ([index, event], [], [], ...)
776             #
777             sub _track_it {
778 0 0   0     return unless $_TRACK_FLAG;
779 0           push( @{$TRACK_HASH{$_[0]}}, [++$_TRACK_INDEX, "$_[1]"] );
  0            
780 0           1;
781             }
782              
783              
784              
785             #
786             # !!!! End the Module !!!!
787             #
788              
789             1;
790             __END__