This file is indexed.

/usr/share/perl5/Carp/Datum/Cfg.pm is in libcarp-datum-perl 1:0.1.3-8.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
# -*- Mode: perl -*-
#
# $Id: Cfg.pm,v 0.1.1.1 2001/07/13 17:05:28 ram Exp $
#
#  Copyright (c) 2000-2001, Christophe Dehaudt & Raphael Manfredi
#  
#  You may redistribute only under the terms of the Artistic License,
#  as specified in the README file that comes with the distribution.
#
# HISTORY
# $Log: Cfg.pm,v $
# Revision 0.1.1.1  2001/07/13 17:05:28  ram
# patch2: random cleanup (from CDE)
#
# Revision 0.1  2001/03/31 10:04:36  ram
# Baseline for first Alpha release.
#
# $EndLog$
#

use strict;

package Carp::Datum::Cfg;

use Carp::Datum::Flags;

use Getargs::Long qw(ignorecase);

require Exporter;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = (qw(
              ),
           @Carp::Datum::Flags::EXPORT);

use vars qw($DEBUG_TABLE);

#
# Structure of the hash ref that is returned by the parser:
#
# FLAG_SETTING:
# { debug => [ DTM_SET, DTM_CLEAR ],
#   trace => [ DTM_SET, DTM_CLEAR ],
#   args  => VAL
# }
#
# debug and trace correspond to a two values array. First value is the
# set mask and the second is the clear one.
#
# args indicates the maximum number of arguments that is printed
# during the tracing of the flow. -1 means all arguments.
#
#
# DEBUG_TABLE:
# { default   => FLAG_SETTING,
#
#   routine   => { "routine_name1" => FLAG_SETTING,
#                  "routine_name2" => FLAG_SETTING,
#                  ....
#                },
#
#   file      => { flags     => { "path1" => FLAG_SETTING,
#                                 "path2" => FLAG_SETTING,
#                                 ....
#                               },
#                  routine   => { "routine_name1" => FLAG_SETTING,
#                                 "routine_name2" => FLAG_SETTING,
#                                 ....
#                               }
#                },
#
#   type      => { flags     => { "type1" => FLAG_SETTING,
#                                 "type2" => FLAG_SETTING,
#                                 ....
#                               },
#                  routine   => { "routine_name1" => FLAG_SETTING,
#                                 "routine_name2" => FLAG_SETTING,
#                                 ....
#                               }
#                },
#
#   alias     => [ [ "path1", "alias1" ],
#                  [ "path2", "alias2" ],
#                  ....
#                ],
#
#   define    => { "name1" => FLAG_SETTING,
#                  "name2" => FLAG_SETTING,
#                  ....
#                }
# }
#
#   



# default debug table
$DEBUG_TABLE = {default => { debug => [DBG_ALL, 0],
                             trace => [TRC_ALL, 0],
                             args => -1
                           },
                alias => []
               };

#
# ->make
#
#
# Arguments:
#   -file     => $filename: file to load [optionnal]
#   -config   => $string: string which contains config set up [optionnal]
#
sub make {
    my $self = bless {}, shift;
    my ($filename, $raw_config) = cgetargs(@_, [qw(file config)]);

    $self->{cfg_table} = $DEBUG_TABLE;
	local $_ = '';
    
    if (defined $filename && open(XFILE, $filename)) {
        
        $_ = "\n" . join('', <XFILE>);
        die $@ if $@;
        close XFILE;
    }

    if (defined $raw_config) {
        $_ .= "\n" . $raw_config;
        $filename .= " + " if defined $filename;
        $filename .= "'RAW DATA CONFIGURATION'";
    }

    # to prevent the parsing when the given parameter is a fake
    # filename, there is a test on the string to parse. It must
    # contain a blank character to possibly be parsed. A non existing
    # path will not contain this character.
    if (/\s/) {
        # use the parser to populate the debug tree structure
        my $p = Carp::Datum::Parser->new(\&Carp::Datum::Parser::yylex,
                                          \&Carp::Datum::Parser::yyerror, 0);
        $p->init_parser($filename);
        my $result = $p->yyparse();
        
        # add the default values to the result if they have not been
        # set during the parsing
        while (my ($k, $v) = each %$DEBUG_TABLE) {
            $result->{$k} = $v unless defined $result->{$k};
        }
        
        $self->{cfg_table} = $result;
    }

    # separate the result in different attibutes to speed-up the
    # processing (one dereference is saved). That is also beautifying
    # the code.
    $self->{cfg_file} = $self->cfg_table->{file};
    $self->{cfg_routine} = $self->cfg_table->{routine};
    $self->{cfg_cluster} = $self->cfg_table->{cluster};
    $self->{cfg_type} = $self->cfg_table->{type};
    $self->{cfg_alias} = $self->cfg_table->{alias};

    return $self;
}


