Subversion Repositories DevTools

Rev

Rev 231 | Rev 261 | 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
52
                      ReportError Error Warning
53
                      Message Message1
54
                      Information Information1
55
                      Question
56
                      Verbose Verbose2 Verbose3
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
    #
72
    $::ScmWho = ''      unless defined( $::ScmWho );
73
    $::ScmVerbose = 0   unless defined( $::ScmVerbose );
74
    $::ScmDebug = 0     unless defined( $::ScmDebug );
75
    $::ScmQuiet = 0     unless defined( $::ScmQuiet );
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;
94
 
95
# non-exported package globals go here
96
$ScmErrorCount = 0;
97
 
98
#  initialize package globals, first exported ones
99
 
100
 
101
#-------------------------------------------------------------------------------
102
# Function        : import
103
#
104
# Description     : Package import function
105
#                   This function will examine argumenst provided in the
106
#                   invoking 'uses' list and will configure the package
107
#                   accordingly.
108
#
109
# Inputs          : $pack           - Name of this package
110
#                   @vars           - User Config Options
111
#                   Config Options:
112
#                       :name=xxxx
113
#                       :quiet=xxx
114
#                       :debug=xxx
115
#                       :verbose=xxx
116
#                       :delay_exit=xxx
117
#
118
# Returns         : 
119
#
120
sub import {
121
    my $pack = shift;
122
    my @vars;
123
    my @config;
124
 
125
    #
126
    #   Extract options of the form: :name=value and pass them to the
127
    #   ErrorConfig function. All other arguments will be passed to the
128
    #
129
    foreach ( @_ )
130
    {
131
        if ( m/^:(.+)=(.+)/ ) {
132
            push @config, $1, $2;
133
        } else {
134
            push @vars, $_;
135
        }
136
    }
137
 
138
    ErrorConfig( @config )
139
        if ( @config );
140
 
141
    #
142
    #   Invoke Exporter function to handle the arguments that I don't understand
143
    #
144
    $pack->export_to_level(1, $pack , @vars);
145
}
146
 
147
#-------------------------------------------------------------------------------
148
# Function        : ErrorConfig
149
#
150
# Description     : Configure aspects of the JATS error handle
151
#
152
# Inputs          : A hash of option,value pairs
153
#                   Valid options
154
#                       name        - Name to report in error
155
#                       verbose     - vebosity level
156
#                       debug       - debug level
157
#                       on_exit     - Register on-exit function
158
#                       delay_exit  - Delay exit on error
159
#
160
# Returns         :
161
#
162
sub ErrorConfig
163
{
164
    my %args = @_;
165
    my $name;
166
 
167
    while (my($key, $value) = each %args)
168
    {
169
        if (       $key =~ /^name/ ) {
170
            $::ScmWho = "[$value] ";
171
            $name = $value;
172
 
173
        } elsif ( $key =~ /^debug/ ) {
174
            $::ScmDebug = $value || 0;
175
 
176
        } elsif ( $key =~ /^verbose/ ) {
177
            $::ScmVerbose = $value || 0;
178
 
179
        } elsif ( $key =~ /^quiet/ ) {
180
            $::ScmQuiet = $value || 0;
181
 
182
        } elsif ( $key =~ /^on_exit/ ) {
183
            $ScmOnExit = $value;
184
 
185
        } elsif ( $key =~ /^delay_exit/ ) {
186
            $ScmDelayExit = $value;
187
 
188
        } else {
189
            Error("ErrorConfig, Unknown option: $key");
190
        }
191
    }
192
 
193
    #
194
    #   Extract program specfic debug flags from the environment
195
    #   These will be based on the reporting 'name'
196
    #       GBE_name_DEBUG
197
    #       GBE_name_VERBOSE
198
    #
199
    if ( $name )
200
    {
201
        my ($value, $tag);
202
 
203
        $tag = "GBE_${name}_DEBUG" ;
204
        $value = $ENV{ $tag };
205
        if (defined $value)
206
        {
207
            $::ScmDebug = $value;
208
            Warning("Envar: $tag setting debug: $value");
209
        }
210
 
211
        $tag = "GBE_${name}_VERBOSE" ;
212
        $value = $ENV{ $tag };
213
        if (defined $value)
214
        {
215
            $::ScmVerbose = $value;
216
            Warning("Envar: $tag setting verbose: $value");
217
        }
218
    }
219
 
220
    #
221
    #   Sanitise quiet and verbose
222
    #   Any verboseness disables quiet
223
    #
224
    $::ScmQuiet = 0 if ( $::ScmVerbose );
225
    $::ScmQuiet = 0 if ( $::ScmDebug );
226
}
227
 
