1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
<?php
class Webgrind_Preprocessor{
const FILE_FORMAT_VERSION = 5;
const NR_FORMAT = 'V';
const NR_SIZE = 4;
const ENTRY_POINT = '{main}';
private $in, $out;
function __construct($inFile, $outFile){
$this->in = fopen($inFile, 'rb');
$this->out = fopen($outFile, 'w+b');
}
function parse(){
// Make local for faster access
$in = $this->in;
$out = $this->out;
$nextFuncNr = 0;
$functions = array();
$headers = array();
// Read information into memory
while(($line = fgets($in))){
if(substr($line,0,3)==='fl='){
list($function) = fscanf($in,"fn=%s");
if(!isset($functions[$function])){
$functions[$function] = array('filename'=>substr(trim($line),3), 'invocationCount'=>0,'nr'=>$nextFuncNr++,'count'=>0,'summedSelfCost'=>0,'summedInclusiveCost'=>0,'callInformation'=>array());
}
$functions[$function]['invocationCount']++;
// Special case for {main} - it contains summary header
if(self::ENTRY_POINT == $function){
fgets($in);
$headers[] = fgets($in);
fgets($in);
}
// Cost line
list($lnr, $cost) = fscanf($in,"%d %d");
$functions[$function]['summedSelfCost'] += $cost;
$functions[$function]['summedInclusiveCost'] += $cost;
} else if(substr($line,0,4)==='cfn=') {
$calledFunctionName = substr(trim($line),4);
// Skip call line
fgets($in);
// Cost line
list($lnr, $cost) = fscanf($in,"%d %d");
$functions[$function]['summedInclusiveCost'] += $cost;
if(!isset($functions[$calledFunctionName]['callInformation'][$function.':'.$lnr]))
$functions[$calledFunctionName]['callInformation'][$function.':'.$lnr] = array('functionNr'=>$functions[$function]['nr'],'line'=>$lnr,'callCount'=>0,'summedCallCost'=>0);
$functions[$calledFunctionName]['callInformation'][$function.':'.$lnr]['callCount']++;
$functions[$calledFunctionName]['callInformation'][$function.':'.$lnr]['summedCallCost'] += $cost;
} else if(strpos($line,': ')!==false){
$headers[] = $line;
}
}
// Write output
$functionCount = sizeof($functions);
fwrite($out, pack(self::NR_FORMAT.'*', self::FILE_FORMAT_VERSION, 0, $functionCount));
// Make room for function addresses
fseek($out,self::NR_SIZE*$functionCount, SEEK_CUR);
$functionAddresses = array();
foreach($functions as $functionName => $function){
$functionAddresses[] = ftell($out);
$calledFromCount = sizeof($function['callInformation']);
fwrite($out, pack(self::NR_FORMAT.'*', $function['summedSelfCost'], $function['summedInclusiveCost'], $function['invocationCount'], $calledFromCount));
// Write call information
foreach($function['callInformation'] as $call){
fwrite($out, pack(self::NR_FORMAT.'*', $call['functionNr'], $call['line'], $call['callCount'], $call['summedCallCost']));
}
fwrite($out, $function['filename']."\n".$functionName."\n");
}
$headersPos = ftell($this->out);
// Write headers
foreach($headers as $header){
fwrite($out,$header);
}
// Write addresses
fseek($out,self::NR_SIZE, SEEK_SET);
fwrite($out, pack(self::NR_FORMAT, $headersPos));
// Skip function count
fseek($out,self::NR_SIZE, SEEK_CUR);
foreach($functionAddresses as $address){
fwrite($out, pack(self::NR_FORMAT, $address));
}
}
}
|