Subversion Repositories DevTools

Rev

Rev 231 | Go to most recent revision | Details | 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
 
25
require 5.6.1;
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
59
                      DebugDumpData DebugDumpPackage
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
    #
263
    #   Kill the eol if the Question is being asked
264
    #
265
    my $eol = ( $tag =~ m/Q/ ) ? "" : "\n";
266
 
267
    foreach my $nextline ( @_ )
268
    {
269
        chomp( my $line = $nextline );
270
        if ( $count eq 1 )
271
        {
272
            my $bol = $eol ? "" : "\n";
273
            $prefix = $bol . ' ' x length($prefix);
274
        }
275
 
276
        print "$prefix $line$eol";
277
        $count++;
278
    }
279
}
280
 
281
#-------------------------------------------------------------------------------
282
# Function        : Information
283
#                   Information1
284
#
285
# Description     : Will display informational messages
286
#                   These are normal operational messages. These may be
287
#                   supressed through the use of QUIET options
288
#
289
# Inputs          : An array of strings to display
290
#
291
sub Information
292
{
293
    _Message '(I)', @_ unless ( $::ScmQuiet);
294
}
295
 
296
sub Information1
297
{
298
    _Message '(I)', @_ unless ( $::ScmQuiet > 1);
299
}
300
 
301
 
302
#-------------------------------------------------------------------------------
303
# Function        : Message
304
#                   Message1
305
#
306
# Description     : Same as Information, except a different prefix
307
#
308
# Inputs          : An array of strings to display
309
#
310
sub Message
311
{
312
    _Message '(M)', @_ unless ( $::ScmQuiet > 1);
313
}
314
 
315
sub Message1
316
{
317
    _Message '(M)', @_ unless ( $::ScmQuiet);
318
}
319
 
320
#-------------------------------------------------------------------------------
321
# Function        : IsQuiet
322
#
323
# Description     : Determine if an Infrmation or Message will be displayed
324
#                   May be used to reduce excessive processing that may be
325
#                   discarded
326
#
327
# Inputs          : $level      - Level to test
328
#
329
# Returns         : TRUE:       A Message at $level would be displayed
330
#
331
sub IsQuiet
332
{
333
    my( $level) = @_;
334
    return $::ScmQuiet >= $level;
335
}
336
 
337
#-------------------------------------------------------------------------------
338
# Function        : Warning
339
#
340
# Description     : Display a warning message
341
#                   These may be disabled with a high quiet level
342
#
343
# Inputs          : An array of strings to display
344
#
345
sub Warning
346
{
347
    _Message '(W)', @_ unless ( $::ScmQuiet > 2);
348
}
349
 
350
#-------------------------------------------------------------------------------
351
# Function        : Question
352
#
353
# Description     : Display a Question message
354
#                   These cannot be disabled
355
#
356
# Inputs          : An array of strings to display
357
#
358
sub Question
359
{
360
    _Message '(Q)', @_;
361
    STDERR->flush;              # Force output to be displayed
362
    STDOUT->flush;              # Force output to be displayed
363
}
364
 
365
#-------------------------------------------------------------------------------
366
# Function        : Error
367
#
368
# Description     : Display a multiline error message
369
#                   This may cause the program to exit, or the user may have
370
#                   configured the package to accumulate error messages
371
#
372
#                   This could be used to generate multiple error messages
373
#                   while parsing a file, and then terminate program execution at
374
#                   the end of the phase.
375
#
376
# Inputs          : An array of strings to display
377
#
378
# Returns         : May not return
379
#
380
 
381
sub Error
382
{
383
    _Message '(E)', @_;
384
    $ScmErrorCount++;
385
    ErrorDoExit() unless ( $ScmDelayExit );
386
}
387
 
388
#-------------------------------------------------------------------------------
389
# Function        : ReportError
390
#
391
# Description     : Like Error, but the error exit is delayed
392
#
393
# Inputs          : An array of strings to display
394
#
395
sub ReportError
396
{
397
    _Message '(E)', @_;
398
    $ScmErrorCount++;
399
}
400
 
401
#-------------------------------------------------------------------------------
402
# Function        : ErrorDoExit
403
#
404
# Description     : Will terminate the program if delayed error messages
405
#                   have been seen.
406
#
407
# Inputs          : None
408
#
409
# Returns         : Will return if no errors have been reported
410
#
411
 
412
sub ErrorDoExit
413
{
414
    if ( $ScmErrorCount )
415
    {
416
        #
417
        #   Prevent recusion.
418
        #   Kill error processing while doing error exit processing
419
        #
420
        if ( my $func = $ScmOnExit )
421
        {
422
            $ScmOnExit = undef;
423
            &$func();
424
        }
425
        exit 1;
426
    }
427
}
428
 
429
#-------------------------------------------------------------------------------
430
# Function        : Verbose
431
#                   Verbose2
432
#                   Verbose3
433
#
434
# Description     : Various levels of progress reporting
435
#                   By default none are displayed
436
#
437
# Inputs          : A single line string
438
#                   Multi-line output is not supported
439
#
440
sub Verbose
441
{
442
    _Message '(V)', "@_" if ($::ScmVerbose);
443
}
444
 