228
 
229
#-------------------------------------------------------------------------------
230
# Function        : Information
231
#                   Message
232
#                   Question
233
#                   Warning
234
#                   Error
235
#                   Verbose
236
#                   Debug
237
#                   _Message ( Internal use only )
238
#
239
# Description     : Error, Warning and Message routines
240
#                   These routines will display a message to the user
241
#                   with the module name.
242
#
243
#                   Multiple arguments are displayed on their own line
244
#                   with suitable spacing.
245
#
246
# Inputs          : Lines of text to display
247
#
248
# Returns         : Nothing
249
#
250
sub _Message
251
{
252
    my $tag = shift;                # First argument is a tag
253
    my $count = 0;
254
 
255
    #
256
    #   Generate the message prefix
257
    #   This will only be used on the first line
258
    #   All other lines will have a space filled prefix
259
    #
260
    my $prefix = $::ScmWho . $tag;
261
    #
262
    #   Kill the eol if the Question is being asked
263
    #
264
    my $eol = ( $tag =~ m/Q/ ) ? "" : "\n";
265
    foreach my $nextline ( @_ )
266
    {
231 dpurdie 267
        next unless ( defined $nextline );              # Ignore undefined arguments
227 dpurdie 268
        chomp( my $line = $nextline );
269
        if ( $count eq 1 )
270
        {
271
            my $bol = $eol ? "" : "\n";
272
            $prefix = $bol . ' ' x length($prefix);
273
        }
274
 
275
        print "$prefix $line$eol";
276
        $count++;
277
    }
278
}
279
 
280
#-------------------------------------------------------------------------------
281
# Function        : Information
282
#                   Information1
283
#
284
# Description     : Will display informational messages
285
#                   These are normal operational messages. These may be
286
#                   supressed through the use of QUIET options
287
#
288
# Inputs          : An array of strings to display
289
#
290
sub Information
291
{
292
    _Message '(I)', @_ unless ( $::ScmQuiet);
293
}
294
 
295
sub Information1
296
{
297
    _Message '(I)', @_ unless ( $::ScmQuiet > 1);
298
}
299
 
300
 
301
#-------------------------------------------------------------------------------
302
# Function        : Message
303
#                   Message1
304
#
305
# Description     : Same as Information, except a different prefix
306
#
307
# Inputs          : An array of strings to display
308
#
309
sub Message
310
{
311
    _Message '(M)', @_ unless ( $::ScmQuiet > 1);
312
}
313
 
314
sub Message1
315
{
316
    _Message '(M)', @_ unless ( $::ScmQuiet);
317
}
318
 
319
#-------------------------------------------------------------------------------
320
# Function        : IsQuiet
321
#
322
# Description     : Determine if an Infrmation or Message will be displayed
323
#                   May be used to reduce excessive processing that may be
324
#                   discarded
325
#
326
# Inputs          : $level      - Level to test
327
#
328
# Returns         : TRUE:       A Message at $level would be displayed
329
#
330
sub IsQuiet
331
{
332
    my( $level) = @_;
333
    return $::ScmQuiet >= $level;
334
}
335
 
336
#-------------------------------------------------------------------------------
337
# Function        : Warning
338
#
339
# Description     : Display a warning message
340
#                   These may be disabled with a high quiet level
341
#
342
# Inputs          : An array of strings to display
343
#
344
sub Warning
345
{
346
    _Message '(W)', @_ unless ( $::ScmQuiet > 2);
347
}
348
 
