os/persistentdata/traceservices/commsdebugutility/tools/extractlog.pl
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
# Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
# All rights reserved.
sl@0
     3
# This component and the accompanying materials are made available
sl@0
     4
# under the terms of "Eclipse Public License v1.0"
sl@0
     5
# which accompanies this distribution, and is available
sl@0
     6
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
#
sl@0
     8
# Initial Contributors:
sl@0
     9
# Nokia Corporation - initial contribution.
sl@0
    10
#
sl@0
    11
# Contributors:
sl@0
    12
#
sl@0
    13
# Description:
sl@0
    14
#
sl@0
    15
sl@0
    16
use strict;
sl@0
    17
use Getopt::Long;
sl@0
    18
sl@0
    19
# read in the command line parameters
sl@0
    20
my $verbose = 0;
sl@0
    21
my $singleLevel = 0;
sl@0
    22
my $fromBatchFile = 0;
sl@0
    23
my $help = 0;
sl@0
    24
GetOptions( 'verbose|v!' => \$verbose,
sl@0
    25
			'1!' => \$singleLevel,
sl@0
    26
			'help|h|?!' => \$help,
sl@0
    27
			'--fromBatchFile!' => \$fromBatchFile );
sl@0
    28
Usage() if $help;
sl@0
    29
my $file  = $ARGV[0];
sl@0
    30
if(!defined($file))
sl@0
    31
{
sl@0
    32
	$file = "$ENV{EPOCROOT}EPOC32\\WINSCW\\C\\LOGS\\LOG.TXT";
sl@0
    33
	$file = "$ENV{EPOCROOT}EPOC32\\WINS\\C\\LOGS\\LOG.TXT" if(!-r $file);
sl@0
    34
	print "No file specified, defaulting to $file\n";
sl@0
    35
}
sl@0
    36
print "Verbose mode on\n" if $verbose;
sl@0
    37
sl@0
    38
# open up the file for input
sl@0
    39
open(INPUT_FILE, "< $file") or die "ERROR: Couldn't open the file \"$file\" for input:";
sl@0
    40
sl@0
    41
# read file without intepretting CR/LF - not ideal on window's systems, but
sl@0
    42
# I introduced this to get around apparent problem when seeking back when reading binary data
sl@0
    43
# The seek back seemed to seek to somewhere other than where we had last "tell"'ed.
sl@0
    44
# binmode fixes this since CR/LF is always seen as 2 distinct chars.
sl@0
    45
binmode(INPUT_FILE);
sl@0
    46
sl@0
    47
# declare handy arrays
sl@0
    48
my %file_handles_text;   # a hash of all components seen for ascii and their associated file handle
sl@0
    49
my %file_handles_binary; # a hash of all components seen for binary and their associated file handle
sl@0
    50
my @comments;       # an array of all the comment lines seen so far
sl@0
    51
sl@0
    52
# iterate through each line of the file
sl@0
    53
my $filepos = tell(INPUT_FILE);
sl@0
    54
my $linenum = 1;
sl@0
    55
