Subversion Repositories DevTools

Rev

Rev 261 | Rev 279 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
#! perl
2
########################################################################
3
# Copyright ( C ) 2004 ERG Limited, All rights reserved
4
#
5
# Module name   : jats
6
# Module type   : Perl Package
7
# Compiler(s)   : n/a
8
# Environment(s): jats
9
#
10
# Description   : A Perl Package to perform error handling within JATS
11
#
12
#                 Uses global variables
13
#                       $::ScmWho;
14
#                       $::ScmVerbose;
15
#                       $::ScmQuiet;
16
#                       $::ScmDebug;
17
#                 For use with existing scripts
18
#
19
# Usage:
20
#
21
# Version   Who      Date        Description
22
#
23
#......................................................................#
24
 
255 dpurdie 25
require 5.006_001;
227 dpurdie 26
use strict;
27
use warnings;
28
use Data::Dumper;
29
use IO::Handle;
30
 
31
package JatsError;
32
 
33
#-------------------------------------------------------------------------------
34
# Function        : BEGIN
35
#
36
# Description     : Standard Package Interface
37
#
38
# Inputs          :
39
#
40
# Returns         :
41
#
42
 
43
BEGIN {
44
    use Exporter   ();
45
    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
46
 
47
    # set the version for version checking
48
    $VERSION     = 1.00;
49
 
50
    @ISA         = qw(Exporter);
51
    @EXPORT      = qw(ErrorConfig ErrorDoExit
261 dpurdie 52
                      ReportError Fatal Error Warning
227 dpurdie 53
                      Message Message1
54
                      Information Information1
55
                      Question
263 dpurdie 56
                      Verbose0 Verbose Verbose2 Verbose3
227 dpurdie 57
                      Debug0 Debug Debug2 Debug3
58
                      IsVerbose IsDebug IsQuiet
231 dpurdie 59
                      DebugDumpData DebugDumpPackage DebugTraceBack
227 dpurdie 60
                      DebugPush DebugPop
61
                      );
62
 
63
    %EXPORT_TAGS = ( );     # eg: TAG => [ qw!name1 name2! ],
64
 
65
    # your exported package globals go here,
66
    # as well as any optionally exported functions
67
    @EXPORT_OK   = qw();
68
 
69
    #
70
    #   Ensure globals have a defined value
71
    #
263 dpurdie 72
    $::ScmWho = ''                          unless defined( $::ScmWho );
73
    $::ScmVerbose = $ENV{GBE_VERBOSE} || 0  unless defined( $::ScmVerbose );
74
    $::ScmDebug = $ENV{GBE_DEBUG} || 0      unless defined( $::ScmDebug );
75
    $::ScmQuiet = 0                         unless defined( $::ScmQuiet );
227 dpurdie 76
 
77
    #
78
    #   Force autoflush in an attempt to limit the intermingling of
79
    #   Error and non-error output.
80
    #
81
    STDOUT->autoflush(1);
82
    STDERR->autoflush(1);
83
}
84
 
85
 
86
 
87
# exported package globals go here
88
#our $ScmWho;
89
#our $ScmVerbose;
90
#our $ScmDebug;
91
our $ScmOnExit;
92
our $ScmDelayExit;
93
our $ScmErrorCount;
261 dpurdie 94
our $ScmExitCode;
227 dpurdie 95
 
96
# non-exported package globals go here
97
$ScmErrorCount = 0;
261 dpurdie 98
$ScmExitCode = 1;
227 dpurdie 99
 
100
#  initialize package globals, first exported ones
101
 
102
 
103
#-------------------------------------------------------------------------------
104
# Function        : import
105
#
106
# Description     : Package import function
107
#                   This function will examine argumenst provided in the
108
#                   invoking 'uses' list and will configure the package
109
#                   accordingly.
110
#
111
# Inputs          : $pack           - Name of this package
112
#                   @vars           - User Config Options
113
#                   Config Options:
114
#                       :name=xxxx
115
#                       :quiet=xxx
116
#                       :debug=xxx
117
#                       :verbose=xxx
118
#                       :delay_exit=xxx
119
#
120
# Returns         : 
121
#
122
sub import {
123
    my $pack = shift;
124
    my @vars;
125
    my @config;
126
 
127
    #
128
    #   Extract options of the form: :name=value and pass them to the
129
    #   ErrorConfig function. All other arguments will be passed to the
130
    #
131
    foreach ( @_ )
132
    {
133
        if ( m/^:(.+)=(.+)/ ) {
134
            push @config, $1, $2;
135
        } else {
136
            push @vars, $_;
137
        }
138
    }
139
 
140
    ErrorConfig( @config )
141
        if ( @config );
142
 
143
    #
144
    #   Invoke Exporter function to handle the arguments that I don't understand
145
    #
146
    $pack->export_to_level(1, $pack , @vars);
147
}
148
 