#########################################################################
# Internal Attribute Access: these methods are not intended to be used  #
# from the external of the object.                                      #
#########################################################################

sub cfg_table    {$_[0]->{cfg_table}}
sub cfg_alias    {$_[0]->{cfg_alias}}

#
# ->basename
#
sub basename {
    my $name = shift;
    my $result = $name;

    if ($name =~ /\//) {
        ($result) = $name =~ /.*\/(\S+)/;
    }
    return $result;
}


#
# ->add_flag
#
# static class function that is used by the flag routine when additive
# method is requested for flag computation.
#
# Arguments:
#   $old: old value,
#   $new: new value (can be undef or null)
#
# Returns:
#   the clear bits of new are cleared on old and set bits of new are
#   set on old.
#
sub add_flag {
    my ($old, $new) = @_;

    if (defined $new && $new != 0) {
        return $old & ~$new->[DTM_CLEAR] | $new->[DTM_SET];
    }
    return $old;
}

#
# ->add_args
#
# static class function that is used by the flag routine when replacing
# method is requested for flag computation.
#
# Arguments:
#   $old: old value,
#   $new: new value (can be undef or null)
#
# Returns:
#   the new value if defined
#
sub add_args {
    my ($old, $new) = @_;

    return $old unless defined $new;
    return $new;
}

#########################################################################
# Class Feature: usable from the external world                         #
#########################################################################


#
# ->check_debug
#
# return true when the given mask matches the flag setting for debug
# mode
#
# Arguments:
#   $mask: bit field that is compared to the setting.
#
#   $caller_penalty: [optional] allows to provide a penalty used to
#   determine the function features (via caller()) that is used to get
#   the configuration setting. When not specified or 0, the call level
#   right above the function that call the check_debug (2 steps from
#   here) will be used.
#
# Returns:
#   a boolean value.
#
sub check_debug {
    return $_[0]->flag('debug', @_ == 3 ? ($_[2]+1) : 1) & $_[1];
}

#
# ->check_trace
#
# return true when the given mask matches the flag setting for trace
# mode
#
# Arguments:
#   $mask: bit field that is compared to the setting.
#
#   $caller_penalty: [optional] allows to provide a penalty used to
#   determine the function features (via caller()) that is used to get
#   the configuration setting. When not specified or 0, the call level
#   right above the function that call the check_trace (2 steps from
#   here) will be used.
#
# Returns:
#   a boolean value.
#
sub check_trace {
    return $_[0]->flag('trace', @_ == 3 ? ($_[2]+1) : 1) & $_[1];
}