while (<INPUT_FILE>) {
sl@0
    56
    # strip off any CR/LF's since we will correctly terminate the line by one
sl@0
    57
    # if we find the line is ascii. Binary lines should also arrive with a CR/LF at their end.
sl@0
    58
    my $line = $_;
sl@0
    59
    print $line if $verbose;
sl@0
    60
    chomp($line);
sl@0
    61
sl@0
    62
    my $strlen = length($line);
sl@0
    63
    if (($strlen == 0) || (ord "$line" == 13)) {
sl@0
    64
       if ($verbose) { print "Line#: $linenum is an empty line.\n"; }
sl@0
    65
    } else {
sl@0
    66
		$line =~ s/\r$//;	# chomp CR
sl@0
    67
        if ($line =~ /^#/) {
sl@0
    68
            # we are dealing with a comment line
sl@0
    69
            $line .= "\n";
sl@0
    70
            push(@comments, "$line");
sl@0
    71
            while((my $component, my $file_handle) = each(%file_handles_text)) {
sl@0
    72
                print $file_handle "$line"
sl@0
    73
            }
sl@0
    74
        }
sl@0
    75
        else {
sl@0
    76
            #we are dealing with a component line so check the correct line format and determine if it is ascii or binary
sl@0
    77
            my @list = split("\t", $line);
sl@0
    78
sl@0
    79
            my $linetype = "$list[2]";
sl@0
    80
sl@0
    81
            if (ord "$linetype" == 97) {
sl@0
    82
                # this is ascii, so return a CR/LF to line
sl@0
    83
                $line .= "\n";
sl@0
    84
                my $component = lc($list[0] . ($singleLevel? "": "_$list[1]") . ".log");
sl@0
    85
                if (not exists $file_handles_text{$component}) {
sl@0
    86
                    # we haven't seen this component before
sl@0
    87
                    local *OUTFILE;
sl@0
    88
                    open(OUTFILE, "> $component") or die "ERROR. Line $linenum: can't open file \"$component\" for output: $!";
sl@0
    89
                    foreach my $comment (@comments) {
sl@0
    90
                        print OUTFILE "$comment";
sl@0
    91
                    }
sl@0
    92
                    $file_handles_text{$component} = *OUTFILE;
sl@0
    93
                }
sl@0
    94
                my $file_handle = $file_handles_text{$component};
sl@0
    95
                print $file_handle "$line";
sl@0
    96
            } elsif (ord "$linetype" == 98) {
sl@0
    97
                #assume it is binary
sl@0
    98
                my $component = "$list[0]_$list[1].bin";
sl@0
    99
                if (not exists $file_handles_binary{$component}) {
sl@0
   100
                    # we haven't seen this component before
sl@0
   101
                    local *OUTFILE;
sl@0
   102
                    open(OUTFILE, "> $component") or die "ERROR. Line $linenum: can't open file \"$component\" for output: $!";
sl@0
   103
                    binmode(OUTFILE);
sl@0
   104
                    $file_handles_binary{$component} = *OUTFILE;
sl@0
   105
                }
sl@0
   106
sl@0
   107
                # go back to start of line since CR/LF might even occur in the length field,
sl@0
   108
                # then read to each tab until the binary tag is found again
sl@0
   109
                seek(INPUT_FILE,$filepos,0);
sl@0
   110
sl@0
   111
                my $old_rs = $/;
sl@0
   112
                $/ = chr(9);
sl@0
   113
                do {
sl@0
   114
                    $_ = <INPUT_FILE>;
sl@0
   115
                } while ((ord "$_" != 98) && (length != 1));
sl@0
   116
                $/ = $old_rs;
sl@0
   117
sl@0
   118
                # read the length as a "little-endian" 4-byte unsigned integer
sl@0
   119
				my $datalenstr;
sl@0
   120
                my $numread = read(INPUT_FILE,$datalenstr,4);
sl@0
   121
                if ($numread != 4) { die "ERROR: did not read all 4 bytes binary data length on line $linenum"; }
sl@0
   122
sl@0
   123
                my $datatoread = unpack("v",$datalenstr);
sl@0
   124
sl@0
   125
                # read next char and ensure it is a tab
sl@0
   126
				my $onechar;
sl@0
   127
                $numread = read(INPUT_FILE,$onechar,1);
sl@0
   128
                if ($numread != 1) { die "ERROR: read error when reading tab char in binary line on line $linenum"; }
sl@0
   129
                if (ord $onechar != 9) { die "ERROR: No tab char in binary line at pos : $filepos where expected between length and data at line $linenum"; }
sl@0
   130
sl@0
   131
                if ($verbose) {
sl@0
   132
                    print "About to read binary data. Beginning of line is at pos: $filepos ";
sl@0
   133
                    printf " [%X] Tags: ",$filepos;
sl@0
   134
                    foreach my $d (@list) {
sl@0
   135
                       print "[$d]";
sl@0
   136
                    }
sl@0
   137
                    print "\nBytes to read: $datatoread\n";
sl@0
   138
                }
sl@0
   139
sl@0
   140
				my $datastr;
sl@0
   141
                $numread = read(INPUT_FILE,$datastr,$datatoread);
sl@0
   142
                if ($datatoread != $numread) { die "ERROR: only read $numread of expected $datatoread bytes binary data on line $linenum"; }
sl@0
   143
sl@0
   144
                if ($verbose) { print "Read Completed.\n"; }
sl@0
   145
sl@0
   146
sl@0
   147
                my $file_handle = $file_handles_binary{$component};
sl@0
   148
                print $file_handle "$datastr";
sl@0
   149
sl@0
   150
                # finally, read in the trailing CR/LF before reverting to textual reading
sl@0
   151
                $_ = <INPUT_FILE>;
sl@0
   152
        
sl@0
   153
            } else {
sl@0
   154
                if ($verbose) {
sl@0
   155
                    print "Line# $linenum at filepos $filepos is CORRUPT: linetype field is neither ascii nor binary so ignoring.\n";
sl@0
   156
                    print "Line fields: ";
sl@0
   157
                    foreach my $d (@list) {
sl@0
   158
                       print "[$d]";
sl@0
   159
                    }
sl@0
   160
                    print "\n     ... skipping line and continuing\n";
sl@0
   161
                }
sl@0
   162
sl@0
   163
            }
sl@0
   164
        } # comment line check
sl@0
   165
    } #empty line check
sl@0
   166
    $filepos = tell(INPUT_FILE);
sl@0
   167
    #print "filepos at end of line proc: $filepos . input rec #: $.";
sl@0
   168
    #printf "[%X]\n",$filepos;
sl@0
   169
    $linenum++;
sl@0
   170
}
sl@0
   171