149
#-------------------------------------------------------------------------------
150
# Function        : ErrorConfig
151
#
152
# Description     : Configure aspects of the JATS error handle
153
#
154
# Inputs          : A hash of option,value pairs
155
#                   Valid options
156
#                       name        - Name to report in error
157
#                       verbose     - vebosity level
158
#                       debug       - debug level
159
#                       on_exit     - Register on-exit function
160
#                       delay_exit  - Delay exit on error
161
#
162
# Returns         :
163
#
164
sub ErrorConfig
165
{
166
    my %args = @_;
167
    my $name;
168
 
169
    while (my($key, $value) = each %args)
170
    {
171
        if (       $key =~ /^name/ ) {
172
            $::ScmWho = "[$value] ";
173
            $name = $value;
174
 
175
        } elsif ( $key =~ /^debug/ ) {
176
            $::ScmDebug = $value || 0;
177
 
178
        } elsif ( $key =~ /^verbose/ ) {
179
            $::ScmVerbose = $value || 0;
180
 
181
        } elsif ( $key =~ /^quiet/ ) {
182
            $::ScmQuiet = $value || 0;
183
 
184
        } elsif ( $key =~ /^on_exit/ ) {
185
            $ScmOnExit = $value;
186
 
187
        } elsif ( $key =~ /^delay_exit/ ) {
188
            $ScmDelayExit = $value;
189
 
190
        } else {
191
            Error("ErrorConfig, Unknown option: $key");
192
        }
193
    }
194
 
195
    #
196
    #   Extract program specfic debug flags from the environment
197
    #   These will be based on the reporting 'name'
198
    #       GBE_name_DEBUG
199
    #       GBE_name_VERBOSE
200
    #
201
    if ( $name )
202
    {
203
        my ($value, $tag);
204
 
205
        $tag = "GBE_${name}_DEBUG" ;
261 dpurdie 206
        $tag =~ s~\s+~~g;
227 dpurdie 207
        $value = $ENV{ $tag };
208
        if (defined $value)
209
        {
210
            $::ScmDebug = $value;
211
            Warning("Envar: $tag setting debug: $value");
212
        }
213
 
214
        $tag = "GBE_${name}_VERBOSE" ;
261 dpurdie 215
        $tag =~ s~\s+~~g;
227 dpurdie 216
        $value = $ENV{ $tag };
217
        if (defined $value)
218
        {
219
            $::ScmVerbose = $value;
220
            Warning("Envar: $tag setting verbose: $value");
221
        }
222
    }
223
 
224
    #
225
    #   Sanitise quiet and verbose
226
    #   Any verboseness disables quiet
227
    #
228
    $::ScmQuiet = 0 if ( $::ScmVerbose );
229
    $::ScmQuiet = 0 if ( $::ScmDebug );
230
}
231
 
232
 
233
#-------------------------------------------------------------------------------
234
# Function        : Information
235
#                   Message
236
#                   Question
237
#                   Warning
238
#                   Error
239
#                   Verbose
240
#                   Debug
241
#                   _Message ( Internal use only )
242
#
243
# Description     : Error, Warning and Message routines
244
#                   These routines will display a message to the user
245
#                   with the module name.
246
#
247
#                   Multiple arguments are displayed on their own line
248
#                   with suitable spacing.
249
#
250
# Inputs          : Lines of text to display
251
#
252
# Returns         : Nothing
253
#
254
sub _Message
255
{
256
    my $tag = shift;                # First argument is a tag
257
    my $count = 0;
258
 
259
    #
260
    #   Generate the message prefix
261
    #   This will only be used on the first line
262
    #   All other lines will have a space filled prefix
263
    #
264
    my $prefix = $::ScmWho . $tag;
265
    #
266
    #   Kill the eol if the Question is being asked
267
    #
268
    my $eol = ( $tag =~ m/Q/ ) ? "" : "\n";
269
    foreach my $nextline ( @_ )
270
    {
231 dpurdie 271
        next unless ( defined $nextline );              # Ignore undefined arguments
227 dpurdie 272
        chomp( my $line = $nextline );
273
        if ( $count eq 1 )
274
        {
275
            my $bol = $eol ? "" : "\n";
276
            $prefix = $bol . ' ' x length($prefix);
277
        }
278
 
279
        print "$prefix $line$eol";
280
        $count++;
281
    }
282
}
283
 