#
# ->flag
#
# Perform a walkthrough the different level of configuration setting
# and and gets a (additive | replacing) value for the result computation.
#
# When requesting the flag for 'debug' or 'trace', each stage value is
# added.  For 'args' request, each value overwrites the previous one.
#
# The walkthrough is perfomed in the following order:
#    - default
#    - file
#    - routine
#    - routine for file
#    - type
#    - routine for type
# 
# Arguments:
#   $field: string that indicates the key that is used during the
#   walkthrough. It is either 'debug', 'trace' or 'args'.
#
#   $caller_penalty: [optional] allows to provide a penalty used to
#   determine the function features (via caller()) that is used to get
#   the configuration setting. When not specified or 0, the call level
#   right above the function that call the check_trace (2 steps from
#   here) will be used.
#
# Returns:
#   a value that depends from the $field request:
#       for 'debug' and 'trace': it represents a bit field.
#       for 'args': it is an integer..
#
sub flag {
    my $self = shift;
    my ($field, $caller_penalty) = @_;

    # get debug caller (for filename location)
    my $caller_level = defined $caller_penalty ? (1 + $caller_penalty) : 1;
    my ($package, $filename, $line1) = caller($caller_level);

    # get debug caller (for routine name)
    package DB;  
    use vars qw(@args); # ignore warning
    my ($package1, $filename1, $line, $subroutine,
        $hasargs, $wantarray, $evaltext, $is_require) = 
          caller($caller_level + 1);
    package Carp::Datum::Cfg;

    # the method that is gonna used to compute the different flag
    # depends of what it is looked for:
    # 'debug' or 'trace' -> flags are merged during the walkthrough
    # 'args' -> value are overwritten during the walkthough
    my $merge_routine = \&add_flag;
    $merge_routine = \&add_args if $field eq 'args';

	$subroutine = '' unless defined $subroutine;
    my ($func_name) = $subroutine =~ /.*::(\S+)/;
    my $file_routine = undef;
    my $type_routine = undef;

    # first get the default flag setting
    my $result = &$merge_routine(0, $self->cfg_table->{default}->{$field});

    # update with cluster setting
    my $cluster_cfg = $self->{cfg_cluster};
    if (defined $cluster_cfg) {
        # perhaps, the package gets directly an entry in the table
        if (defined $cluster_cfg->{$package}) {
            $result = &$merge_routine(
                $result, 
                $cluster_cfg->{$package}->{flags}->{$field}
            );
        }
        else {
            # anyway, try to find a filter matching a part of the package name
            my $tmp = $package;
            while ($tmp =~ /(.*)::/) {
                $tmp = $1;
                if (defined $cluster_cfg->{$tmp}) {
                    $result = &$merge_routine(
                        $result, 
                        $cluster_cfg->{$tmp}->{flags}->{$field}
                    );
                    last;
                }

            };
        }
    }

    # update with file specific setting (if any), trying base name second
    my $file_cfg = $self->{cfg_file}->{$filename};
    if (defined $file_cfg) {
        $result = &$merge_routine($result, $file_cfg->{flags}->{$field});
        $file_routine = $file_cfg->{routine}->{$func_name};
    }
    else {
        $file_cfg = $self->{cfg_file}->{basename($filename)};
        if (defined $file_cfg) {
            $result = &$merge_routine($result, $file_cfg->{flags}->{$field});
            $file_routine = $file_cfg->{routine}->{$func_name};
        }
    }
    
    # update with routine specific setting (if any)
    my $routine_cfg = $self->{cfg_routine}->{$func_name};
    $result = &$merge_routine($result, $routine_cfg->{flags}->{$field});
    
    # update with routine specific setting from file specification (if any)
    $result = &$merge_routine($result, $file_routine->{flags}->{$field});
    
    # update with dynamic type specific setting (if any)
    my $dyna_type = '';
    ($dyna_type) = $DB::args[0] =~ /(.*)=\w+\(.*\)/ if defined $DB::args[0];
    my $dyna_cfg = $self->{cfg_type}->{$dyna_type};
    $result = &$merge_routine($result, $dyna_cfg->{flags}->{$field});

    # update with routine specific setting from type specification (if any)
    $type_routine = $dyna_cfg->{routine}->{$func_name};
    $result = &$merge_routine($result, $type_routine->{flags}->{$field});

    return $result;
}

1;

=head1 NAME

Carp::Datum::Cfg - Dynamic Debug Configuration Setting for Datum

=head1 SYNOPSIS

 # In application's main
 use Carp::Datum qw(:all on);      # turns Datum "on" or "off"
 DLOAD_CONFIG(-file => "./debug.cf", -config => "config string");

=head1 DESCRIPTION

By using the DLOAD_CONFIG function in an application's main file, 
a debugging configuration can be dynamically loaded to define a particular
level of debug/trace flags for a specific sub-part of code.

For instance, the tracing can be turned off when entering a routine
of a designated package. That is very useful for concentrating the
debugging onto the area that is presently developed and/or to filter
some verbose parts of code (recursive function call), when they don't
need to be monitored to fix the problem.

=head1 EXAMPLE