445
sub Verbose2
446
{
447
    _Message '(V)', "@_" if ($::ScmVerbose >= 2);
448
}
449
 
450
sub Verbose3
451
{
452
    _Message '(V)', "@_" if ($::ScmVerbose >= 3);
453
}
454
 
455
sub IsVerbose
456
{
457
    my( $level) = @_;
458
    return $::ScmVerbose >= $level;
459
}
460
 
461
#-------------------------------------------------------------------------------
462
# Function        : Debug
463
#                   Debug0
464
#                   Debug1
465
#                   Debug2
466
#                   Debug3
467
#
468
# Description     : Various levels of debug reporting
469
#                   By default none are displayed
470
#
471
# Inputs          : A single line string
472
#                   Multi-line output is not supported
473
#
474
sub Debug0
475
{
476
    _Message '------', "@_";
477
}
478
 
479
sub Debug
480
{
481
    _Message '(D)', "@_" if ($::ScmDebug >= 1) ;
482
}
483
 
484
 
485
sub Debug2
486
{
487
    _Message '(D)', "@_" if ($::ScmDebug >= 2) ;
488
}
489
 
490
 
491
sub Debug3
492
{
493
    _Message '(D)', "@_" if ($::ScmDebug >= 3) ;
494
}
495
 
496
sub IsDebug
497
{
498
    my( $level) = @_;
499
    return $::ScmDebug >= $level;
500
}
501
 
502
#-------------------------------------------------------------------------------
503
# Function        : DebugDumpData
504
#
505
# Description     : Dump a data structure
506
#
507
# Inputs          : $name           - A name to give the structure
508
#                   @refp           - An array of references
509
#
510
# Returns         :
511
#
512
sub DebugDumpData
513
{
514
    my ($name, @refp) = @_;
515
 
516
    my $ii = 0;
517
    foreach  ( @refp )
518
    {
519
        print Data::Dumper->Dump ( [$_], ["*[Arg:$ii] $name" ]);
520
        $ii++
521
    }
522
}
523
 
524
#-------------------------------------------------------------------------------
525
# Function        : DebugPush
526
#
527
# Description     : Save the current debug level and then use a new name and
528
#                   debug level for future reporting
529
#
530
# Inputs          : $name       - Nwe program name
531
#                   $level      - New program debug level
532
#
533
# Returns         : Current debug level
534
#
535
 
536
my @DebugStack = ();
537
sub DebugPush
538
{
539
    my ($name, $new_level) = @_;
540
 
541
    push @DebugStack, $::ScmDebug;
542
    push @DebugStack, $::ScmWho;
543
 
544
    $::ScmDebug = $new_level if ( defined $new_level && $new_level );
545
    $::ScmWho =   $name      if ( defined $name && $name );
546
 
547
    return $::ScmDebug;
548
}
549
 
550
#-------------------------------------------------------------------------------
551
# Function        : DebugPop
552
#
553
# Description     : Restores the operation of the DebugPush
554
#
555
# Inputs          : None
556
#
557
sub DebugPop
558
{
559
    $::ScmWho   = pop @DebugStack;
560
    $::ScmDebug = pop @DebugStack;
561
}
562
 
563
#-------------------------------------------------------------------------------
564
# Function        : DebugDumpPackage
565
#
566
# Description     : Dump data within the scope of a given package
567
#
568
# Inputs          : $packageName            - To dump
569
#
570
# Returns         : 
571
#
572
 
573
sub DebugDumpPackage
574
{
575
    no strict "vars";
576
    no strict "refs";
577
    my ($packageName) = @_;
578
    print "==DebugDumpPackage: $packageName =============================\n";
579
 
580
 
581
    local (*alias);             # a local typeglob
582
    local $Data::Dumper::Pad = "\t ";
583
    local $Data::Dumper::Maxdepth = 2;
584
    local $Data::Dumper::Indent  = 1;
585
 
586
    # We want to get access to the stash corresponding to the package name
587
 
588
    *stash = *{"${packageName}::"};  # Now %stash is the symbol table
589
#    $, = " ";                        # Output separator for print
590
    # Iterate through the symbol table, which contains glob values
591
    # indexed by symbol names.
592
    while (my ($varName, $globValue) = each %stash)
593
    {
594
        print "$varName =============================\n";
595
        next if ( $varName eq 'stash' );
596
        *alias = $globValue;
597
        if (defined ($alias)) {
598
            print Data::Dumper->Dump ( [$alias], ["*$varName" ]);
599
#            print "\t \$$varName $alias \n";
600
        } 
601
        if (defined (@alias)) {
602
            print Data::Dumper->Dump ( [\@alias], ["*$varName" ]);
603
#            print "\t \@$varName @alias \n";
604
        } 
605
        if (defined (%alias)) {
606
            print Data::Dumper->Dump ( [\%alias], ["*$varName" ]);
607
#            print "\t \%$varName ",%alias," \n";
608
        }
609
        if (defined (&alias)) {
610
#            print Data::Dumper->Dump ( [\&alias], ["*$varName" ]);
611
            print "\t \&$varName ","Code Fragment"," \n";
612
        }
613
     }
614
}
615
 
616
#
617
#
618
1;