284
#-------------------------------------------------------------------------------
285
# Function        : Information
286
#                   Information1
287
#
288
# Description     : Will display informational messages
289
#                   These are normal operational messages. These may be
290
#                   supressed through the use of QUIET options
291
#
292
# Inputs          : An array of strings to display
293
#
294
sub Information
295
{
296
    _Message '(I)', @_ unless ( $::ScmQuiet);
297
}
298
 
299
sub Information1
300
{
301
    _Message '(I)', @_ unless ( $::ScmQuiet > 1);
302
}
303
 
304
 
305
#-------------------------------------------------------------------------------
306
# Function        : Message
307
#                   Message1
308
#
309
# Description     : Same as Information, except a different prefix
310
#
311
# Inputs          : An array of strings to display
312
#
313
sub Message
314
{
315
    _Message '(M)', @_ unless ( $::ScmQuiet > 1);
316
}
317
 
318
sub Message1
319
{
320
    _Message '(M)', @_ unless ( $::ScmQuiet);
321
}
322
 
323
#-------------------------------------------------------------------------------
324
# Function        : IsQuiet
325
#
326
# Description     : Determine if an Infrmation or Message will be displayed
327
#                   May be used to reduce excessive processing that may be
328
#                   discarded
329
#
330
# Inputs          : $level      - Level to test
331
#
332
# Returns         : TRUE:       A Message at $level would be displayed
333
#
334
sub IsQuiet
335
{
336
    my( $level) = @_;
337
    return $::ScmQuiet >= $level;
338
}
339
 
340
#-------------------------------------------------------------------------------
341
# Function        : Warning
342
#
343
# Description     : Display a warning message
344
#                   These may be disabled with a high quiet level
345
#
346
# Inputs          : An array of strings to display
347
#
348
sub Warning
349
{
350
    _Message '(W)', @_ unless ( $::ScmQuiet > 2);
351
}
352
 
353
#-------------------------------------------------------------------------------
354
# Function        : Question
355
#
356
# Description     : Display a Question message
357
#                   These cannot be disabled
358
#
359
# Inputs          : An array of strings to display
360
#
361
sub Question
362
{
363
    _Message '(Q)', @_;
364
    STDERR->flush;              # Force output to be displayed
365
    STDOUT->flush;              # Force output to be displayed
366
}
367
 
368
#-------------------------------------------------------------------------------
261 dpurdie 369
# Function        : Fatal
370
#
371
# Description     : Display a multi line fatal message
372
#                   This will cause the program to exit.
373
#
374
#                   Similar to Error(), except
375
#                       Display a (F) prefix
376
#                       Alters the exit code to "2"
377
#                       Will terminate program execution.
378
#                       Will not honor delayed exit configuration.
379
#
380
#                   Fatal is to be used to indicate to consumer processes that
381
#                   the error is a function of the infrastructure and cannot be
382
#                   corrected by a user. ie:
383
#                       clearcase is not available
384
#                           Not just a bad user parameter
385
#                       dpkg_archive is not available
386
#                       release manager database is not available
387
#
388
#                   Intended to be used by build deamons to determine if building
389
#                   should continue, or if the entire build process should be
390
#                   terminated.
391
#
392
# Inputs          : An array of strings to display
393
#
394
# Returns         : May not return
395
#
396
sub Fatal
397
{
398
    _Message '(F)', @_;
399
    $ScmErrorCount++;
400
    $ScmExitCode = 2;
401
    ErrorDoExit() unless ( $ScmDelayExit );
402
}
403
 
404
#-------------------------------------------------------------------------------
227 dpurdie 405
# Function        : Error
406
#
261 dpurdie 407
# Description     : Display a multi line error message
227 dpurdie 408
#                   This may cause the program to exit, or the user may have
409
#                   configured the package to accumulate error messages
410
#
411
#                   This could be used to generate multiple error messages
412
#                   while parsing a file, and then terminate program execution at
413
#                   the end of the phase.
414
#
415
# Inputs          : An array of strings to display
416
#
417
# Returns         : May not return
418
#
419
 
420
sub Error
421
{
422
    _Message '(E)', @_;
423
    $ScmErrorCount++;
424
    ErrorDoExit() unless ( $ScmDelayExit );
425
}
426
 
