1 ###############################################################################
2 # Copyright (c) 2000-2015 Ericsson Telecom AB
3 # All rights reserved. This program and the accompanying materials
4 # are made available under the terms of the Eclipse Public License v1.0
5 # which accompanies this distribution, and is available at
6 # http://www.eclipse.org/legal/epl-v10.html
7 ###############################################################################
9 #############################################################
10 # The gdb cannot load the symbol table for compiler. That is why this script was written.
11 # This script creates logs for the stack.
12 # The following parameters can be used:
13 # 1st parameter : ON or OFF. ON makes the changes for Makefiles and creates the logger C++ files.
14 # The OFF sets mandatory the -R flag. The cleaning is always recursive.
15 # 2nd parameter : -R. Optional. If set the search for files is recursive in directory structure.
16 # 3d parameter : a directory or file name under titan. This sript now is only for compiler2.
17 # 4th parameter : -L main or -L all. Optional. Omitting it, the all is used default.
18 # The main logs only between the program function main entry and exit.
19 # The following parameters shall be set to restore all the changes: OFF -R subdir
20 # where subdir is a directory name directly under titan.
21 # The logfile is placed into ../titan/stacklogger directory. The format: stack_logger_MM_DD_YYYY.log.
22 # The date is the one when the script generated the changes in the source code.
24 # perl stacklogger.pl ON -R compiler2 -L main
25 # perl stacklogger.pl ON -R compiler2 -L all
26 # perl stacklogger.pl OFF -R compiler2
27 ##############################################################
34 use POSIX
qw(strftime);
40 my $set = 0; # default off
41 my $recursive = 0; # default non recursive iteration
42 my $loglevel = 1; # this means: -L all
44 #weird name not to macth for any string in C++ file
45 my $macroname = "STACK_LOGGER_2014_BL67";
46 my $loggerdirname = "stacklogger";
48 &processArgs
( \
$topdir, \
$path, \
$loggerdir, \
$pathtomain, \
$set, \
$recursive, \
$loglevel );
50 &getDirs
( $path, \
@dirs );
53 &getFiles
( $path, \
@files );
64 ############################################################
65 sub setLogger
# switches the logger on
67 &add_objects_to_target_makes
( @dirs );
69 &create_logger_files
( $loggerdir );
70 &insert_include
( @files );
71 &insert_logger_macro
( @files );
73 ############################################################
74 sub resetLogger
# switches the logger off
76 &remove_logger_macro
( @files );
77 &remove_include
( @files );
78 &delete_logger_files
( $loggerdir );
79 &restore_make
( $path );
80 &delete_dep_files
( $path );
81 if ( -d
$loggerdir && ( $pathtomain eq $path )) { rmdir $loggerdir or die ( "$loggerdir cannot be deleted\n"); }
83 ############################################################
84 sub insert_logger_macro
# inserts the logger macro in the files
86 my @files = @_; #all the files where the logger macros are to be written
89 remove_logger_macro
( $file );
90 open ( FILE
, "<", $file ) or die ( "failed to open file: $file\n" );
93 my $arrSize = scalar @lines;
97 open ( FILE
, ">", $file ) or die ( "failed to open file: $file\n" );
102 my $regex1 = qr/.*[:]{2}.*/s;
103 my $found = $line =~ $regex1;
104 if ( $found || ( $moreline ne "" ))
106 $moreline = append_and_check
( $moreline, $line );
116 ############################################################
117 sub remove_logger_macro
# removes the logger macros from the files
119 my @files = @_; #all the files where the logger macros are to be written
120 for my $file (@files)
122 open ( FILE
, "<", $file ) or die ( "failed to open file: $file\n" );
125 my $arrSize = scalar @lines;
127 open ( FILE
, ">", $file ) or die ( "failed to open file: $file\n" );
128 for my $line (@lines)
130 $line =~ s/$macroname//;
136 ############################################################
137 sub append_and_check
# appends the next line to $moreline if the pattern was not found
138 { # it searches through more lines
139 my $origline = $_[1]; # the next line to be examined and/or append
140 # remove C++ style comment
141 my $cppcomment = qr/\/{2}.*/s
;
142 my $ccomment = qr/\/\
*.*\
*\
//s;
143 # valid function definition
144 my $regex2 = qr/.*[:]{2}[A-Za-z0-9_~\s]+[(].*[)][^;}]*[{]/s;
145 # found ';' it cannot be a function definition
146 my $regex3 = qr/.*[:]{2}.+[;].*/s;
150 $append =~ s/$cppcomment//;
151 my $string = $_[0] . $append;
153 $string =~ s/$ccomment//;
154 my $found = ($string =~ $regex2);
158 $origline =~ s/\{/\{$macroname/;
160 print FILE
$origline;
161 my $invalid = ($string =~ $regex3);
168 ############################################################
169 sub add_dir_to_top_make
# the directory of the stacklogger will be added to Makefile in the {top} dir
171 my $replace = ":= " . $loggerdirname . " ";
172 # the compiler2 pattern is fix the stacklogger shall be written in this line to the first place
173 #ALLDIRS := **insert here** common compiler2 repgen xsdconvert
174 my $search = qr/^[\s]*ALLDIRS[\s]*:=.*compiler2/s;
175 my $makefile = $topdir . "Makefile";
176 open ( FILE
, "<", $makefile ) or die ( "failed to open file: $makefile\n" );
179 my @found = grep /$loggerdirname/, @list;
182 my $newfile = $topdir . "Makefile.orig";
183 if ( -f
$newfile ) { unlink $newfile; }
184 copy
( $makefile, $newfile ) or die ( "File cannot be copied." );
185 open ( FILE
, ">", $makefile ) or die ( "failed to open file: $makefile\n" );
187 for my $i ( 0 .. $#list )
189 if ( $list[$i] =~ $search )
191 $list[$i] =~ s/:=/$replace/;
192 $list[$i] =~ s/ {2,}/ /; # 2 spaces are replaced to 1, if there is any
195 print FILE
$list[$i];
198 if ( $count != 1) { die ( "The Makefile in $topdir seems to have been changed.\nPlease redesign the regex in sub add_dir_to_top_make.\n" ); }
201 ############################################################
202 sub add_objects_to_target_makes
#changes the Makefiles to be compiled
204 my @dirs = @_; # the target and its subdirectories
205 if ( ! grep {/$pathtomain$/} @dirs )
207 push ( @dirs, $pathtomain );
209 my $date = strftime
"%m_%d_%Y", localtime;
211 my $objectfilename = "stack_logger_" . $date . $object;
213 CPPFLAGS += -I$loggerdir
214 COMPILER_COMMON_OBJECTS += $loggerdir/$objectfilename
215 MFGEN_COMMON_OBJECTS += $loggerdir/$objectfilename
216 TCOV2LCOV_COMMON_OBJECTS += $loggerdir/$objectfilename
219 CPPFLAGS += -I$loggerdir
221 my $search = qr/^SUBDIRS :=/s;
222 for my $dir ( @dirs )
224 my $makefile = $dir . "Makefile";
225 open ( FILE
, "<", $makefile ) or die ( "failed to open file: $makefile\n" );
228 my @found = grep /$loggerdir/, @list;
231 my $newfile = $dir . "Makefile.orig";
232 if ( -f
$newfile ) { unlink $newfile; }
233 copy
( $makefile, $newfile ) or die ( "File cannot be copied." );
234 open ( FILE
, ">", $makefile ) or die ( "failed to open file: $makefile\n" );
236 for my $i ( 0 .. $#list )
238 if ( $list[$i] =~ $search )
240 if ( $dir eq $pathtomain )
246 print FILE
$insertsubdir ;
250 print FILE
$list[$i];
253 if ( $count != 1) { die ( "The Makefile in $dir seems to have been changed.\nPlease redesign the regex in sub add_objects_to_target_makes.\n" ); }
257 ############################################################
258 sub restore_make
#restores the original Makefiles
260 my $path = $_[0]; #path to target directory
261 if ( $path eq $pathtomain )
264 &getDirs
( $path, \
@dirs );
268 push ( @dirs, $path );
270 for my $dir ( @dirs )
272 my $origmakefile = $dir . "Makefile.orig";
273 if ( -f
$origmakefile )
275 my $makefile = $dir . "Makefile";
277 rename ( $origmakefile, $makefile ) or die ( "File cannot be renamed." );
280 if ( $path eq $pathtomain )
282 &restore_make
( $topdir );
285 ############################################################
286 sub create_logger_files
# creates the .hh the .cc and the Makefile for the stacklogger
287 { # these files are C++ construct which at construction and destruction creates a logentry for the function contained
288 my $dir = $_[0]; # path to directory where the logger files are to be created
289 &delete_logger_files
( $dir );
291 my $guard = $macroname . "_H";
296 #define $macroname EntryRaiiObject obj ## __LINE__ (__FUNCTION__ , __FILE__);
297 class EntryRaiiObject {
299 EntryRaiiObject (const char* func, const char* file);
305 static unsigned int level;
311 static FILE* getHandler ();
318 static const char* file_name;
323 my $date = strftime
"%m_%d_%Y", localtime;
324 my $headerfilename = "stack_logger_" . $date . ".hh";
325 my $logfilename = "stack_logger_" . $date . ".log";
326 open(FILE
, ">", $headerfilename) or die ( "failed to open file: $headerfilename\n" );
327 print FILE
$logger_header;
330 if ( $loglevel == 0 )
332 $printlog = "if (!doLog()) { return; }";
335 "#include \"$headerfilename\"
339 const char* FH::file_name = \"$dir/$logfilename\";
340 unsigned int EntryRaiiObject::level = 0;
341 EntryRaiiObject::EntryRaiiObject (const char* func, const char* file) : func_(func), file_(file)
345 fprintf ( FH::getHandler(), \"%*u %s - Entry - %s\\n\", level, level, func_, file_);
346 fflush (FH::getHandler());
348 EntryRaiiObject::~EntryRaiiObject ()
351 fprintf( FH::getHandler(), \"%*u %s - Exit - %s\\n\", level, level, func_, file_);
352 fflush (FH::getHandler());
355 int EntryRaiiObject::doLog ()
357 static int count = 0;
358 if (strcmp ( func_ , \"main\") == 0)
372 FILE* FH::getHandler ()
376 fh = fopen (file_name, \"w\");
379 printf (\"Failed to open file: %s\", file_name);
391 my $extension = ".cc";
392 my $bodyfilename = "stack_logger_" . $date . $extension;
393 open ( FILE
, ">", $bodyfilename ) or die ( "failed to open file: $bodyfilename\n" );
398 include \$(TOP)/Makefile.cfg
399 SOURCES := $bodyfilename
400 HEADERS := \$(SOURCES:.cc=.hh)
401 OBJECTS := \$(SOURCES:.cc=.o)
403 all run : \$(OBJECTS)
407 include ../Makefile.genrules
410 open ( FILE
, ">", "Makefile" ) or die ( "failed to open file: Makefile\n" );
414 ############################################################
415 sub insert_include
# inserts the header file include of the stacklogger for every files touched
417 my @files = @_; # all files for inserting the header
418 # if found previuos Include then update
419 my $regex = qr/#include <stack_logger_*/;
420 for my $includefilenamein (@files)
422 my $date = strftime
"%m_%d_%Y", localtime;
423 my $includefilename = "stack_logger_" . $date . ".hh";
424 my $include = "#include <$includefilename>\n";
425 my $includefilenameout = "$includefilenamein.new" ;
426 open ( IN
, "<", $includefilenamein) or die ( "failed to open file: $includefilenamein\n" );
427 open ( OUT
, ">", $includefilenameout) or die ( "failed to open file: $includefilenameout\n" );
428 my $first_line = <IN
>;
429 if ( $first_line !~ $regex )
432 print OUT
$first_line;
444 unlink $includefilenamein;
445 rename $includefilenameout, $includefilenamein;
448 ############################################################
449 sub remove_include
# removes the header file include of the stacklogger from files
451 my @files = @_; # all files where the include is to be removed from
452 # if found previuos Include then update
453 my $regex = qr/#include <stack_logger_*/;
455 for my $file (@files)
457 open ( FILE
, "<", $file) or die ( "failed to open file: $file\n" );
461 open ( FILE
, ">", $file) or die ( "failed to open file: $file\n" );
462 while ( $lines[$start] =~ $regex )
466 for my $i ( $start .. $#lines )
468 print FILE
$lines[$i];
473 ############################################################
474 sub getFiles
# collects the .cc files recursively from the path given
476 my($path) = $_[0]; # the target path
479 push ( @files, $path );
482 #append a trailing / if it's not there
483 $path .= '/' if($path !~ /\
/$/);
484 #loop through the files contained in the directory
485 for my $eachFile (glob($path . '*'))
487 # if the file is a directory
488 if ( -d
$eachFile && $recursive )
490 # pass the directory to the routine
491 getFiles
( $eachFile, \
@files );
495 my $regex = qr/.+\.cc$/s;
496 my $cpp = ($eachFile =~ $regex);
499 push ( @files, $eachFile );
504 ############################################################
505 sub getDirs
# collects the directories recursively from the path given
507 my($path) = $_[0]; # the target path
510 my $dir = dirname
( $path );
511 $dir .= '/' if($dir !~ /\
/$/);
512 push ( @dirs, $dir );
515 #append a trailing / if it's not there
516 $path .= '/' if($path !~ /\
/$/);
517 push ( @dirs, $path );
518 #loop through the files contained in the directory
519 for my $eachFile (glob($path . '*'))
521 # if the file is a directory
522 if ( -d
$eachFile && $recursive )
524 # pass the directory to the routine
525 getDirs
( $eachFile, \
@dirs );
529 ############################################################
530 sub delete_dep_files
# deletes the dependency files that breaks the recompilation
532 my($path) = $_[0]; # the target path
533 if ( -f
$path ) { return; }
534 #append a trailing / if it's not there
535 $path .= '/' if($path !~ /\
/$/);
536 #loop through the files contained in the directory
537 for my $eachFile (glob($path . '*'))
539 # if the file is a directory
542 # pass the directory to the routine
543 delete_dep_files
( $eachFile );
547 my $regex = qr/.+\.d$/s;
548 my $dep = ($eachFile =~ $regex);
556 ############################################################
557 sub delete_logger_files
# removes the logger files and their directory
559 if ( $path ne $pathtomain) { return;}
560 my ($logpath) = $_[0];
561 $logpath .= '/' if($logpath !~ /\
/$/);
562 for my $file (glob($logpath . '*'))
570 ############################################################
571 sub getMainDir
# defines the directory where the main.cc is to be found
573 my $dir = $_[0] ; # the target directory
575 my $enddir = $topdir;
577 if ( -f
$dir ) { $dir = dirname
( $dir ); } # if it is file, get the containing dir
578 while ( $enddir ne $dir )
580 opendir ( DIR
, $dir ) or die $!;
581 my @dir = grep { /main.cc/ } readdir DIR
;
584 $dir = dirname
( $dir ) ; # get the parent
591 die ( "There was no main.cc in the path given and in their parent directories up to titan\n");
593 ############################################################
594 sub processArgs
#( \$topdir, \$path, \$loggerdir, \$target, \$set, \$recursive, \$loglevel )
597 $messages[0] = "\nUsage: perl stacklogger.pl ON|OFF [ -R ] compiler2 | pathto/file \n";
598 $messages[1] = "ON switches on the stack logger\n";
599 $messages[2] = "OFF removes the stack logger\n";
600 $messages[3] = "-R optional: recursive handling the path given\n";
601 $messages[4] = "/pathto/file accept only a filename with extension .cc\n";
602 $messages[5] = "compiler2 accept only the directory name within titan\n";
603 $messages[6] = "-L main or -L all, sets the log level\n";
604 $messages[7] = "Correct usage of the ";
605 my $numArgs = $#ARGV + 1;
607 if ( $numArgs < 1 && $numArgs > 5 )
611 if (( uc ( $ARGV[0] ) ne "ON" ) && ( uc ( $ARGV[0] ) ne "OFF" ))
613 print $messages[7] . "first parameter :\n";
619 if ((( $numArgs == 3 ) || ( $numArgs == 5 )) && ($ARGV[1] ne "-R" ))
621 print $messages[7] . "second parameter :\n";
626 if (( $numArgs > 3 ) && ( $ARGV[1] eq "-R" ) ||
627 ( $numArgs > 2 ) && ( $ARGV[1] ne "-R" ))
631 if ( $ARGV[1] ne "-R" )
636 if (( $ARGV[$logarg1] ne "-L" ) || (( uc ( $ARGV[$logarg2] ) ne "MAIN" ) && ( uc ( $ARGV[$logarg2] ) ne "ALL" )))
638 print $messages[7] . "the log level :\n";
642 if ( uc $ARGV[$logarg2] eq "MAIN" )
650 my $ttcn3_dir = $ENV{TTCN3_DIR
};
651 if ( defined ( $ttcn3_dir))
652 { # the top dir is ../titan/
653 $ttcn3_dir =~ s/.*\/titan\K.+//;
654 $topdir = $path = $ttcn3_dir . "/";
656 if ( $ARGV[1] ne "-R" ) { $index -= 1; }
657 $path = $path . $ARGV[$index] ;
658 $path =~ s/\/\//\//; # replace // to /
659 unless ( -d
$path || -f
$path ) { die ( "$path neither file nor directory\n" ) ;}
660 if ( -d
$path ) {$path .= "/"; }
661 $pathtomain = &getMainDir
( $path );
663 else { die ( "Error: environment variable TTCN3_DIR is not defined\n" ); }
666 if (( $numArgs >= 3 ) && ( $ARGV[1] eq "-R" ) && ( -f
$path ))
668 die ( "recursive iteration is only for directories\n" );
671 $loggerdir = $topdir . $loggerdirname;
672 if ( uc ( $ARGV[0] ) eq "ON" )
675 unless ( -d
$loggerdir )
676 { # Create a directory
677 mkdir ( $loggerdir, 0770 ) or die ("can't create: $loggerdir\n");
681 if (( $numArgs >= 3 ) && ( $ARGV[1] eq "-R" ))
686 ############################################################