--- a/kerneltest/e32utils/trace/btracevw.pl Thu Aug 19 11:14:22 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1952 +0,0 @@
-#
-# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
-# All rights reserved.
-# This component and the accompanying materials are made available
-# under the terms of the License "Eclipse Public License v1.0"
-# which accompanies this distribution, and is available
-# at the URL "http://www.eclipse.org/legal/epl-v10.html".
-#
-# Initial Contributors:
-# Nokia Corporation - initial contribution.
-#
-# Contributors:
-#
-# Description:
-#
-
-#!/usr/bin/perl
-
-use File::Find;
-use File::Spec::Functions;
-
-
- my $TraceFileName;
-
- my $PrintFlagFilePos = 0;
- my $PrintFlagHdrLen = 0;
- my $PrintFlagHdrFlags = 0;
- my $PrintFlagFormatString = 0;
- my $VerboseMode = 0;
- my $RawMode = 0;
- my $FormatIdIsSubCategory = 0;
- my $OutputSawDictionaryMode = 0;
-
- # for the category range 0-191, the format string is indexed by the category & subcategory
- %FormatTables =
- (
- 0 => # ERDebugPrintf
- {
- 0 => "ThreadId %h, %s",
- },
-
- 1 => # ERKernPrintf
- {
- 0 => "ThreadId %h, %s",
- },
-
- 3 => # EThreadIdentification
- {
- 0 => "ENanoThreadCreate, NThread %x",
- 1 => "ENanoThreadDestroy, NThread %x",
- 2 => "EThreadCreate, NThread %x, DProcess %x, name %s",
- 3 => "EThreadDestroy, NThread %x, DProcess %x, Id %x",
- 4 => "EThreadName, NThread %x, DProcess %x, name %s",
- 5 => "EProcessName, NThread %x, DProcess %x, name %s",
- 6 => "EThreadId, NThread %x, DProcess %x, Id %x",
- 7 => "EProcessCreate, DProcess %x",
- 8 => "EProcessDestroy, DProcess %x",
- },
- );
-
- my @typedefs;
- my @members;
- my %values = (
-# UTF::KInitialClientFormat => {type=>"TFormatId", size=>2, value=>512}
- KMaxTUint8 => {type=>"TUint8", size=>1, value=>255},
- KMaxTUint16 => {type=>"TUint16", size=>2, value=>65535}
- );
- my %macros;
- my @classes;
- my @enums;
- my %formatStrings; # each enum may have it's own format string
- my %formatCategories; # each enum may have it's own format category
-
- my %filescope;
- $filescope{file}=1;
- undef $filescope{name};
-
- $filescope{typedefs}=\@typedefs;
- $filescope{members}=\@members;
- $filescope{values}=\%values;
- $filescope{macros} = \%macros;
- $filescope{FormatTables} = \%FormatTables;
-
- $filescope{classes} = \@classes;
- $filescope{enums} = \@enums;
-
- $filescope{formatStrings} =\%formatStrings;
- $filescope{formatCategories} = \%formatCategories;
-
-
-
- if (@ARGV == 0)
- {
- print "BTraceVw.pl \n";
- print "An unsupported utility which extracts UTrace-style format-strings\n";
- print "from header files & uses these to decode a BTrace output file\n";
- print "Syntax : BTraceVw.pl [-v] [-r] [-sd] [-i <IncFilePath>] [<BTrace file>]\n";
- print "where : -v = verbose mode\n";
- print " : -r = raw output mode\n";
- print " : -sd = produce SAW trace viewer dictionary file\n";
- print " : this file then needs to be merged into the 'com.symbian.analysis.trace.ui.prefs' file\n";
- print " : located under the carbide workspace directory\n";
- print "\n";
-
- print "e.g. (this decodes a trace file & produces a comma-separated output file) : \n";
- print "btracevw.pl -i /os/kernelhwsrv/userlibandfileserver/fileserver/inc/f32tracedef.h -i /os/kernelhwsrv/userlibandfileserver/fileserver/inc/utraceefsrv.h -i /os/kernelhwsrv/userlibandfileserver/fileserver/inc/utraceefile.h trace.utf >trace.csv\n";
- print "\n";
- print "e.g. (this overwrites the SAW dictioany file) : \n";
- print "btracevw.pl -sd -i /os/kernelhwsrv/userlibandfileserver/fileserver/inc/f32tracedef.h -i /os/kernelhwsrv/userlibandfileserver/fileserver/inc/utraceefsrv.h -i /os/kernelhwsrv/userlibandfileserver/fileserver/inc/utraceefile.h >com.symbian.analysis.trace.ui.prefs\n";
-
- exit;
- }
-
- while (@ARGV > 0)
- {
-
- if ($ARGV[0] eq "-i")
- {
- shift @ARGV;
- ($FilePath) = @ARGV;
- shift @ARGV;
-
- undef @incFiles;
- @incFiles;
-
- find sub { push @incFiles, $File::Find::name if m/\.h$/i;}, $FilePath ;
- foreach $incFile (@incFiles)
- {
- H2Trace($incFile, \%filescope);
- }
- }
- elsif ($ARGV[0] eq "-r")
- {
- $RawMode = 1;
- shift @ARGV;
- }
- elsif ($ARGV[0] eq "-sd")
- {
- $OutputSawDictionaryMode = 1;
- shift @ARGV;
- }
- elsif ($ARGV[0] eq "-v")
- {
- $VerboseMode = 1;
- shift @ARGV;
- }
- else
- {
- $TraceFileName = "$ARGV[0]";
- shift @ARGV;
- }
- }
-
- if ($VerboseMode)
- {
- dump_scope(\%filescope);
- PrintFormatTables(\%FormatTables);
- }
- if ($OutputSawDictionaryMode)
- {
- OutputSawDictionary(\%FormatTables);
- }
-
- if (defined ($TraceFileName))
- {
- ReadTraceFile($RawMode);
- }
-
-
-
-
-sub ReadTraceFile($)
- {
- (my $RawMode) = @_;
-# print "Trace file is $TraceFileName, RawMode $RawMode, VerboseMode $VerboseMode\n\n";
-
- open (LOGFILE, "<$TraceFileName") or die "Can't open $TraceFileName: $!\n";
- binmode (LOGFILE);
-
- my $val = 0;
-
-
- # enum TFlags from e32btrace.h
- $EHeader2Present = 1<<0;
- $ETimestampPresent = 1<<1;
- $ETimestamp2Present = 1<<2;
- $EContextIdPresent = 1<<3;
- $EPcPresent = 1<<4;
- $EExtraPresent = 1<<5;
- $ERecordTruncated = 1<<6;
- $EMissingRecord = 1<<7;
-
- # enum TFlags2 from e32btrace.h
- $EMultipartFlagMask = 3<<0;
- $ECpuIdMask = 0xfff<<20;
-
- # enum TMultiPart from e32btrace.h
- $EMultipartFirst = 1;
- $EMultipartMiddle = 2;
- $EMultipartLast = 3;
-
- $EMaxBTraceDataArray = 80;
-
- # enum TCategory from e32btrace.h
- $EThreadIdentification = 3;
-
- # enum TThreadIdentification from e32btrace.h
- $EThreadCreate = 2;
- $EThreadName = 4;
- $EProcessName = 5;
- $EThreadId = 6;
-
- # Context Id bits from e32btrace.h
- $EContextIdMask = 0x00000003;
- $EContextIdThread = 0;
- $EContextIdFIQ = 0x1;
- $EContextIdIRQ = 0x2;
- $EContextIdIDFC = 0x3;
-
- # enum TClassificationRange from e32btraceu.h
- $EAllRangeFirst = 192;
- $EAllRangeLast = 222;
-
- %TCategoryIdToString =
- (
- 0 => "ERDebugPrintf",
- 1 => "EKernPrintf",
- 2 => "EPlatsecPrintf",
- 3 => "EThreadIdentification",
- 4 => "ECpuUsage",
- 5 => "EKernPerfLog",
- 6 => "EClientServer",
- 7 => "ERequests",
- 8 => "EChunks",
- 9 => "ECodeSegs",
- 10 => "EPaging",
- 11 => "EThreadPriority",
- 12 => "EPagingMedia",
- 13 => "EKernelMemory",
- 14 => "EHeap",
- 15 => "EMetaTrace",
- 16 => "ERamAllocator",
- 17 => "EFastMutex",
- 18 => "EProfiling",
- 19 => "EResourceManager",
- 20 => "EResourceManagerUs",
- 21 => "ERawEvent ",
- 128 => "EPlatformSpecificFirst",
- 191 => "EPlatformSpecificLast",
- 192 => "ESymbianExtentionsFirst",
-
- # UTrace "ALL" range
- 192 => "EPanic",
- 193 => "EError",
- 194 => "EWarning",
- 195 => "EBorder",
- 196 => "EState",
- 197 => "EInternals",
- 198 => "EDump",
- 199 => "EFlow",
- 200 => "ESystemCharacteristicMetrics",
- 201 => "EAdhoc",
-
- 253 => "ESymbianExtentionsLast",
- 254 => "ETest1",
- 255 => "ETest2",
- );
-
-
- %ProcessNames;
- %ThreadNames;
- %ThreadIds;
-
-
- # print column titles
- if ($PrintFlagFilePos) {printf "FilePos, ";} # col #0
- if ($PrintFlagHdrLen) { printf "Len, ";} # col #1
- if ($PrintFlagHdrFlags) {printf "Flags, "; } # col #2
- printf "Category, "; # col #3
- printf "TimeStamp, "; # col #4
- printf "Delta, "; # col #5
- printf "context Id, "; # col #6
- printf "PC, "; # col #7
- printf "UID, "; # col #8
- if ($PrintFlagFormatString){printf "Format string, ";} # col #9
- printf "Formatted text, "; # col #10
- print "\n\n";
-
-
- while (1)
- {
- my $pos = tell (LOGFILE);
-
- # print file pos (col #0)
- if ($PrintFlagFilePos){ printf ("0x%08X, ", $pos);}
-
- my $category;
- my $subCategory;
- my $multipartFlags = 0;
- my $recordData = "";
- my $recordLen;
- my $recordPos = 0;
-
- $recordLen = ReadRecord(LOGFILE, \$pos, \$recordData, \$category, \$subCategory, \$multipartFlags, $RawMode);
- if ($recordLen == -1)
- {last;}
-
-
- if (!$RawMode && ($multipartFlags == $EMultipartMiddle || $multipartFlags == $EMultipartLast))
- {next;}
-
-# print record contents
-# my $buf;
-# for (my $i=0; $i < $recordLen; $i+=4)
-# {
-# $buf.= sprintf ("%08X ", unpack("V", substr($recordData, $recordPos+$i, 4)));
-# }
-# printf "\n[$buf\n]";
-
-
- # for UTrace "ALL" range, read UID
- if ($category >= $EAllRangeFirst && $category <= $EAllRangeLast &&
- (!$RawMode) && $multipartFlags != $EMultipartMiddle && $multipartFlags != $EMultipartLast)
- {
- $uid = unpack("V", substr($recordData, $recordPos, 4));
- $recordPos+= 4;
-
- # then read formatID
- $FormatIdIsSubCategory = ($subCategory != 0) ? 1 : 0;
- if ($FormatIdIsSubCategory)
- {
- $formatId = $subCategory
- }
- else
- {
- $formatId = unpack("V", substr($recordData, $recordPos, 4));
- $recordPos+= 4;
- }
- }
-
-
- # print UID (col #8)
- printf "0x%08X, ", $uid;
-
-
- my $formatTable;
- my $formatString;
- if ($category >= $EAllRangeFirst && $category <= $EAllRangeLast)
- {
- $formatString = $FormatTables{$uid}{$formatId};
- }
- else
- {
- $formatString = $FormatTables{$category}{$subCategory};
- }
-
-
- # Get thread names
- if ($category == $EThreadIdentification)
- {
- if ($subCategory == $EProcessName)
- {
- my $process = unpack("V", substr($recordData, 4, 4));
- my $processName = substr($recordData, 8, $recordLen - 8);
-# printf ("\nprocess [%08X] processName [$processName]\n", $process);
- $ProcessNames{$process} = $processName;
- }
- elsif ($subCategory == $EThreadCreate || $subCategory == $EThreadName)
- {
- my $thread = unpack("V", substr($recordData, 0, 4));
- my $process = unpack("V", substr($recordData, 4, 4));
- my $threadName = substr($recordData, 8, $recordLen - 8);
-# printf ("\nprocess [%08X] thread [%08X] threadName [$threadName]\n", $process, $thread, $threadName);
- $ThreadNames{$thread} = $ProcessNames{$process} . "::" . $threadName;
- }
- elsif ($subCategory == $EThreadId)
- {
- my $thread = unpack("V", substr($recordData, 0, 4));
- my $process = unpack("V", substr($recordData, 4, 4));
- my $threadId = unpack("V", substr($recordData, 8, 4));
-# printf ("\nprocess [%08X] thread [%08X] threadId [%08X]\n", $process, $thread, $threadId);
- $ThreadIds{$thread} = $threadId;
- }
- }
-
-
- # print Format string (col #9)
- if ($PrintFlagFormatString)
- {
- my $formatStringWithoutCommas = $formatString;
- $formatStringWithoutCommas=~ s/,/ /g;
- printf "%s, ", $formatStringWithoutCommas;
- }
-
- my $formattedText;
-
- my $lenFormatString = length($formatString);
- if ($lenFormatString && !$RawMode && $multipartFlags != $EMultipartMiddle && $multipartFlags != $EMultipartLast)
- {
- for (my $i=0; $i<$lenFormatString; $i++)
- {
- my $c = (substr ($formatString, $i, 1));
-# printf "$c\n";
- if ($c eq "%")
- {
- undef my $fieldLen;
- $i++;
- $c = (substr ($formatString, $i, 1));
- if ($c eq "%")
- {
- $formattedText.= substr ($formatString, $i, 1);
- next;
- }
- if ($c eq "*") ## take length from buffer
- {
- $fieldLen = unpack("V", substr($recordData, $recordPos, 4));
- if ($fieldLen > $recordLen-$recordPos)
- {
- $formattedText.= "*** Invalid field length ***";
- last;
- }
- $recordPos+= 4;
- $i++;
- $c = (substr ($formatString, $i, 1));
- }
- if (lc $c eq "x" || $c eq "h")
- {
- if (defined $fieldLen)
- {
- if (($fieldLen & 3) == 0)
- {
- for (my $i=0; $i< $fieldLen; $i+= 4)
- {
- $formattedText.= sprintf ("%08X ", unpack("V", substr($recordData, $recordPos, 4)));
- $recordPos+= 4;
- }
- }
- else
- {
- for (my $i=0; $i< $fieldLen; $i++)
- {
- $formattedText.= sprintf ("%02X ", unpack("C", substr($recordData, $recordPos, 1)));
- $recordPos++;
- }
- }
- }
- else
- {
- $formattedText.= sprintf ("0x%08X", unpack("V", substr($recordData, $recordPos, 4)));
- $recordPos+= 4;
- }
- $recordPos = ($recordPos + 3) & ~3;
- next;
- }
- # display "%ld" as hex for now as don't know how to get perl to use or display a 64 decimal value
- elsif (lc $c eq "l" && substr ($formatString, $i+1, 1) eq "d")
- {
- $i++;
- my $loWord = unpack("V", substr($recordData, $recordPos, 4));
- $recordPos+= 4;
- my $hiWord = unpack("V", substr($recordData, $recordPos, 4));
- $recordPos+= 4;
- $formattedText.= sprintf ("0x%X:%08X", $hiWord, $loWord);
- }
- elsif (lc $c eq "l" && substr ($formatString, $i+1, 1) eq "x")
- {
- $i++;
- my $loWord = unpack("V", substr($recordData, $recordPos, 4));
- $recordPos+= 4;
- my $hiWord = unpack("V", substr($recordData, $recordPos, 4));
- $recordPos+= 4;
- $formattedText.= sprintf ("0x%X:%08X", $hiWord, $loWord);
- }
- elsif (lc $c eq "d")
- {
- $formattedText.= sprintf ("%d", unpack("V", substr($recordData, $recordPos, 4)));
- $recordPos+= 4;
- $recordPos = ($recordPos + 3) & ~3;
- next;
- }
- elsif ($c eq "s")
- {
- if (!defined $fieldLen)
- {$fieldLen = $recordLen - $recordPos;}
- $formattedText.= substr($recordData, $recordPos, $fieldLen);
- $recordPos+= $fieldLen;
- $recordPos = ($recordPos + 3) & ~3;
- next;
- }
- elsif ($c eq "S")
- {
- if (!defined $fieldLen)
- {$fieldLen = $recordLen-$recordPos;}
- for (my $j=0; $j < $fieldLen; $j+=2)
- {
- my $byte = unpack("c", substr ($recordData, $recordPos+$j, 1));
- $formattedText.= sprintf ("%c", $byte);
- }
- $recordPos+= $fieldLen;
- $recordPos = ($recordPos + 3) & ~3;
- next;
- }
- elsif ($c eq "c")
- {
- my $byte = unpack("c", substr ($recordData, $recordPos, 1));
- $formattedText.= sprintf ("%c", $byte);
- }
- }
- else
- {
- $formattedText.= $c;
- }
- }
- }
- else # no format string : print as hex
- {
- for (my $i=0; $i < $recordLen; $i+=4)
- {
- $formattedText.= sprintf ("%08X ", unpack("V", substr($recordData, $i, 4)));
- }
- $recordPos+= $recordLen; $recordLen = 0;
-
- }
-
-
- # print Formatted text (col #10)
- $formattedText=~ s/,/;/g;
- $formattedText=~ s/\r//g;
- $formattedText=~ s/\n/,/g;
- printf "%s", $formattedText;
-
- printf("\n");
-
- if ($len < 0 || $recordLen < 0) {die "truncated file";}
-
-
- $pos+= ($len +3) & ~3;
- seek (LOGFILE, $pos, SEEK_SET) or die "truncated file";
- $i++;
- }
-
- close (LOGFILE);
-
- if ($VerboseMode)
- {
- print "*** Processes ***\n";
- for $id ( keys %ProcessNames )
- {
- printf ("process %08X ProcessName %s\n", $id, $ProcessNames{$id});
- }
- print "*** Thread ***\n";
- for $id ( keys %ThreadNames )
- {
- printf ("thread %08X ThreadName %s::%X\n", $id, $ThreadNames{$id}, $ThreadIds{$id});
- }
- }
-
- }
-
-
-sub ReadSingleRecord
- {
- ($fh, $data, $dataLen, $recordLen, $category, $subCategory, $multipartFlags, $extraN, $totalLen, $offset, $RawMode) = @_;
-
- my $hdr;
- my $flags;
- my $header2;
- my $timestamp;
- my $timestamp2;
- my $contextId;
- my $programConter;
-
- my $recordOffset = 0;
-
- $timestampLast;
- my $timestampDelta = 0;
-
- my $bytesRead = read($fh, $hdr, 4);
-
-
- if ($bytesRead < 4)
- {return -1;}
-
- ($$recordLen,$flags,$$category,$$subCategory) = unpack("CCCC", $hdr);
- $$dataLen = $$recordLen-4;
-
- if ($flags & $EHeader2Present)
- {$$multipartFlags = (ReadDword($fh) & $EMultipartFlagMask); $$dataLen-= 4}
- else
- {$$multipartFlags = 0;}
- if ($flags & $ETimestampPresent)
- {$timestamp = ReadDword($fh); $$dataLen-= 4;}
- if ($flags & $ETimestamp2Present)
- {$timestamp2 = ReadDword($fh); $$dataLen-= 4;}
- if ($flags & $EContextIdPresent)
- {$contextId = ReadDword($fh); $$dataLen-= 4;}
- if ($flags & $EPcPresent)
- {$programConter = ReadDword($fh); $$dataLen-= 4;}
- if ($flags & $EExtraPresent)
- {$$extraN = ReadDword($fh); $$dataLen-= 4;}
- if ($$multipartFlags != 0)
- {
- $$totalLen = ReadDword($fh); $$dataLen-= 4;
- if ($$multipartFlags == $EMultipartMiddle || $$multipartFlags == $EMultipartLast)
- {$$offset = ReadDword($fh); $$totalLen-= 4; $$dataLen-= 4;}
- }
-
- $timestampDelta = $timestamp - $timestampLast;
- $timestampLast = $timestamp;
-
- read($fh, $$data, ($$dataLen + 3) & ~3);
-
-
- if ($RawMode || $$multipartFlags == $EMultipartFirst || $$multipartFlags == 0)
- {
- # print header len (col #1)
- if ($PrintFlagHdrLen){printf ("0x%02X, ", $$recordLen);}
-
- # print header flags (col #2)
- if ($PrintFlagHdrFlags)
- {
- printf ("%02X ", $flags);
- if ($flags & $EHeader2Present) {printf "EHeader2Present ";}
- if ($flags & $ETimestampPresent) {printf "ETimestampPresent ";}
- if ($flags & $ETimestamp2Present) {printf "ETimestamp2Present ";}
- if ($flags & $EContextIdPresent) {printf "EContextIdPresent ";}
- if ($flags & $EPcPresent) {printf "EPcPresent ";}
- if ($$multipartFlags != 0)
- {
- printf "EExtraPresent ";
- if ($$multipartFlags == $EMultipartFirst) {print "EMultipartFirst ";}
- elsif ($$multipartFlags == $EMultipartMiddle) {print "EMultipartMiddle ";}
- elsif ($$multipartFlags == $EMultipartLast) {print "EMultipartLast ";}
- printf ("ExtraN(0x%08X) ", $$extraN);
- }
- if ($flags & $ERecordTruncated) {printf "ERecordTruncated ";}
- if ($flags & $EMissingRecord) {printf "EMissingRecord ";}
- print ",";
- }
-
- # print category (col #3)
- printf "(%d;%d) $categoryString , ", $$category, $$subCategory;
-
- # print timestamp(s) (col #4)
- printf "0x";
- if (defined $timestamp2) {printf "%08X : ", $timestamp2;}
- printf "%08X", $timestamp;
- printf ", ";;
-
- # print timestamp delta (col #5)
- printf "0x%08X, ", $timestampDelta;
-
- # print context Id (col #6)
- if (!$RawMode && defined $ThreadNames{$contextId})
- {
- printf ("%s::%X, ", $ThreadNames{$contextId}, $ThreadIds{$contextId});
- }
- else
- {
- if ((($contextId & $EContextIdMask) == $EContextIdThread) || $RawMode)
- {printf "0x%08X, ", $contextId;}
- elsif (($contextId & $EContextIdMask) == $EContextIdFIQ)
- {printf "FIQ, ";}
- elsif (($contextId & $EContextIdMask) == $EContextIdIRQ)
- {printf "IRQ, ";}
- elsif (($contextId & $EContextIdMask) == $EContextIdIDFC)
- {printf "IDFC, ";}
- }
-
- # print Program Counter (col #7)
- printf "0x%08X, ", $programConter;
- }
-
-
-
-
-#########################################################
-# my $hex;
-# for (my $i=0; $i < $$dataLen; $i+=4)
-# {
-# $hex.= sprintf ("%08X ", unpack("V", substr($$data, $i, 4)));
-# }
-# printf "\nadding [$hex]\n";
-#########################################################
- return $bytesRead
- }
-
-
-sub ReadRecord
- {
- ($fh, $recordPos, $recordData, $category, $subCategory, $multipartFlags, $RawMode) = @_;
-# printf "CurrentPos %08X\n", $pos;
-
-
-
- seek ($fh, $$recordPos, SEEK_SET) or die "truncated file";
- my $recordLen;
- my $extraN;
- my $totalLen;
- my $offset;
- my $dataLen;
- my $data;
- my $bytesRead;
-
-
- $bytesRead = ReadSingleRecord($fh, \$data, \$dataLen, \$recordLen, \$$category, \$$subCategory, \$$multipartFlags, \$extraN, \$totalLen, \$offset, $RawMode);
-
- if ($bytesRead == -1) # eof ?
- {return -1; }
- $$recordPos+= ($recordLen +3) & ~3;
-
- $$recordData = $data;
- $offset = $dataLen;
-
- $offset-= 4; # subtract 4 bytes for UID ?????????
-
- if ($RawMode || $$multipartFlags != $EMultipartFirst)
- {return $dataLen;}
-
- $pos = $$recordPos;
-
- while (1)
- {
-
- # find next record, i.e. look for a record which matches $extraN
-
- seek ($fh, $pos, SEEK_SET) or die "truncated file";
-
- my $recordLen;
-
- my $category;
- my $subCategory;
- my $multipartFlags;
- my $currentExtraN;
- my $currentOffset;
-
- my $totalLen;
- my $currentDataLen;
- my $data;
- $bytesRead = ReadSingleRecord($fh, \$data, \$currentDataLen, \$recordLen, \$category, \$subCategory, \$multipartFlags, \$currentExtraN, \$totalLen, \$currentOffset, $RawMode);
- if ($bytesRead == -1) # eof ?
- {return -1; }
- $pos+= ($recordLen +3) & ~3;
-
-# printf "\npos %08X, Seaching for (extra %08X, offset %08X), found (extra %08X, offset %08X)\n",
-# $pos, $extraN, $offset, $currentExtraN, $currentOffset;
-
- if ($currentExtraN == $extraN && $currentOffset == $offset)
- {
- $$recordData.= $data;
- $offset+= $currentDataLen;
- $dataLen+= $currentDataLen;
- }
-
- if ($multipartFlags == $EMultipartLast)
- {last;}
- }
-
- return $dataLen;
- }
-
-sub ReadDword {
- (my $fh) = @_;
- my $buffer;
-
- $bytesRead = read($fh, $buffer, 4);
- if ($bytesRead < 4) {die "truncated file";}
-
- my $dword = unpack("V", $buffer);
-
- return $dword
- };
-
-sub ReadByte {
- (my $fh) = @_;
- my $buffer;
-
- $bytesRead = read($fh, $buffer, 1);
- if ($bytesRead < 1) {die "truncated file";}
-
- my $byte = unpack("C", $buffer);
-
- return $byte
- };
-
-
-
-sub PrintFormatTables($)
- {
- my ($formatTables) = @_;
-
- for $tableIndex ( sort keys %$formatTables )
- {
- printf ("SYMTraceFormatCategory %08X:\n", $tableIndex);
- for $formatId (sort keys %{ $$formatTables{$tableIndex} } )
- {
- printf ("%08X => %s\n", $formatId, $$formatTables{$tableIndex}{$formatId});
- }
- print "\n";
- }
- }
-
-
-
-sub OutputSawDictionary($)
- {
- my ($formatTables) = @_;
-
-
- # SAW enums
- $EFieldTypeHexDump = 0;
- $EFieldTypeHex = 1;
- $EFieldTypeDecimal = 2;
- $EFieldTypeStringToEnd = 3;
- $EFieldTypeNullTerminatedString = 4;
- $EFieldTypeHexDumpToEnd = 5;
- $EFieldTypeUnicodeToEnd = 6;
- $EFieldTypeNullTerminatedUnicode = 7;
- $EFieldTypeCountedUnicode = 8;
- $EFieldTypeCountedHexDump = 9;
- $EFieldTypeCountedString = 10;
-
- my $moduleIds; # string containg all UIDs separared by semi-colons
-
- for $tableIndex ( sort keys %$formatTables )
- {
- if ($tableIndex < 256)
- {
- next;
- }
- $moduleIds.= sprintf ("%08X;", $tableIndex);
-
- printf ("MODULEID_%08X_DESC=\n", $tableIndex);
- printf ("MODULEID_%08X_NAME=%08X\n", $tableIndex, $tableIndex);
-
- my $formatIds;
- $formatIds = sprintf ("MODULEID_%08X_FORMATIDS=", $tableIndex);
-
- for $formatId (sort keys %{ $$formatTables{$tableIndex} } )
- {
- $formatIds.= sprintf ("%d;", $formatId);
- }
- printf ("$formatIds\n");
-
-
- for $formatId (sort keys %{ $$formatTables{$tableIndex} } )
- {
- my $fieldCount = 0;
- my $formatString = $$formatTables{$tableIndex}{$formatId};
-
-#printf ("formatString = (%s)\n", $formatString);
-
- # format name is the first format string up until the first space or '%' character or end-of line ...
- $formatString=~ m/^[^%\s]*/;
- my $formatName = $&;
-
- # thow the format name away
- $formatString = $';
-
- # strip the leading space
- $formatString=~ s/\s*//;
-
- printf ("MODULEID_%08X_FORMATID_%d_NAME=%s\n", $tableIndex, $formatId, $formatName);
-#printf ("MODULEID_%08X_FORMATID_%d_DESC=\n", $tableIndex, $formatId);
-
- my $lenFormatString = length($formatString);
-
- my $formattedText;
- my $fieldType = $EFieldTypeHex;
- my $fieldLen = 0;
- while (length($formatString))
- {
- my $c = (substr ($formatString, 0, 1));
-#print ("[$formatString][$c]\n");
- $formatString=~ s/.//; # strip the leading space
- if ($c eq "%")
- {
-#print "found %\n";
- my $fieldLenSpecified = 0;
- $c = (substr ($formatString, 0, 1));
- $formatString=~ s/.//; # discard char
-#print "c2=$c\n";
- if ($c eq "%")
- {
- $formattedText.= substr ($formatString, 0, 1);
- next;
- }
- if ($c eq "*") ## take length from buffer
- {
- $fieldLenSpecified = 1;
- $c = (substr ($formatString, 0, 1));
- $formatString=~ s/.//; # discard char
- }
- if (lc $c eq "x" || $c eq "h")
- {
- ## deal wilth $fieldLenSpecified
- if ($fieldLenSpecified)
- {
- $fieldType = $EFieldTypeCountedHexDump;
- $fieldLen = 0;
- }
- else
- {
- $fieldType = $EFieldTypeHex;
- $fieldLen = 4;
- }
- }
- elsif (lc $c eq "l" && substr ($formatString, 0, 1) eq "d")
- {
- $formatString=~ s/.//; # discard char
- $fieldType = $EFieldTypeDecimal;
- $fieldLen = 8;
- }
- elsif (lc $c eq "l" && substr ($formatString, 0, 1) eq "x")
- {
- $formatString=~ s/.//; # discard char
- $fieldType = $EFieldTypeHex;
- $fieldLen = 8;
- }
- elsif (lc $c eq "d")
- {
- $fieldType = $EFieldTypeDecimal;
- $fieldLen = 4;
- }
- elsif ($c eq "s")
- {
- ## deal wilth $fieldLenSpecified
- if ($fieldLenSpecified)
- {
- $fieldType = $EFieldTypeCountedString;
- $fieldLen = 0;
- }
- else
- {
- $fieldType = $EFieldTypeStringToEnd;
- $fieldLen = 0;
- }
- }
- elsif ($c eq "S")
- {
- ## deal wilth $fieldLenSpecified
- if ($fieldLenSpecified)
- {
- $fieldType = $EFieldTypeCountedUnicode;
- $fieldLen = 0;
- }
- else
- {
- $fieldType = EFieldTypeUnicodeToEnd;
- $fieldLen = 0;
- }
- }
- elsif ($c eq "c")
- {
- $fieldType = $EFieldTypeHex;
- $fieldLen = 1;
- }
- printf ("MODULEID_%08X_FORMATID_%d_FIELD_%d_NAME=%s\n", $tableIndex, $formatId, $fieldCount, $formattedText);
- printf ("MODULEID_%08X_FORMATID_%d_FIELD_%d_TYPE=%s\n", $tableIndex, $formatId, $fieldCount, $fieldType);
- if ($fieldLen > 0)
- {printf ("MODULEID_%08X_FORMATID_%d_FIELD_%d_LENGTH=%s\n", $tableIndex, $formatId, $fieldCount, $fieldLen);}
- $fieldCount++;
- $formattedText="";
-
- $formatString=~ s/\s//; # strip the leading space
- }
- else
- {
-# if ($c eq ":") {$formattedText.= '\\'; }
- $formattedText.= $c;
- }
- }
- printf ("MODULEID_%08X_FORMATID_%d_FIELDS=%d\n", $tableIndex, $formatId, $fieldCount);
-
- }
- print "MODULEIDS=$moduleIds\n";
- }
- }
-
-
-
-
-
-
-
-
-sub H2Trace($$)
-{
- %basictypes = (
- TInt8 => 1,
- TUint8 => 1,
- TInt16 => 2,
- TUint16 => 2,
- TInt32 => 4,
- TUint32 => 4,
- TInt => 4,
- TUint => 4,
- TBool => 4,
- TInt64 => 8,
- TUint64 => 8,
- TLinAddr => 4,
- TVersion => 4,
- TPde => 4,
- TPte => 4,
- TProcessPriority => 4,
- TFormatId => 2,
- );
-
- if (scalar(@_)!= 2) {
- die "perl h2trace.pl <input.h>\n";
- }
- my ($infile, $filescope) = @_;
-
- if ($VerboseMode)
- {print "\nOpening $infile\n";}
-
- open IN, $infile or die "Can't open $infile for input\n";
- my $in;
- while (<IN>) {
- $in.=$_;
- }
- close IN;
-
- # First remove any backslash-newline combinations
- $in =~ s/\\\n//gms;
-
- # Remove any character constants
- $in =~ s/\'(.?(${0})*?)\'//gms;
-
- # Strip comments beginning with //
- $in =~ s/\/\/(.*?)\n/\n/gms; #//(.*?)\n
-
- # Strip comments (/* */) but leave doxygen comments (/** */)
- $in =~ s/\/\*[^*](.*?)\*\//\n/gms; #/*(.*?)*/
-
-
- # Collapse whitespace into a single space or newline
- $in =~ s/\t/\ /gms;
- $in =~ s/\r/\ /gms;
-
- # Tokenize on non-identifier characters
- my @tokens0 = split(/(\W)/,$in);
- my @tokens;
- my $inString = 0;
- my $inComment = 0;
- my $string;
- foreach $t (@tokens0) {
- next if ($t eq "");
- next if (!$inString && ($t eq " " or $t eq ""));
- if ($inComment == 0)
- {
- if ($t eq "/")
- {$inComment = 1;}
- }
- elsif ($inComment == 1)
- {
- if ($t eq "*")
- {$inComment = 2;}
- else
- {$inComment = 0;}
- }
- elsif ($inComment == 2)
- {
- if ($t eq "*")
- {$inComment = 3;}
- }
- elsif ($inComment == 3)
- {
- if ($t eq "/")
- {
- $inComment = 0;
- # if we were in a string, need to push previous '*'
- if ($inString)
- {
- push @tokens, "*";
- }
- $inString = 0; # end of comment aborts a string
- $string = "";
- }
- else
- {$inComment = 2;}
- }
-
- if ($t eq "\"")
- {
- if (!$inString)
- {
- $inString=1;
- next;
- }
- else
- {
- $inString=0;
- $t = $string;
- $string = "";
-# if ($VerboseMode) {print "string : [$t]\n"; }
- }
- }
-
- if ($inString)
- {
- $string.= $t;
- next;
- }
- push @tokens, $t;
- }
-
- my $CurrentTraceFormatString;
- my $CurrentTraceFormatCategory;
- # format Key as specified by the @TraceFormatCategory tag is either the current category
- # or the current UID
- my $CurrentFormatTableKey;
-
-
- my $line=1;
- parse_scope($filescope, \@tokens, \$line);
-
- #print $in;
- #print join (" ", @tokens);
-} # end of H2Trace
-
-
-
- sub parse_scope($$$) {
- my ($scope, $tokens, $line) = @_;
- my $state = 1;
-
- my @classes;
- my $curr_offset=0;
- my $overall_align=0;
-# print ">parse_scope $scope->{name}\n";
-
- while (scalar(@$tokens))
- {
- my $t = shift @$tokens;
-# printf "t: [$t] [$$line]\n";
- if (!defined ($t)) {
- printf "undefined !";
- next;
- }
- if ($state>=-1 and $t eq "\n") {
- ++$$line;
- $state=1;
- next;
- } elsif ($state==-1 and $t ne "\n") {
- next;
- } elsif ($state==-2 and $t ne ';') {
- next;
- }
-
- if ($state>0 and $t eq '#') {
- $t = shift @$tokens;
- if ($t eq 'define') {
- my $ident = shift @$tokens;
- my $defn = shift @$tokens;
- if ($defn ne '(') { # don't do macros with parameters
-# print "MACRO: $ident :== $defn\n";
- $macros{$ident} = $defn;
- }
- }
- $state=-1; # skip to next line
- next;
- }
-
-
- if (parse_doxygen($scope,$tokens, $line, $t) == 1)
- {next;}
-
- if ($t eq "namespace" ) {
- $state=0;
- my %cl;
- $cl{specifier}=$t;
- $cl{scope}=$scope;
- $cl{values}=$scope->{values};
- $cl{members}=\$scope->{members};
- $cl{typedefs}=\$scope->{typedefs};
- $cl{FormatTables}=$scope->{FormatTables};
- $cl{formatStrings} =$scope->{formatStrings};
- $cl{formatCategories} =$scope->{formatCategories};
-
- my $new_namespace = \%cl;
- my $n = get_token($scope,$tokens,$line);
- if ($n !~ /\w+/) {
- warn "Unnamed $t not supported at line $$line\n";
- return;
- }
- $new_namespace->{name}=$n;
- my @class_match = grep {$_->{name} eq $n} @classes;
- my $exists = scalar(@class_match);
- my $b = get_token($scope,$tokens,$line);
- if ($b eq ':') {
- die "Inheritance not supported at line $$line\n";
- } elsif ($b eq ';') {
- # forward declaration
- push @classes, $new_namespace unless ($exists);
- next;
- } elsif ($b ne '{') {
- warn "Syntax error#1 at line $$line\n";
- return;
- }
- if ($exists) {
- $new_namespace = $class_match[0];
- if ($new_namespace->{complete}) {
- warn "Duplicate definition of $cl{specifier} $n\n";
- }
- }
- push @classes, $new_namespace unless ($exists);
- parse_scope($new_namespace, $tokens, $line);
- next;
- }
-
- if ($t eq "struct" or $t eq "class" or $t eq "NONSHARABLE_CLASS") {
- next if ($state==0);
- $state=0;
- my %cl;
- $cl{specifier}=$t;
- $cl{scope}=$scope;
- my @members;
- my @typedefs;
- $cl{members}=\@members;
- $cl{typedefs}=\@typedefs;
- $cl{FormatTables}=$scope->{FormatTables};
- my $new_class = \%cl;
- my $n;
-
- if ($t eq "NONSHARABLE_CLASS")
- {
- my $b = get_token($scope,$tokens,$line);
- if ($b !~ /\(/) {die "Syntax error at line $$line\n";}
- $n = get_token($scope,$tokens,$line);
- $b = get_token($scope,$tokens,$line);
- if ($b !~ /\)/) {die "Syntax error at line $$line\n";}
- }
- else
- {
- $n = get_token($scope,$tokens,$line);
- }
-
-
- if ($n !~ /\w+/) {
- warn "Unnamed $t not supported at line $$line\n";
- return;
- }
- $new_class->{name}=$n;
- my @class_match = grep {$_->{name} eq $n} @classes;
- my $exists = scalar(@class_match);
- my $b = get_token($scope,$tokens,$line);
- #skip inheritance etc until we get to a '{' or \ ';'
- while ($b ne '{' && $b ne ';')
- {
- $b = get_token($scope,$tokens,$line);
- die "Syntax error#2 at line $$line\n" if (!defined $b);
- }
- if ($b eq ';') {
- # forward declaration
- push @classes, $new_class unless ($exists);
- next;
- }
- if ($exists) {
- $new_class = $class_match[0];
- if ($new_class->{complete}) {
- warn "Duplicate definition of $cl{specifier} $n\n";
- }
- }
- push @classes, $new_class unless ($exists);
- parse_scope($new_class, $tokens, $line);
- next;
- } elsif ($t eq "enum") {
- $state=0;
- my $n = get_token($scope,$tokens,$line);
- my $name="";
- if ($n =~ /\w+/) {
- $name = $n;
- $n = get_token($scope,$tokens,$line);
- }
- push @enums, $name;
- if ($n ne '{') {
- die "Syntax error#4 at line $$line\n";
- }
- parse_enum($scope, $tokens, $line, $name);
- next;
- } elsif ($t eq '}') {
- $state=0;
- if ($scope->{scope}) {
- if ($scope->{specifier} eq "namespace")
- {
- $scope->{complete}=1;
-# print "Scope completed\n";
- last;
- }
- $t = get_token($scope,$tokens,$line);
- # skip to next ';'
- while (defined ($t) and $t ne ';')
- {$t = get_token($scope,$tokens,$line);}
- die "Syntax error#5 at line $$line\n" if ($t ne ';');
- $scope->{complete}=1;
-# print "Scope completed\n";
- last;
- }
- warn "Syntax error#5 at line $$line\n";
- return;
- }
- $state=0;
- if ($scope->{scope}) {
- if ($t eq "public" or $t eq "private" or $t eq "protected") {
- if (shift (@$tokens) eq ':') {
- next; # ignore access specifiers
- }
- die "Syntax error#6 at line $$line\n";
- }
- }
- unshift @$tokens, $t;
-
- my @currdecl = parse_decl_def($scope, $tokens, $line);
-# print scalar (@currdecl), "\n";
- if ($t eq 'static') {
- next; # skip static members
- }
- my $typedef;
- if ($t eq 'typedef') {
-# print "TYPEDEF\n";
- $typedef = 1;
- $t = shift @currdecl;
- $t = $currdecl[0];
- } else {
-# print "NOT TYPEDEF\n";
- $typedef = 0;
- }
-# print "$currdecl[0]\n";
- next if (scalar(@currdecl)==0);
-
- if ($t eq "const") {
- # check for constant declaration
-# print "CONST $currdecl[1] $currdecl[2] $currdecl[3]\n";
- my $ctype = lookup_type($scope, $currdecl[1]);
-# print "$ctype->{basic} $ctype->{size}\n";
- if ($ctype->{basic} and $currdecl[2]=~/^\w+$/ and $currdecl[3] eq '=') {
- if ($typedef!=0) {
- die "Syntax error#7 at line $$line\n";
- }
- shift @currdecl;
- shift @currdecl;
- my $type = $ctype->{name};
- my $name; #### = shift @currdecl;
-
- if ($scope->{name})
- {
- $name = $scope->{name} . "::" . shift @currdecl;
- }
- else
- {
- $name = shift @currdecl;
- }
-# printf "[$name,$scope->{name}]";
- my $size = $ctype->{size};
- shift @currdecl;
- my $value = get_constant_expr($scope,\@currdecl,$line);
- $values{$name} = {type=>$type, size=>$size, value=>$value};
- next;
- }
- }
-
-
-
- }
- }
-
- sub get_token($$$) {
- my ($scope,$tokenlist,$line) = @_;
- while (scalar(@$tokenlist)) {
- my $t = shift @$tokenlist;
- return $t if (!defined($t));
- if (parse_doxygen($scope,$tokenlist, $line, $t) == 1)
- {next;}
- if ($t !~ /^[\s]*$/)
- {
- if ($$tokenlist[0] eq ":" and $$tokenlist[1] eq ":")
- {
- $t.= shift @$tokenlist;
- $t.= shift @$tokenlist;
- $t.= shift @$tokenlist;
-# print "Colon-separated token";
- }
- return $t
- }
- ++$$line;
- }
- return undef;
- }
-
- sub skip_qualifiers($) {
- my ($tokens) = @_;
- my $f=0;
- my %quals = (
- EXPORT_C => 1,
- IMPORT_C => 1,
- inline => 1,
- virtual => 0,
- const => 0,
- volatile => 0,
- static => 0,
- extern => 0,
- LOCAL_C => 0,
- LOCAL_D => 0,
- GLDEF_C => 0,
- GLREF_C => 0,
- GLDEF_D => 0,
- GLREF_D => 0
- );
- for (;;) {
- my $t = $$tokens[0];
- my $q = $quals{$t};
- last unless (defined ($q));
- $f |= $q;
- shift @$tokens;
- }
- return $f;
- }
-
- sub parse_indirection($) {
- my ($tokens) = @_;
- my $level = 0;
- for (;;) {
- my $t = $$tokens[0];
- if ($t eq '*') {
- ++$level;
- shift @$tokens;
- next;
- }
- last if ($t ne "const" and $t ne "volatile");
- shift @$tokens;
- }
- return $level;
- }
-
- sub get_operand($$$) {
- my ($scope,$tokens,$line) = @_;
- my $t = get_token($scope,$tokens,$line);
- if ($t eq '-') {
- my $x = get_operand($scope,$tokens,$line);
- return -$x;
- } elsif ($t eq '+') {
- my $x = get_operand($scope,$tokens,$line);
- return $x;
- } elsif ($t eq '~') {
- my $x = get_operand($scope,$tokens,$line);
- return ~$x;
- } elsif ($t eq '!') {
- my $x = get_operand($scope,$tokens,$line);
- return $x ? 0 : 1;
- } elsif ($t eq '(') {
- my $x = get_constant_expr($scope,$tokens,$line);
- my $t = get_token($scope,$tokens,$line);
- if ($t ne ')') {
- warn "Missing ) at line $$line\n";
- return undefined;
- }
- return $x;
- } elsif ($t eq "sizeof") {
- my $ident = get_token($scope,$tokens,$line);
- if ($ident eq '(') {
- $ident = get_token($scope,$tokens,$line);
- my $cb = get_token($scope,$tokens,$line);
- if ($cb ne ')') {
- warn "Bad sizeof() syntax at line $$line\n";
- return undefined;
- }
- }
- $ident = look_through_macros($ident);
- if ($ident !~ /^\w+$/) {
- warn "Bad sizeof() syntax at line $$line\n";
- return undefined;
- }
- my $type = lookup_type($scope, $ident);
- if (!defined $type) {
- warn "Unrecognised type $ident at line $$line\n";
- return undefined;
- }
- if ($type->{basic}) {
- return $type->{size};
- } elsif ($type->{enum}) {
- return 4;
- } elsif ($type->{ptr}) {
- return 4;
- } elsif ($type->{fptr}) {
- return 4;
- }
- my $al = $type->{class}->{align};
- my $sz = $type->{class}->{size};
- return ($sz+$al-1)&~($al-1);
- }
- $t = look_through_macros($t);
- if ($t =~ /^0x/i) {
- return oct($t);
- } elsif ($t =~ /^\d/) {
- return $t;
- } elsif ($t =~ /^\w+$/) {
- my $x = lookup_value($scope,$t);
-# die "Unrecognised identifier '$t' at line $$line\n" unless defined($x);
- if (!defined($x)) {
- print "Unrecognised identifier '$t' at line $$line\n" ;
- }
- return $x;
- } elsif ($t =~ /^\w+::\w+$/) {
- my $x = lookup_value($scope,$t);
-# die "Unrecognised identifier '$t' at line $$line\n" unless defined($x);
- if (!defined($x)) {
- print "Unrecognised identifier '$t' at line $$line\n" ;
- }
- return $x;
- } else {
- warn "Syntax error#10 at line $$line\n";
- return undefined;
- }
- }
-
- sub look_through_macros($) {
- my ($ident) = @_;
- while ($ident and $macros{$ident}) {
- $ident = $macros{$ident};
- }
- return $ident;
- }
-
- sub lookup_value($$) {
- my ($scope,$ident) = @_;
- while ($scope) {
- my $vl = $scope->{values};
- if (defined($vl->{$ident})) {
- return $vl->{$ident}->{value};
- }
- $scope = $scope->{scope};
- }
- return undef();
- }
-
- sub lookup_type($$) {
- my ($scope,$ident) = @_;
- if ($basictypes{$ident}) {
- return {scope=>$scope, basic=>1, name=>$ident, size=>$basictypes{$ident} };
- }
- while ($scope) {
- if ($basictypes{$ident}) {
- return {scope=>$scope, basic=>1, name=>$ident, size=>$basictypes{$ident} };
- }
- my $el = $scope->{enums};
- my $cl = $scope->{classes};
- my $td = $scope->{typedefs};
- if (grep {$_ eq $ident} @$el) {
- return {scope=>$scope, enum=>1, name=>$ident, size=>4 };
- }
- my @match_class = (grep {$_->{name} eq $ident} @$cl);
- if (scalar(@match_class)) {
- return {scope=>$scope, class=>$match_class[0]};
- }
- my @match_td = (grep {$_->{name} eq $ident} @$td);
- if (scalar(@match_td)) {
- my $tdr = $match_td[0];
- my $cat = $tdr->{category};
- if ($cat eq 'basic' or $cat eq 'enum' or $cat eq 'class') {
- $ident = $tdr->{alias};
- next;
- } else {
- return { scope=>$scope, $cat=>1, $size=>$tdr->{size} };
- }
- }
- $scope = $scope->{scope};
- }
- return undef();
- }
-
- sub get_mult_expr($$$) {
- my ($scope,$tokens,$line) = @_;
- my $x = get_operand($scope,$tokens,$line);
- my $t;
- for (;;) {
- $t = get_token($scope,$tokens,$line);
- if ($t eq '*') {
- my $y = get_operand($scope,$tokens,$line);
- $x = $x * $y;
- } elsif ($t eq '/') {
- my $y = get_operand($scope,$tokens,$line);
- if ($y != 0)
- {$x = int($x / $y);}
- } elsif ($t eq '%') {
- my $y = get_operand($scope,$tokens,$line);
- if ($y != 0)
- {$x = int($x % $y);}
- } else {
- last;
- }
- }
- unshift @$tokens, $t;
- return $x;
- }
-
- sub get_add_expr($$$) {
- my ($scope,$tokens,$line) = @_;
- my $x = get_mult_expr($scope,$tokens,$line);
- my $t;
- for (;;) {
- $t = get_token($scope,$tokens,$line);
- if ($t eq '+') {
- my $y = get_mult_expr($scope,$tokens,$line);
- $x = $x + $y;
- } elsif ($t eq '-') {
- my $y = get_mult_expr($scope,$tokens,$line);
- $x = $x - $y;
- } else {
- last;
- }
- }
- unshift @$tokens, $t;
- return $x;
- }
-
- sub get_shift_expr($$$) {
- my ($scope,$tokens,$line) = @_;
- my $x = get_add_expr($scope,$tokens,$line);
- my $t, $t2;
- for (;;) {
- $t = get_token($scope,$tokens,$line);
- if ($t eq '<' or $t eq '>') {
- $t2 = get_token($scope,$tokens,$line);
- if ($t2 ne $t) {
- unshift @$tokens, $t2;
- last;
- }
- }
- if ($t eq '<') {
- my $y = get_add_expr($scope,$tokens,$line);
- $x = $x << $y;
- } elsif ($t eq '>') {
- my $y = get_add_expr($scope,$tokens,$line);
- $x = $x >> $y;
- } else {
- last;
- }
- }
- unshift @$tokens, $t;
- return $x;
- }
-
- sub get_and_expr($$$) {
- my ($scope,$tokens,$line) = @_;
- my $x = get_shift_expr($scope,$tokens,$line);
- my $t;
- for (;;) {
- $t = get_token($scope,$tokens,$line);
- if ($t eq '&') {
- my $y = get_shift_expr($scope,$tokens,$line);
- $x = $x & $y;
- } else {
- last;
- }
- }
- unshift @$tokens, $t;
- return $x;
- }
-
- sub get_xor_expr($$$) {
- my ($scope,$tokens,$line) = @_;
- my $x = get_and_expr($scope,$tokens,$line);
- my $t;
- for (;;) {
- $t = get_token($scope,$tokens,$line);
- if ($t eq '^') {
- my $y = get_and_expr($scope,$tokens,$line);
- $x = $x ^ $y;
- } else {
- last;
- }
- }
- unshift @$tokens, $t;
- return $x;
- }
-
- sub get_ior_expr($$$) {
- my ($scope,$tokens,$line) = @_;
- my $x = get_xor_expr($scope,$tokens,$line);
- my $t;
- for (;;) {
- $t = get_token($scope,$tokens,$line);
- if ($t eq '|') {
- my $y = get_xor_expr($scope,$tokens,$line);
- $x = $x | $y;
- } else {
- last;
- }
- }
- unshift @$tokens, $t;
- return $x;
- }
-
- sub get_constant_expr($$$) {
- my ($scope,$tokens,$line) = @_;
- my $x = get_ior_expr($scope,$tokens,$line);
- return $x;
- }
-
- sub parse_enum($$$$) {
- my ($scope,$tokens,$line,$enum_name) = @_;
- my $vl = $scope->{values};
- my $fstr = $scope->{formatStrings};
- my $fcat = $scope->{formatCategories};
- my $fmtTable = $scope->{FormatTables};
-
- my $x = 0;
- for (;;) {
- my $t = get_token($scope,$tokens,$line);
- last if ($t eq '}');
- if (!defined($t)) {
- die "Unexpected end of file #2 at line $$line\n";
- }
-
- if ($t eq '#') {
- next;
- }
-
- if ($t !~ /^\w+$/) {
- warn "Syntax error#11 at line $$line\n";
- next;
- }
-
- if ($scope->{name})
- {
- $t = $scope->{name} . "::" . $t;
- }
-
- if (defined($vl->{$t})) {
- warn "Duplicate identifier [$t] at line $$line\n";
- }
- my $t2 = get_token($scope,$tokens,$line);
- if ($t2 eq ',') {
- $vl->{$t} = {type=>$enum_name, size=>4, value=>$x, enum=>1};
- $fstr->{$t} = $CurrentTraceFormatString;
- $fcat->{$t} = $CurrentTraceFormatCategory;
- if (defined $CurrentTraceFormatCategory && defined $CurrentTraceFormatString)
- { $fmtTable->{$CurrentTraceFormatCategory}{$x} = $CurrentTraceFormatString; }
- undef $CurrentTraceFormatString;
- ++$x;
- } elsif ($t2 eq '}') {
- $vl->{$t} = {type=>$enum_name, size=>4, value=>$x, enum=>1};
- $fstr->{$t} = $CurrentTraceFormatString;
- $fcat->{$t} = $CurrentTraceFormatCategory;
- if (defined $CurrentTraceFormatCategory && defined $CurrentTraceFormatString)
- { $fmtTable->{$CurrentTraceFormatCategory}{$x} = $CurrentTraceFormatString; }
- undef $CurrentTraceFormatString;
- ++$x;
- last;
- } elsif ($t2 eq '=') {
- $x = get_constant_expr($scope, $tokens, $line);
- $vl->{$t} = {type=>$enum_name, size=>4, value=>$x, enum=>1};
- $fstr->{$t} = $CurrentTraceFormatString;
- $fcat->{$t} = $CurrentTraceFormatCategory;
- if (defined $CurrentTraceFormatCategory && defined $CurrentTraceFormatString)
- { $fmtTable->{$CurrentTraceFormatCategory}{$x} = $CurrentTraceFormatString; }
- undef $CurrentTraceFormatString;
- ++$x;
- $t2 = get_token($scope,$tokens,$line);
- last if ($t2 eq '}');
- next if ($t2 eq ',');
- warn "Syntax error#12 at line $$line\n";
- } else {
- unshift @$tokens, $t2;
- }
- }
- my $t = get_token($scope,$tokens,$line);
- if ($t ne ';') {
- warn "Missing ; at line $$line\n";
- }
- }
-
-
- sub parse_decl_def($$$) {
- my ($scope,$tokens,$line) = @_;
- my $level=0;
- my @decl;
- while ( scalar(@$tokens) ) {
- my $t = get_token($scope,$tokens, $line);
- if ( (!defined ($t) || $t eq ';') and ($level==0)) {
- return @decl;
- }
-
- if ($t eq "static")
- {
- next;
- }
-
- push @decl, $t;
- if ($t eq '{') {
- ++$level;
- }
- if ($t eq '}') {
- if ($level==0) {
- warn "Syntax error#13 at line $$line\n";
- unshift @$tokens, $t;
- return @decl;
-
- }
- if (--$level==0) {
- return (); # end of function definition reached
- }
- }
- }
- die "Unexpected end of file #3 at line $$line\n";
- }
-
- sub dump_scope($) {
- my ($scope) = @_;
- my $el = $scope->{enums};
- my $cl = $scope->{classes};
- my $vl = $scope->{values};
- my $fstr = $scope->{formatStrings};
- my $fcat = $scope->{formatCategories};
- print "SCOPE: $scope->{name}\n";
- if (scalar(@$el)) {
- print "\tenums:\n";
- foreach (@$el) {
- print "\t\t$_\n";
- }
- }
- if (scalar(keys(%$vl))) {
- print "\tvalues:\n";
- foreach $vname (keys(%$vl)) {
- my $v = $vl->{$vname};
- my $x = $v->{value};
- my $t = $v->{type};
- my $sz = $v->{size};
- my $fstring = $fstr->{$vname};
- my $fcategory = $fcat->{$vname};
- if ($v->{enum}) {
- printf ("\t\t$vname\=$x (enum $t) size=$sz fcat=[0x%x] fstr=[%s]\n", $fcategory,$fstring);
- } else {
- printf ("\t\t$vname\=$x (type $t) size=$sz fcat=[0x%x] fstr=[%s]\n", $fcategory, $fstring);
- }
- }
- }
- if ($scope->{scope}) {
- my $members = $scope->{members};
- foreach (@$members) {
- my $n = $_->{name};
- my $sz = $_->{size};
- my $off = $_->{offset};
- my $spc = $_->{spacing};
- if (defined $spc) {
- print "\t$n\[\]\: spacing $spc size $sz offset $off\n";
- } else {
- print "\t$n\: size $sz offset $off\n";
- }
- }
- print "\tOverall size : $scope->{size}\n";
- print "\tOverall align: $scope->{align}\n";
- }
- foreach $s (@$cl) {
- dump_scope($s);
- }
- }
-
-
-
-
- sub parse_doxygen($$$$) {
- my ($scope,$tokens,$line,$t) = @_;
-
- if ($t ne "/")
- {
- return 0; # not a doxygen comment
- }
- if ($t eq "/") {
- $state=0;
- my $t2 = shift @$tokens;
- my $t3 = shift @$tokens;
-
- if ($t2 ne "*" || $t3 ne "*")
- {
- unshift @$tokens, $t3;
- unshift @$tokens, $t2;
- return 0; # not a doxygen comment
- }
- }
-# printf "doxygen start on line %d\n", $$line;
- for (;;) {
- my $t = shift @$tokens;
- if (!defined($t))
- {
- warn "Unexpected end of file #4 at line $$line\n";
- return
- }
-
- if ($t eq "\n"){++$$line };
-
- if ($t eq '*')
- {
- my $t2 = shift @$tokens;
- last if ($t2 eq '/');
- unshift @$tokens, $t2;
- }
-
- if ($t eq '@')
- {
- my $t2 = shift @$tokens;
- if ($t2 eq 'SYMTraceFormatString')
- {
- my $t3 = shift @$tokens;
-# if ($VerboseMode){print "SYMTraceFormatString = [$t3]\n";}
- $CurrentTraceFormatString = $t3;
- }
- if ($t2 eq 'SYMTraceFormatCategory')
- {
- $CurrentTraceFormatCategory = get_operand($scope,$tokens,$line);
-# if ($VerboseMode){printf ("SYMTraceFormatCategory = 0x%x\n", $CurrentTraceFormatCategory);}
- }
- else
- {
- unshift @$tokens, $t2;
- }
- }
-
- }
-# printf ("doxygen end on line %d\n", $$line);
- return 1; # is a doxygen comment
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-