File Coverage

blib/lib/Devel/DebugInit.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Devel::DebugInit;
2 2     2   3457 use English;
  2         9577  
  2         12  
3 2     2   1145 use Carp;
  2         5  
  2         157  
4 2     2   254350 use C::Scan qw(0.4);
  0            
  0            
5             require Exporter;
6              
7             @Devel::DebugInit::ISA = (Exporter);
8              
9             use strict;
10             use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $MACROS_ALL $MACROS_LOCAL $MACROS_NONE);
11              
12             # Items to export into callers namespace by default. Note: do not export
13             # names by default without a very good reason. Use EXPORT_OK instead.
14             # Do not simply export all your public functions/methods/constants.
15             @EXPORT = qw(
16            
17             );
18             $VERSION = '0.3';
19              
20             $Devel::DebugInit::MACROS_NONE = 0;
21             $Devel::DebugInit::MACROS_LOCAL = 1;
22             $Devel::DebugInit::MACROS_ALL = 2;
23              
24             =head1 NAME
25              
26             Devel::DebugInit - Perl extension for creating a debugger
27             initialization files from C header file macros
28              
29             =head1 SYNOPSIS
30              
31             use Devel::DebugInit::GDB;
32             my $gdb = new Devel::DebugInit::GDB 'filenames' => ["/my/path/to/library.h"];
33             $gdb->write("/my/path/to/library/.gdbinit");
34              
35             =head1 DESCRIPTION
36              
37             Devel::DebugInit is aimed at C/C++ developers who want access to C
38             macro definitions from within a debugger. It provides a simple and
39             automated way of creating debugger initialization files for a specific
40             project. The initialization files created contain user-defined
41             functions built from the macro definitions in the project's header
42             files.
43              
44             By calling new(), the files specified by the 'filenames' parameter are
45             parsed by the C preprocessor, and all macros #define'd in the file
46             (and if desired, all macros #define'd by all #include'd files as
47             well), will be parsed and expanded. By then calling the write()
48             method, these macros can be written to an output file in the format of
49             user-defined functions specific for your debugger.
50              
51             By automating the process, a new file can be created whenever the code
52             of a project changes, and that way there will not be antiquated copies
53             lying around to trap the unwary.
54              
55             =head1 NOTES
56              
57             This module requires the use of one of the debugger-specific backend
58             modules, such as Devel::DebugInit::GDB which is supplied with
59             DebugInit. The backends supply the output routines which are specific
60             for that debugger.
61              
62             This module also requires both the C::Scan and Data::Flow modules and
63             will not function without them.
64              
65             =head1 WHY CARE?
66              
67             Debugger initialization files can contain user-defined functions that
68             make doing complicated or repetitive actions easier. Normally, from
69             within the debugger a user can evaluate any C function call. But for a
70             number of reasons, many projects use C preprocessor macros (#define
71             statements) in place of an actual C function call. The use of macros
72             instead of function calls is transparent during compilation, but most
73             debuggers do not allow access to macros, and so the user must type in
74             the code by hand each time s/he wants to use a macro, or must build an
75             initialization file by hand. Retyping is tedious, but hand coding the
76             initialization file may result in antiquated code when the project changes. By
77             automating the process, I hope to alleviate a few headaches for
78             developers.
79              
80             There are two types of macros: macros with arguments, e.g:
81              
82             #define min(x,y) ((x) < (y) ? (x) : (y))
83              
84             and macros without arguments (simple macros), e.g.
85              
86             #define PI 3.14
87              
88             Of the two types, macros with arguments are more useful from within a
89             debugger, and so, printing of simple macros is turned off by default
90             (but see L for how to turn them on).
91              
92             =head1 INTERNALS
93              
94             For the casual user the defaults, and the three lines given in the
95             L should be enough. But for the determined user, a few
96             details of how things happen under the hood might be useful in
97             customizing the output of this module.
98              
99             =head2 How Devel::DebugInit Parses Files
100              
101             When new() is called to create an instance of a Devel::DebugInit, the
102             following steps occur. The C preprocessor is invoked on the file with
103             the 'macros only' flag set (this flag defaults to '-dM' and if this does
104             not work on your system, change the value of $C::Scan::MACROS_ONLY and
105             let the author know, and he will try and fix it :-). This lists all
106             macros #define'd in the file PLUS all macros #define'd in all files
107             #include'd by that file (both the system files and the user
108             files "mystring.h"). This may include many more macros than is desired
109             (not everybody really wants '_LINUX_C_LIB_VERSION_MAJOR' as a user
110             defined function in their debugger...), so there are 3 mode flags
111             defined that allow the user to control which macros are included:
112             MACROS_ALL, MACROS_LOCAL, and MACROS_NONE.
113              
114             =head2 MACROS_ALL, MACROS_LOCAL, and MACROS_NONE
115              
116             These flags can be used to control what macros go into the print
117             tables that Devel::DebugInit uses to create the output file. The
118             MACROS_ALL flag instructs DebugInit to included all macros of that
119             type in the output table. To avoid printing out all of the system level
120             macros that can get #include'd you can use the MACROS_LOCAL flag. This
121             indicates that only macros actually #define'd in that file should be
122             stored, and macros #define'd in other files which are #include'd into
123             the file should NOT be stored (they are, however, still made available
124             for expansion purposes). The MACROS_LOCAL flag is the default for
125             macros with arguments. Finally, the MACROS_NONE flag indicates that no
126             macros of that type should be put in the output table. The MACROS_NONE
127             flag is the default for the simple macros.
128              
129             =head2 Output Tables and Lookup Tables
130              
131             Devel::DebugInit has two separate groups of tables that it uses -
132             lookup tables for expanding macro definitions and output tables for
133             printing the fully expanded macros. The lookup tables always include
134             all macros that a given file has access to, but the output tables may
135             have many fewer. Because the user-defined functions of some debuggers
136             can be very limited, Devel::DebugInit fully expands all macros stored
137             in the output tables before writing them to a file. In this way, any
138             macro which utilized other macros in its body will have those expanded
139             in place. So by the end of the expansion process, all macros will be
140             self defined and not rely on any other macro definition. Each macro in
141             the output tables is expanded in this manner using the definitions in
142             the lookup tables. Using separate lookup tables and output tables
143             allows users to print out only those macros they care about while
144             still be able to fully expand all macros.
145              
146             =cut
147              
148             # Preloaded methods go here.
149              
150             =head1 METHODS
151              
152             =head2 new()
153              
154             Returns a blessed reference to an instance of a Devel::DebugInit
155             subclass. Each Devel::DebugInit subclass takes a list of option value
156             pairs as optional arguments to new. Currently there are three
157             recognized options 'filenames', 'macros_args', and
158             'macros_no_args'. The 'filenames' option controls which file is used
159             for creating the output. The 'macros_args' option controls the level
160             of output support for macros with arguments. The 'macro_no_args'
161             option controls the level of output support for simple macros. For
162             example, to make a .gdbinit file useful for debugging perl or perl
163             XSUBs try the following:
164              
165             $gdb = new Devel::DebugInit::GDB
166             'filenames' => ["$Config{'archlib'}/CORE/perl.h"],
167             'macros_args' => $Devel::DebugInit::MACROS_ALL,
168             'macros_no_args' => $Devel::DebugInit::MACROS_ALL;
169              
170             $gdb->write();
171              
172             When written, this will create a file that is about 110k in size and
173             have about 1750 user-defined functions. So it may be useful to limit
174             it in scope somewhat. It is not clear that simple macros are useful
175             from within a debugger, so the default value for 'macros_no_args' is
176             MACROS_NONE, and to avoid printing all system level macros, the
177             default for 'macros_args' is MACROS_LOCAL. NOTE that by using
178             MACROS_LOCAL, you will inhibit printing of all macros not #define'd in
179             the file listed, both from local header files and system headers
180             alike. To get around this multiple files can be included in the array
181             ref for the 'filenames' option. Each files macros are added to a
182             common lookup table, but only the macros #defined in each file are
183             printed. So could do the following:
184              
185             $gdb = new Devel::DebugInit::GDB
186             'filenames' => ["$Config{'archlib'}/CORE/perl.h",
187             "$Config{'archlib'}/CORE/sv.h",
188             "$Config{'archlib'}/CORE/XSUB.h"],
189             'macros_args' => $Devel::DebugInit::MACROS_LOCAL,
190             'macros_no_args' => $Devel::DebugInit::MACROS_NONE;
191              
192             $gdb->write();
193              
194             This reduces the output file to only 21k and 250 or so macros.
195              
196             =head2 write()
197             =head2 write($filename)
198              
199             This function is overloaded by each of the debugger specific
200             subclasses to produce output recognized by that debugger. If $filename
201             is not given, it defaults to something reasonable for that
202             debugger. All macros in the output table for each macro type (macros
203             with arguments and simple macros) will be printed if it passes
204             scrutiny by the L method. See the L section for
205             more details on controlling what macros are stored in the print
206             tables.
207              
208             =head2 scan()
209              
210             The only other method of interest to users of this module is the
211             scan() method which is also overloaded by each backend subclass. This
212             method is called by write() to ascertain whether or not a given macro
213             should be written out to the output file. By default, scan() stops
214             undefined macros, blank macros (e.g. macros such as <#define VMS>
215             which are usually just conditional compiler flags and of no use in a
216             debugger), and macros with names that conflict with built-in debugger
217             commands. Users desiring a very fine grained control over the output
218             can override the builtin scan() with their own on a per need
219             basis. For example:
220              
221             package myGDB;
222             use Devel::DebugInit::GDB;
223             @myGDB::ISA = (Devel::DebugInit::GDB);
224            
225             sub scan {
226             my ($gdb,$key,$macro) = @_;
227            
228             #first give the superclass scan a chance
229             return 0 unless $gdb->SUPER::scan(@_);
230            
231             # dont' print out any macros with a leading '_'
232             return 0 if $macro =~ /^_/;
233            
234             # print the rest
235             return 1;
236             }
237              
238             =cut
239              
240             sub new {
241             my ($class,%args) = @_;
242              
243             # set the default values
244             my $ARGS = $MACROS_LOCAL; # print only local macros with args
245             my $NOARGS = $MACROS_NONE; # don't print simple macros
246              
247             # check the input arguments to see what support is desired
248             # we pass refs so that this call can modify the parameters
249             Devel::DebugInit::setup_args(\$NOARGS,\$ARGS,%args);
250              
251             # see if an input file was specified
252             die "Must specify array of filenames" unless exists $args{'filenames'} && ref $args{'filenames'};
253              
254             my $self = [];
255             bless $self, $class;
256              
257             my ($file,$filename);
258             foreach $filename (@{$args{'filenames'}}) {
259             $file = new C::DebugFile 'filename' => $filename;
260             if (defined $file) {
261             push(@{$self}, $file);
262             } else {
263             die "Bad file name: $filename";
264             }
265             }
266              
267             foreach $file (@{$self}) {
268             $file->setup_tables($NOARGS,$ARGS);
269             }
270              
271             # expand all definitions using the lookup tables GDB's user defined
272             # functions are pretty limited and one cannot call another, so they
273             # all have to be expanded to the lowest common denominator
274             foreach $file (@{$self}) {
275             $file->defines_no_args($self);
276             $file->defines_args($self);
277             }
278             return $self
279             }
280              
281             sub files {
282             my $self = @_;
283             my (@files,$file);
284             foreach $file (@{$self}) {
285             push(@files,$file);
286             }
287             return (@files);
288             }
289              
290             sub print {
291             die "Can't call Devel::DebugInit::print(), must use a backend specific subclass";
292             }
293              
294             sub setup_args {
295             my ($NOARGS,$ARGS,%args) = @_;
296              
297             # see if any Debug specific args were given
298             if (exists $args{'macros_args'}) {
299             my $args = $args{'macros_args'};
300             if ($args == $MACROS_NONE ||
301             $args == $MACROS_LOCAL ||
302             $args == $MACROS_ALL ) {
303             $$ARGS = $args;
304             } else {
305             warn("bad argument %s given to macros_args, should be 0,1,2. Ignoring...", $args);
306             }
307             }
308              
309             if (exists $args{'macros_no_args'}) {
310             my $no_args = $args{'macros_no_args'};
311             if ($no_args == $MACROS_NONE ||
312             $no_args == $MACROS_LOCAL ||
313             $no_args == $MACROS_ALL ) {
314             $$NOARGS = $no_args;
315             } else {
316             warn("bad argument %s given to macros_no_args, should be 0,1,2. Ignoring...", $no_args);
317             }
318             }
319             }
320              
321             # the following are private methods. Don't use them as they are
322             # subject to change without warning. You've been warned ;-)
323              
324             ##################################
325             #
326             # C::DebugFile
327             #
328             package C::DebugFile;
329             @C::DebugFile::ISA = qw(C::Scan);
330              
331             sub new {
332             my ($class,%args) = @_;
333             return $class->SUPER::new(%args);
334             }
335              
336             sub setup_tables {
337             my ($self,$NOARGS,$ARGS) = @_;
338              
339             # set up the lookup tables
340             $self->set_no_args_lookup($self->get('defines_no_args_full'));
341             $self->set_args_lookup($self->get('defines_args_full'));
342            
343             # set up the output tables
344             if ($ARGS == $Devel::DebugInit::MACROS_ALL) {
345             $self->set_args($self->get('defines_args_full'));
346             } elsif ($ARGS == $Devel::DebugInit::MACROS_LOCAL) {
347             $self->set_args($self->get('defines_args'));
348             }
349             if ($NOARGS == $Devel::DebugInit::MACROS_ALL) {
350             $self->set_no_args($self->get('defines_no_args_full'));
351             } elsif ($NOARGS == $Devel::DebugInit::MACROS_LOCAL) {
352             $self->set_no_args($self->get('defines_no_args'));
353             }
354             }
355              
356             sub defines_no_args {
357             my ($self,$debug) = @_;
358             my $defines = $self->get_no_args();
359             return unless defined $defines;
360              
361             my ($key,$define);
362             foreach $key (keys %{$defines}) {
363             $defines->{$key} = $self->strip($defines->{$key});
364             }
365              
366             # this recursively refines each macro definition in the lookup table
367             # and then stores the final fully expanded value in the output table
368             foreach $key (keys %{$defines}) {
369             $define = C::Define::NoArgs->new($debug,$self,$key);
370             $define->keep($define->expand());
371             }
372             }
373              
374             sub defines_args {
375             my ($self,$debug) = @_;
376             my $defines = $self->get_args();
377             return unless defined $defines;
378              
379             my ($key,$define);
380             foreach $key (keys %{$defines}) {
381             $defines->{$key}->[1] = $self->strip($defines->{$key}->[1]);
382             }
383              
384             # this recursively refines each macro definition in the lookup table
385             # and then stores the final fully expanded value in the output table
386             foreach $key (keys %{$defines}) {
387             $define = C::Define::Args->new($debug,$self,$key);
388             $define->keep($define->expand());
389             }
390             }
391              
392             # Gets rid of unwanted characters in the macro
393             sub strip {
394             my ($self,$define) = @_;
395              
396             # strip all comments - I think that C::Scan really ought to do this,
397             # but until I understand what &sanitize does, I'm not touching it.
398             # besides these are pretty simple regexp's...
399             $define =~ s@\s*//.*@@; # Get rid of C++ comments
400             $define =~ s@/\s*\*.*\*/\s*@@; # Get rid of C comments
401             $define =~ s@\s*$@@; # Get rid of trailing whitespace
402             $define =~ s@\n@@; # Get rid of newlines
403             $define =~ s@\s+@ @; # Get rid of extra whitespace
404             return $define;
405             }
406              
407             # these methods operate on the output tables
408             sub get_args {
409             my ($self) = @_;
410             return $self->[1]->{'args'};
411             }
412              
413             sub set_args {
414             my ($self,$macros) = @_;
415             return $self->[1]->{'args'} = $macros;
416             }
417              
418             sub get_no_args {
419             my ($self) = @_;
420             return $self->[1]->{'no_args'};
421             }
422              
423             sub set_no_args {
424             my ($self,$macros) = @_;
425             return $self->[1]->{'no_args'} = $macros;
426             }
427              
428             # these methods operate on the lookup tables
429             sub get_no_args_lookup {
430             my ($self) = @_;
431             return $self->[1]->{'no_args_lookup'};
432             }
433              
434             sub set_no_args_lookup {
435             my ($self,$macros) = @_;
436             return $self->[1]->{'no_args_lookup'} = $macros;
437             }
438              
439             sub get_args_lookup {
440             my ($self) = @_;
441             return $self->[1]->{'args_lookup'};
442             }
443              
444             sub set_args_lookup {
445             my ($self,$macros) = @_;
446             return $self->[1]->{'args_lookup'} = $macros;
447             }
448              
449             ##################################
450             #
451             # C::DEFINES
452             # C::DEFINES::NoArgs
453             # C::DEFINES::Args
454             #
455             # These classes abstract out the two different types of #define
456             # macros, Those with arguments, e.g. #define min(x,y) ((x) < (y) ? (x): (y)),
457             # and simple macros, e.g. #define NEEDS_JPEG 1
458              
459             package C::Define;
460              
461             sub new {
462             my ($class,$debug,$file,$name) = @_;
463             my $self = {};
464             $self->{'debug'} = $debug;
465             $self->{'file'} = $file;
466             $self->{'name'} = $name;
467             bless $self, $class;
468             }
469              
470             sub debug {return shift->{'debug'};}
471             sub file {return shift->{'file'};}
472              
473             # by default, the macros don't have arguments
474             sub args {return 0;}
475              
476             # is $name a macro in this file? If so, return an instance of the
477             # appropriate C::Define subclass, otherwise return undef.
478             # we now look up the symbol in every file in $debug's list of files.
479             sub defined {
480             my $self = shift;
481             my $name = shift;
482             my $debug = $self->debug();
483             my $file;
484             foreach $file (@{$debug}) {
485             if (exists $file->get_no_args_lookup()->{$name}) {
486             return new('C::Define::NoArgs',$debug,$file,$name);
487             } elsif (exists $file->get_args_lookup()->{$name}) {
488             return new('C::Define::Args',$debug,$file,$name);
489             }
490             }
491             return undef;
492             }
493              
494             # Given a macro definition, we expand it - so that it relies on no
495             # other (known) macros - by tokenizing it and expanding each token in
496             # the macro depth first, and then replacing each token in the current
497             # macro by the fully expanded version of the token
498             sub expand {
499             my $self = shift;
500             my $macro = $self->get();
501              
502             # If local macros are being used, it is possible for them to be in
503             # the local table but not in the global lookup table. The local
504             # version just looks for all #define's in the file, without actually
505             # expanding the #if's
506             return undef unless defined $macro;
507              
508             my (@tokens,$token,$new_macro);
509              
510             # tokenize $macro and expand each of the tokens
511             # abort if there are any unexpanded tokens
512             @tokens = $macro =~ m/\w+/g;
513             foreach $token (@tokens) {
514             # is there a better way to tell if an sv is a number???
515             if ($token =~ /^\d+$/ || $token =~ /0x[a-f0-9]+/) {
516             # just a number, so skip it
517             next;
518             }
519            
520             # this is really a token that we might need to expand
521             $new_macro = $self->defined($token);
522             unless (defined $new_macro) {
523             # this token isn't in the macro tables so I take it to be a
524             # global symbol so we don't need to replace it
525             next;
526             }
527              
528             # refine the token
529             $new_macro->expand();
530             if (!defined $new_macro->get) {
531             print "Broke on token = $token, macro = $macro\n";
532             }
533             # replace all occurrences of token with its definition
534             if ($new_macro->args()) {
535             # if it takes args, replace the arglist too
536             $macro =~ s/\b$token\b\([^\)]*?\)/$new_macro->get()/e;
537             } else {
538             $macro =~ s/\b$token\b/$new_macro->get()/e;
539             }
540             }
541              
542             # replace the hash entry with the fully expanded definition
543             return $self->set($macro);
544             }
545              
546             # For simple macros, C::Scan stores the macro as the value of the name key.
547             package C::Define::NoArgs;
548             @C::Define::NoArgs::ISA = ('C::Define');
549              
550             # NOTE: get() and set() only affect the lookup tables, keep()
551             # changes the value in the output table
552             sub get {
553             my $self = shift;
554             my $hash = $self->file()->get_no_args_lookup();
555             my $name = $self->{'name'};
556             return $hash->{$name};
557             }
558              
559             sub set {
560             my $self = shift;
561             my $value = shift;
562             my $hash = $self->file()->get_no_args_lookup();
563             my $name = $self->{'name'};
564             return $hash->{$name} = $value;
565             }
566              
567             sub keep {
568             my $self = shift;
569             my $value = shift;
570             my $hash = $self->file()->get_no_args();
571             my $name = $self->{'name'};
572             return $hash->{$name} = $value;
573             }
574              
575             # For macros with arguments, C::Scan stores the info in an array
576             # ref. The first position is an array ref of all the argumentment
577             # names. The second position is the string of the actual macro.
578             package C::Define::Args;
579             @C::Define::Args::ISA = ('C::Define');
580              
581             # members of this class have arguments
582             sub args {return 1;}
583              
584             # NOTE: get() and set() only affect the lookup tables, keep()
585             # changes the value in the output table
586             sub get {
587             my $self = shift;
588             my $hash = $self->file()->get_args_lookup();
589             my $name = $self->{'name'};
590             return $hash->{$name}->[1];
591             }
592              
593             sub set {
594             my $self = shift;
595             my $value = shift;
596             my $hash = $self->file()->get_args_lookup();
597             my $name = $self->{'name'};
598             return $hash->{$name}->[1] = $value;
599             }
600              
601             sub keep {
602             my $self = shift;
603             my $value = shift;
604             my $hash = $self->file()->get_args();
605             my $name = $self->{'name'};
606             return $hash->{$name}->[1] = $value;
607             }
608              
609             # Autoload methods go after =cut, and are processed by the autosplit program.
610              
611             1;
612             __END__