Before the obscure explaination of the grammar, here is an example of
what can be specified by dynamic configuration:

  /* 
   * flags definition: macro that can be used in further configuration
   * settings
   */
  flags common {
      all(yes);
      trace(yes): all;
  }

  flags silent {
      all(yes);
      flow(no);
      trace(no);
      return(no);
  }

  /*
   * default setting to use when there is no specific setting 
   * for the area
   */
  default common;


  /*
   * specific settings for specific areas
   */
  routine "context", "cleanup"                 { use silent; }
  routine "validate", "is_num", "is_greater"   { use silent; }

  file "Keyed_Tree.pm"                         { use silent; }
  file "Color.pm" {
      use silent; 
      trace(yes): emergency, alert, critical;
  }

  cluster "CGI::MxScreen" {
      use silent; 
      assert(no);
      ensure(no);
  }

  /*
   * aliasing to reduce the trace output line length
   */

  alias "/home/dehaudtc/usr/perl/lib/site_perl/5.6.0/CGI" => "<PM>";

=head1 INTERFACE

The only user interface is the C<DLOAD_CONFIG> routine, which expects
the following optional named parameters:

=over 4

=item C<-config> => I<string>

Give an inlined configuration string that is appended to the one
defined by C<-file>, if any.

=item C<-file> => I<filename>

Specifies the configuration file to load to initialize the
debugging and tracing flags to be used for this run.

=back

=head1 CONFIGURATION DIRECTIVES

=head2 Main Configuration Directives

The following main directives can appear at a nesting level of 0.  The
syntax unit known as I<BLOCK> is a list of semi-colon terminated directives
held within curly braces.

=over 4

=item C<alias> I<large_path> => I<short_path>

Defines an alias to be used during tracing.  The I<large_path> string
is replaced by the I<short_path> in the logs.

For instance, given:

  alias "/home/dehaudtc/lib/CGI" => "<CGI>";

then a trace for file C</home/dehaudtc/lib/CGI/Carp.pm> would be
traced as coming from file C<E<lt>CGIE<gt>/Carp.pm>, which is nicer to read.

=item C<cluster> I<name1>, I<name2> I<BLOCK>

The I<BLOCK> defines the flags to be applied to all named clusters.
A cluster is a set of classes under a given name scope.
Cluster names are given by strings within double quotes, as in:

    cluster "CGI::MxScreen", "Net::MsgLink" { use silent; }

This would apply to all classes under the "CGI::MxScreen" or "Net::MsgLink"
name scopes, i.e. C<CGI::MxScreen::Screen> would be affected.

An exact match is attempted first, i.e. saying:

    cluster "CGI::MxScreen"         { use verbose; }
    cluster "CGI::MxScreen::Screen" { use silent; }

would apply the I<silent> flags for C<CGI::MxScreen::Screen> but the I<verbose>
ones to C<CGI::MxScreen::Tie::Stdout>.

=item C<default> I<name>|I<BLOCK>.

Specifies the default flags that should apply.  The default flags can be
given by providing the I<name> of flags, defined by the C<flags> directive,
or by expansing them in the following I<BLOCK>.

For instance:

    default silent;

would say that the flags to apply by default are the ones defined by an
earlier C<flags silent> directive.  Not expanding defaults allows for
quick switching by replacing I<silent> with I<verbose>.  It is up to the
module user to define what is meant by that though.

=item C<file> I<name1>, I<name2> I<BLOCK>

The I<BLOCK> defines the flags to be applied to all named files.
File names are given by strings withing double quotes, as in:

    file "foo.pm", "bar.pm" { use silent; }

This would apply to all files named "foo.pm" or "bar.pm", whatever their
directory, i.e. it would apply to C</tmp/foo.pm> as well as C<../bar.pm>.

An exact match is attempted first, i.e. saying:

    file "foo.pm"      { use verbose; }
    file "/tmp/foo.pm" { use silent; }

would apply the I<silent> flags for C</tmp/foo.pm> but the I<verbose>
ones to C<./foo.pm>.

=item C<flags> I<name> I<BLOCK>

Define a symbol I<name> whose flags are described by the following I<BLOCK>.
This I<name> can then be used in C<default> and C<use> directives.