427
#-------------------------------------------------------------------------------
428
# Function        : ReportError
429
#
430
# Description     : Like Error, but the error exit is delayed
431
#
432
# Inputs          : An array of strings to display
433
#
434
sub ReportError
435
{
436
    _Message '(E)', @_;
437
    $ScmErrorCount++;
438
}
439
 
440
#-------------------------------------------------------------------------------
441
# Function        : ErrorDoExit
442
#
443
# Description     : Will terminate the program if delayed error messages
444
#                   have been seen.
445
#
446
# Inputs          : None
447
#
448
# Returns         : Will return if no errors have been reported
449
#
450
 
451
sub ErrorDoExit
452
{
453
    if ( $ScmErrorCount )
454
    {
455
        #
456
        #   Prevent recusion.
457
        #   Kill error processing while doing error exit processing
458
        #
459
        if ( my $func = $ScmOnExit )
460
        {
461
            $ScmOnExit = undef;
462
            &$func();
463
        }
261 dpurdie 464
        exit $ScmExitCode;
227 dpurdie 465
    }
466
}
467
 
468
#-------------------------------------------------------------------------------
263 dpurdie 469
# Function        : ArgsToString
470
#
471
# Description     : Convert an array of arguments to a string
472
#                   Main purpose is to allow Debug and Verbose
473
#                   calls to pass undef values without causing warnings
474
#
475
# Inputs          : REF to a list of scalar values
476
#                   Passing a REF is faster
477
#
478
# Returns         : A string
479
#
480
sub ArgsToString
481
{
482
    my $result = '';
483
 
484
    $result .= (defined ($_) ? $_ : '\'undef\'') . ' ' foreach  ( @{$_[0]} );
485
    return $result;
486
}
487
 
488
#-------------------------------------------------------------------------------
489
# Function        : Verbose0
490
#                   Verbose
227 dpurdie 491
#                   Verbose2
492
#                   Verbose3
493
#
494
# Description     : Various levels of progress reporting
495
#                   By default none are displayed
496
#
497
# Inputs          : A single line string
498
#                   Multi-line output is not supported
263 dpurdie 499
#                   Arguments will be processed such that undef is handled well
227 dpurdie 500
#
263 dpurdie 501
sub Verbose0
502
{
503
    _Message '------', ArgsToString (\@_);
504
}
227 dpurdie 505
sub Verbose
506
{
263 dpurdie 507
    _Message '(V)', ArgsToString (\@_) if ($::ScmVerbose);
227 dpurdie 508
}
509
 
510
sub Verbose2
511
{
263 dpurdie 512
    _Message '(V)', ArgsToString (\@_) if ($::ScmVerbose >= 2);
227 dpurdie 513
}
514
 
515
sub Verbose3
516
{
263 dpurdie 517
    _Message '(V)', ArgsToString (\@_) if ($::ScmVerbose >= 3);
227 dpurdie 518
}
519
 
520
sub IsVerbose
521
{
522
    my( $level) = @_;
523
    return $::ScmVerbose >= $level;
524
}
525
 
526
#-------------------------------------------------------------------------------
527
# Function        : Debug
528
#                   Debug0
529
#                   Debug1
530
#                   Debug2
531
#                   Debug3
532
#
533
# Description     : Various levels of debug reporting
534
#                   By default none are displayed
535
#
536
# Inputs          : A single line string
537
#                   Multi-line output is not supported
263 dpurdie 538
#                   Arguments will be processed such that undef is handled well
227 dpurdie 539
#
540
sub Debug0
541
{
263 dpurdie 542
    _Message '------', ArgsToString (\@_);
227 dpurdie 543
}
544
 
545
sub Debug
546
{
263 dpurdie 547
    _Message '(D)', ArgsToString (\@_) if ($::ScmDebug >= 1 ) ;
227 dpurdie 548
}
549
 
550
 
551
sub Debug2
552
{
263 dpurdie 553
    _Message '(D)', ArgsToString (\@_) if ($::ScmDebug >= 2) ;
227 dpurdie 554
}
555
 
556
 
557
sub Debug3
558
{
263 dpurdie 559
    _Message '(D)', ArgsToString (\@_) if ($::ScmDebug >= 3) ;
227 dpurdie 560
}
561
 
562
sub IsDebug
563
{
564
    my( $level) = @_;
565
    return $::ScmDebug >= $level;
566
}
567
 