349
#-------------------------------------------------------------------------------
350
# Function        : Question
351
#
352
# Description     : Display a Question message
353
#                   These cannot be disabled
354
#
355
# Inputs          : An array of strings to display
356
#
357
sub Question
358
{
359
    _Message '(Q)', @_;
360
    STDERR->flush;              # Force output to be displayed
361
    STDOUT->flush;              # Force output to be displayed
362
}
363
 
364
#-------------------------------------------------------------------------------
365
# Function        : Error
366
#
367
# Description     : Display a multiline error message
368
#                   This may cause the program to exit, or the user may have
369
#                   configured the package to accumulate error messages
370
#
371
#                   This could be used to generate multiple error messages
372
#                   while parsing a file, and then terminate program execution at
373
#                   the end of the phase.
374
#
375
# Inputs          : An array of strings to display
376
#
377
# Returns         : May not return
378
#
379
 
380
sub Error
381
{
382
    _Message '(E)', @_;
383
    $ScmErrorCount++;
384
    ErrorDoExit() unless ( $ScmDelayExit );
385
}
386
 
387
#-------------------------------------------------------------------------------
388
# Function        : ReportError
389
#
390
# Description     : Like Error, but the error exit is delayed
391
#
392
# Inputs          : An array of strings to display
393
#
394
sub ReportError
395
{
396
    _Message '(E)', @_;
397
    $ScmErrorCount++;
398
}
399
 
400
#-------------------------------------------------------------------------------
401
# Function        : ErrorDoExit
402
#
403
# Description     : Will terminate the program if delayed error messages
404
#                   have been seen.
405
#
406
# Inputs          : None
407
#
408
# Returns         : Will return if no errors have been reported
409
#
410
 
411
sub ErrorDoExit
412
{
413
    if ( $ScmErrorCount )
414
    {
415
        #
416
        #   Prevent recusion.
417
        #   Kill error processing while doing error exit processing
418
        #
419
        if ( my $func = $ScmOnExit )
420
        {
421
            $ScmOnExit = undef;
422
            &$func();
423
        }
424
        exit 1;
425
    }
426
}
427
 
428
#-------------------------------------------------------------------------------
429
# Function        : Verbose
430
#                   Verbose2
431
#                   Verbose3
432
#
433
# Description     : Various levels of progress reporting
434
#                   By default none are displayed
435
#
436
# Inputs          : A single line string
437
#                   Multi-line output is not supported
438
#
439
sub Verbose
440
{
441
    _Message '(V)', "@_" if ($::ScmVerbose);
442
}
443
 
444
sub Verbose2
445
{
446
    _Message '(V)', "@_" if ($::ScmVerbose >= 2);
447
}
448
 
449
sub Verbose3
450
{
451
    _Message '(V)', "@_" if ($::ScmVerbose >= 3);
452
}
453
 
454
sub IsVerbose
455
{
456
    my( $level) = @_;
457
    return $::ScmVerbose >= $level;
458
}
459
 
460
#-------------------------------------------------------------------------------
461
# Function        : Debug
462
#                   Debug0
463
#                   Debug1
464
#                   Debug2
465
#                   Debug3
466
#
467
# Description     : Various levels of debug reporting
468
#                   By default none are displayed
469
#
470
# Inputs          : A single line string
471
#                   Multi-line output is not supported
472
#
473
sub Debug0
474
{
475
    _Message '------', "@_";
476
}
477
 
478
sub Debug
479
{
480
    _Message '(D)', "@_" if ($::ScmDebug >= 1) ;
481
}
482
 
483
 
484
sub Debug2
485
{
486
    _Message '(D)', "@_" if ($::ScmDebug >= 2) ;
487
}
488
 
489
 
490
sub Debug3
491
{
492
    _Message '(D)', "@_" if ($::ScmDebug >= 3) ;
493
}
494
 
495
sub IsDebug
496
{
497
    my( $level) = @_;
498
    return $::ScmDebug >= $level;
499
}
500
 
501
#-------------------------------------------------------------------------------
502
# Function        : DebugDumpData
503
#
504
# Description     : Dump a data structure
505
#
506
# Inputs          : $name           - A name to give the structure
507
#                   @refp           - An array of references
508
#
509
# Returns         :
510
#
511
sub DebugDumpData
512
{
513
    my ($name, @refp) = @_;
514
 
515
    my $ii = 0;
516
    foreach  ( @refp )
517
    {
518
        print Data::Dumper->Dump ( [$_], ["*[Arg:$ii] $name" ]);
519
        $ii++
520
    }
521
}
522
 