For instance:

    flags common {
        all(yes);
        trace(yes): all;
    }

would define the flags known as I<common>, which can then be re-used, as in:

    flags other {
        use common;         # reuses definiton of common flags
        panic(no);          # but switches off panic, enabled in common
    }

A flag symbol must be defined prior being used.

=item C<routine> I<name1>, I<name2> I<BLOCK>

The I<BLOCK> defines the flags to be applied to all named routines.
Routine names are given by strings within double quotes, as in:

    routine "foo", "bar" { use silent; }

This would apply to all routines named "foo" or "bar", whatever their package,
for instance C<main::foo> and C<x::bar>.

=back

=head2 Debugging and Tracing Flags

Debugging (and tracing) flags can be specified only within syntactic I<BLOCK>
items, as expected by main directives such as C<flags> or C<file>.

Following is a list of debugging flags that can be specified in the
configuration.  The order in which they are given in the file is significant:
the I<yes>/I<no> settings are applied sequentially.

=over 4

=item C<use> I<name>

Uses flags defined by a C<flags> directive under I<name>.  It acts as a
recursive macro expansion (since C<use> can also be specified in C<flags>).
The symbol I<name> must have been defined earlier.

=item flow(yes|no)

Whether to print out the entering/exiting of routines. That implies the
invocation of the C<DFEATURE> function in the routines.

=item return(yes|no)

Whether to print out the returned when using the return
C<DVAL> and C<DARY> routines.

=item trace(yes|no)

Whether to print out traces specified by the C<DTRACE> function. By 
default all trace levels are affected.  It may be followed by a list
of trace levels affected by the directive, as in.

    trace(yes): emergency, alert, critical;

Trace levels are purely conventional, and have a strict one-to-one mapping
with C<DTM_TRC_> levels given at the C<DTRACE> call.  They are further
described in L<Trace Levels> below.  There is one bit per defined trace
level, contrary to the convention established by syslog(), for better
tuning.

=item require(yes|no)

Whether to evaluate the pre-condition given by C<DREQUIRE>.  But see
L<Assertion Evaluation Note> below.

=item assert(yes|no)

Whether to evaluate the assertion given by C<DASSERT>.  But see
L<Assertion Evaluation Note> below.

=item ensure(yes|no)

Whether to evaluate the post-condition given by C<DENSURE>.  But see
L<Assertion Evaluation Note> below.

=item panic(yes|no)

Whether to panic upon an assertion failure (pre/post condition or 
assertion).  If not enabled, a simple warning is issued, tracing the
assertion failure.

=item stack(yes|no)

Whether to print out a stack trace upon assertion failure.

=item all(yes|no)

Enable or disables B<all> the previously described items.

=back

=head2 Assertion Evaluation Note

When C<Carp::Datum> is switched off, the assertions are always monitored,
and any failure is fatal.  This is because a failing assertion is a Bad Thing
in production mode. Also, since C<DREQUIRE> and friends are not
C macros but routines, the assertion expression is evaluated anyway, so
it might as well be tested.

Therefore, a directive like:

    require(no);

will only turn off monitoring of pre-conditions in debugging mode (e.g. because
the interface is not finalized, or the clients do not behave properly yet).

=head2 Trace Levels

Here is the list of trace flags that can be specified by the configuration:

    Configuration    DTRACE flag
    -------------    -------------
              all    TRC_ALL
        emergency    TRC_EMERGENCY
            alert    TRC_ALERT
         critical    TRC_CRITICAL
            error    TRC_ERROR
          warning    TRC_WARNING
           notice    TRC_NOTICE
             info    TRC_INFO
            debug    TRC_DEBUG

A user could say something like:

    trace(no): all;
    trace(yes): emergency, alert, critical, error;

Since flags are applied in sequence, the first directive turns all tracing
flags to off, the second enables only the listed ones.

=head1 BUGS

Some things are not fully documented.

=head1 AUTHORS

Christophe Dehaudt and Raphael Manfredi are the original authors.

Send bug reports, hints, tips, suggestions to Dave Hoover at <squirrel@cpan.org>.

=head1 SEE ALSO

Log::Agent(3).

=cut