568
#-------------------------------------------------------------------------------
569
# Function        : DebugDumpData
570
#
571
# Description     : Dump a data structure
572
#
573
# Inputs          : $name           - A name to give the structure
574
#                   @refp           - An array of references
575
#
576
# Returns         :
577
#
578
sub DebugDumpData
579
{
580
    my ($name, @refp) = @_;
581
 
582
    my $ii = 0;
583
    foreach  ( @refp )
584
    {
585
        print Data::Dumper->Dump ( [$_], ["*[Arg:$ii] $name" ]);
586
        $ii++
587
    }
588
}
589
 
590
#-------------------------------------------------------------------------------
231 dpurdie 591
# Function        : DebugTraceBack
592
#
593
# Description     : Display the call stack
594
#
595
# Inputs          : $tag
596
#
597
# Returns         : Nothing
598
#
599
sub DebugTraceBack
600
{
601
    my ($tag) = @_;
602
    $tag = 'TraceBack' unless ( $tag );
603
 
604
    #
605
    #   Limit the stack stace.
606
    #   It can't go on forever
607
    #
608
    foreach my $ii ( 0 .. 20 )
609
    {
610
         my ($package, $filename, $line) = caller($ii);
611
         last unless ( $package );
612
         print "$tag: $ii: $package, $filename, $line\n";
613
    }
614
}
615
 
616
#-------------------------------------------------------------------------------
227 dpurdie 617
# Function        : DebugPush
618
#
619
# Description     : Save the current debug level and then use a new name and
620
#                   debug level for future reporting
621
#
622
# Inputs          : $name       - Nwe program name
623
#                   $level      - New program debug level
624
#
625
# Returns         : Current debug level
626
#
627
 
628
my @DebugStack = ();
629
sub DebugPush
630
{
631
    my ($name, $new_level) = @_;
632
 
633
    push @DebugStack, $::ScmDebug;
634
    push @DebugStack, $::ScmWho;
635
 
636
    $::ScmDebug = $new_level if ( defined $new_level && $new_level );
637
    $::ScmWho =   $name      if ( defined $name && $name );
638
 
639
    return $::ScmDebug;
640
}
641
 
642
#-------------------------------------------------------------------------------
643
# Function        : DebugPop
644
#
645
# Description     : Restores the operation of the DebugPush
646
#
647
# Inputs          : None
648
#
649
sub DebugPop
650
{
651
    $::ScmWho   = pop @DebugStack;
652
    $::ScmDebug = pop @DebugStack;
653
}
654
 
655
#-------------------------------------------------------------------------------
656
# Function        : DebugDumpPackage
657
#
658
# Description     : Dump data within the scope of a given package
659
#
660
# Inputs          : $packageName            - To dump
661
#
662
# Returns         : 
663
#
664
 
665
sub DebugDumpPackage
666
{
667
    no strict "vars";
668
    no strict "refs";
669
    my ($packageName) = @_;
670
    print "==DebugDumpPackage: $packageName =============================\n";
671
 
672
 
673
    local (*alias);             # a local typeglob
674
    local $Data::Dumper::Pad = "\t ";
675
    local $Data::Dumper::Maxdepth = 2;
676
    local $Data::Dumper::Indent  = 1;
677
 
678
    # We want to get access to the stash corresponding to the package name
679
 
680
    *stash = *{"${packageName}::"};  # Now %stash is the symbol table
681
#    $, = " ";                        # Output separator for print
682
    # Iterate through the symbol table, which contains glob values
683
    # indexed by symbol names.
684
    while (my ($varName, $globValue) = each %stash)
685
    {
686
        print "$varName =============================\n";
687
        next if ( $varName eq 'stash' );
688
        *alias = $globValue;
689
        if (defined ($alias)) {
690
            print Data::Dumper->Dump ( [$alias], ["*$varName" ]);
691
#            print "\t \$$varName $alias \n";
692
        } 
693
        if (defined (@alias)) {
694
            print Data::Dumper->Dump ( [\@alias], ["*$varName" ]);
695
#            print "\t \@$varName @alias \n";
696
        } 
697
        if (defined (%alias)) {
698
            print Data::Dumper->Dump ( [\%alias], ["*$varName" ]);
699
#            print "\t \%$varName ",%alias," \n";
700
        }
701
        if (defined (&alias)) {
702
#            print Data::Dumper->Dump ( [\&alias], ["*$varName" ]);
703
            print "\t \&$varName ","Code Fragment"," \n";
704
        }
705
     }
706
}
707
 
708
#
709
#
710
1;