sl@0
   172
# and finally clean up
sl@0
   173
close(INPUT_FILE) or die "ERROR: failed to close the input log file: $!";
sl@0
   174
my $firstFile = 1;
sl@0
   175
while((my $component, my $file_handle) = each(%file_handles_text)) 
sl@0
   176
{
sl@0
   177
	printf "%s%s", $firstFile? "Generated: ": ", ", $component;
sl@0
   178
	$firstFile = 0;
sl@0
   179
    close($file_handle) or die "ERROR: failed to close the output log file for \"$component\": $!";
sl@0
   180
}
sl@0
   181
while((my $component, my $file_handle) = each(%file_handles_binary)) 
sl@0
   182
{
sl@0
   183
	printf "%s%s", $firstFile? "Generated: ": ", ", $component;
sl@0
   184
	$firstFile = 0;
sl@0
   185
    close($file_handle) or die "ERROR: failed to close the output log file for \"$component\": $!";
sl@0
   186
}
sl@0
   187
print "\n";
sl@0
   188
sl@0
   189
sl@0
   190
sub Usage () {
sl@0
   191
print $fromBatchFile? "Common Usage: splitlog [logfile] [-v][-1]\n": "Args: [logfile] [-v][-1]\n";
sl@0
   192
    print <<ENDHERESTRING;
sl@0
   193
Where:
sl@0
   194
  [logfile] = CDU log file (default: {EPOCROOT}\\EPOC32\\WINS[CW]\\C\\LOGS\\LOG.TXT)
sl@0
   195
  [-v]      = verbose output
sl@0
   196
  [-1]      = split only at component level (one file per unique first tag)
sl@0
   197
   
sl@0
   198
Input Log file format:
sl@0
   199
 as specified in the FLOGGER documentation.  Briefly, there are three
sl@0
   200
 types of log messages:
sl@0
   201
   1) Comment lines.  These contain a '#' character at the beginning of
sl@0
   202
      the line.
sl@0
   203
   2) Ascii Log lines.  Contains tab separated fields - the first being the 
sl@0
   204
      name of the component that logged that particular message.
sl@0
   205
   3) Binary Log lines. Same fields as an ascii line but then contains
sl@0
   206
      a specified number of bytes of raw data. 
sl@0
   207
sl@0
   208
Output:
sl@0
   209
 This script will create a number of files in the current 
sl@0
   210
 directory - one for each component found in the input log file.  Each
sl@0
   211
 file will have the same name as the first two tags separated by an underscore.
sl@0
   212
 If the component is logging ascii test, its output log file will contain all
sl@0
   213
 comment lines, and all log lines relating to that particular component.
sl@0
   214
 If the component is logging binary data, only the actual data is placed in
sl@0
   215
 the output log file.
sl@0
   216
 Ascii output files are given the extension *.log while binary files have
sl@0
   217
 extension *.bin
sl@0
   218
sl@0
   219
"Out of Memory":
sl@0
   220
  error may mean the file is corrupt and the script tried to
sl@0
   221
  read a section of binary data which isn't there. Try rerunning with the "-v"
sl@0
   222
  flag to help diagnose. File position numbers reported should correlate exactly
sl@0
   223
  with the byte position if displaying file in a hex editor.
sl@0
   224
ENDHERESTRING
sl@0
   225
sl@0
   226
    exit 1;
sl@0
   227
}