523
#-------------------------------------------------------------------------------
231 dpurdie 524
# Function        : DebugTraceBack
525
#
526
# Description     : Display the call stack
527
#
528
# Inputs          : $tag
529
#
530
# Returns         : Nothing
531
#
532
sub DebugTraceBack
533
{
534
    my ($tag) = @_;
535
    $tag = 'TraceBack' unless ( $tag );
536
 
537
    #
538
    #   Limit the stack stace.
539
    #   It can't go on forever
540
    #
541
    foreach my $ii ( 0 .. 20 )
542
    {
543
         my ($package, $filename, $line) = caller($ii);
544
         last unless ( $package );
545
         print "$tag: $ii: $package, $filename, $line\n";
546
    }
547
}
548
 
549
#-------------------------------------------------------------------------------
227 dpurdie 550
# Function        : DebugPush
551
#
552
# Description     : Save the current debug level and then use a new name and
553
#                   debug level for future reporting
554
#
555
# Inputs          : $name       - Nwe program name
556
#                   $level      - New program debug level
557
#
558
# Returns         : Current debug level
559
#
560
 
561
my @DebugStack = ();
562
sub DebugPush
563
{
564
    my ($name, $new_level) = @_;
565
 
566
    push @DebugStack, $::ScmDebug;
567
    push @DebugStack, $::ScmWho;
568
 
569
    $::ScmDebug = $new_level if ( defined $new_level && $new_level );
570
    $::ScmWho =   $name      if ( defined $name && $name );
571
 
572
    return $::ScmDebug;
573
}
574
 
575
#-------------------------------------------------------------------------------
576
# Function        : DebugPop
577
#
578
# Description     : Restores the operation of the DebugPush
579
#
580
# Inputs          : None
581
#
582
sub DebugPop
583
{
584
    $::ScmWho   = pop @DebugStack;
585
    $::ScmDebug = pop @DebugStack;
586
}
587
 
588
#-------------------------------------------------------------------------------
589
# Function        : DebugDumpPackage
590
#
591
# Description     : Dump data within the scope of a given package
592
#
593
# Inputs          : $packageName            - To dump
594
#
595
# Returns         : 
596
#
597
 
598
sub DebugDumpPackage
599
{
600
    no strict "vars";
601
    no strict "refs";
602
    my ($packageName) = @_;
603
    print "==DebugDumpPackage: $packageName =============================\n";
604
 
605
 
606
    local (*alias);             # a local typeglob
607
    local $Data::Dumper::Pad = "\t ";
608
    local $Data::Dumper::Maxdepth = 2;
609
    local $Data::Dumper::Indent  = 1;
610
 
611
    # We want to get access to the stash corresponding to the package name
612
 
613
    *stash = *{"${packageName}::"};  # Now %stash is the symbol table
614
#    $, = " ";                        # Output separator for print
615
    # Iterate through the symbol table, which contains glob values
616
    # indexed by symbol names.
617
    while (my ($varName, $globValue) = each %stash)
618
    {
619
        print "$varName =============================\n";
620
        next if ( $varName eq 'stash' );
621
        *alias = $globValue;
622
        if (defined ($alias)) {
623
            print Data::Dumper->Dump ( [$alias], ["*$varName" ]);
624
#            print "\t \$$varName $alias \n";
625
        } 
626
        if (defined (@alias)) {
627
            print Data::Dumper->Dump ( [\@alias], ["*$varName" ]);
628
#            print "\t \@$varName @alias \n";
629
        } 
630
        if (defined (%alias)) {
631
            print Data::Dumper->Dump ( [\%alias], ["*$varName" ]);
632
#            print "\t \%$varName ",%alias," \n";
633
        }
634
        if (defined (&alias)) {
635
#            print Data::Dumper->Dump ( [\&alias], ["*$varName" ]);
636
            print "\t \&$varName ","Code Fragment"," \n";
637
        }
638
     }
639
}
640
 
641
#
642
#
643
1;