371 lines
11 KiB
Perl
371 lines
11 KiB
Perl
|
|
#Copyright (c) 1992-2000 Microsoft Corporation
|
|
#
|
|
#Module Name:
|
|
#
|
|
# gnbugcds.pl
|
|
#
|
|
#Abstract:
|
|
#
|
|
# WinDbg Extension Api
|
|
#
|
|
#Environment:
|
|
#
|
|
# User Mode.
|
|
#
|
|
#Revision History:
|
|
#
|
|
# Kshitix K. Sharma (kksharma)
|
|
#
|
|
#
|
|
# Parse bugcodes.txt file to generate C-relevant info for bugcheck codes
|
|
#
|
|
# Expected format of a bugcheck description:
|
|
#
|
|
# BUGCHECK
|
|
# <bugcheck name> (<numericvalue>)
|
|
# optional - <multiline description string about bugcheck>
|
|
# optional - PARAMETERS <parameters description as follows>
|
|
# Param [1|2|3|4] - <string>
|
|
# OR
|
|
# Param [1|2|3|4]
|
|
# VALUES:
|
|
# [<value> : <Rest of parameter description>]*
|
|
# END_VALUES <required only in case of nesting>
|
|
#DESCRIPTION
|
|
#<additional description string>
|
|
#
|
|
|
|
sub emit_file_header;
|
|
sub emit_bugcheck_info;
|
|
sub emit_param_info;
|
|
sub next_line;
|
|
sub is_new_bugcheck;
|
|
sub is_bugcheck_description;
|
|
|
|
|
|
#
|
|
# main
|
|
#
|
|
$NumLine = 0;
|
|
@BugCheckList = {};
|
|
@FullParamDesc = {"", "", "", ""};
|
|
$ParamValueRec = {
|
|
VALUE => 0,
|
|
PARAMID => -1,
|
|
PARAM1DESC => "",
|
|
PARAM2DESC => "",
|
|
PARAM3DESC => "",
|
|
PARAM4DESC => "",
|
|
};
|
|
@ParamValueRecList = {};
|
|
|
|
while ($arg = shift) {
|
|
if ($arg eq "-o") {
|
|
$OutFileName = shift;
|
|
} elsif ($arg eq "-i") {
|
|
$BugCheckTxtFile = shift;
|
|
} else {
|
|
$BugCheckTxtFile = $arg;
|
|
}
|
|
}
|
|
|
|
die "Cannot open file $BugCheckTxtFile\n" if !open(BUGC_FILE, $BugCheckTxtFile);
|
|
|
|
emit_file_header();
|
|
|
|
while (is_new_bugcheck() || next_line ) {
|
|
$line = $_ if !is_new_bugcheck();
|
|
if (is_new_bugcheck()) {
|
|
emit_bugcheck_info;
|
|
}
|
|
} continue {
|
|
close BUGC_FILE if eof;
|
|
}
|
|
# emit a list of APIS for quick reference
|
|
print OUT_FILE "BUGDESC_APIREFS g_BugDescApiRefs[] = {\n";
|
|
for $i(1..$#BugCheckList) {
|
|
printf (OUT_FILE " { %30s, &BugCheck%s},\n", $BugCheckList[ $i ], $BugCheckList[ $i ]);
|
|
}
|
|
print OUT_FILE "};\n";
|
|
print OUT_FILE "ULONG g_NumBugDescApiRefs = sizeof(g_BugDescApiRefs) / sizeof(BUGDESC_APIREFS);\n";
|
|
|
|
#
|
|
# Subroutines
|
|
#
|
|
sub is_new_bugcheck {
|
|
if ($line =~ /^BUGCHECK$/) {
|
|
next_line;
|
|
}
|
|
if ($line =~ /^([A-Z][A-Z_0-9]+)\s*\((.*)\)$/) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub is_bugcheck_description {
|
|
if ($line =~ /^DESCRIPTION\s*$/) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
sub emit_file_header {
|
|
|
|
die "Cannot open file $OutFileName\n" if !open(OUT_FILE, ">" . $OutFileName);
|
|
|
|
print OUT_FILE "//-------------------------------------".
|
|
"--------------------------------------\n";
|
|
print OUT_FILE "//\n";
|
|
print OUT_FILE "// IMPORTANT: This file is automatically generated.\n";
|
|
print OUT_FILE "// Do not edit by hand.\n";
|
|
print OUT_FILE "//\n";
|
|
print OUT_FILE "// Generated from $BugCheckTxtFile " . localtime() . "\n";
|
|
print OUT_FILE "//\n";
|
|
print OUT_FILE "//-------------------------------------".
|
|
"--------------------------------------\n\n";
|
|
print OUT_FILE "#include \"precomp.h\"\n";
|
|
|
|
print OUT_FILE "\n\n";
|
|
}
|
|
|
|
sub emit_bugcheck_header {
|
|
print OUT_FILE "//\n";
|
|
print OUT_FILE "// DescriptionRoutine for $_[0] ($_[1])\n";
|
|
print OUT_FILE "//\n";
|
|
print OUT_FILE "void\nBugCheck$_[0] ( \n";
|
|
print OUT_FILE " PBUGCHECK_ANALYSIS pBugCheck\n";
|
|
print OUT_FILE " )\n";
|
|
print OUT_FILE "{\n";
|
|
print OUT_FILE " ULONG Value = $_[0];\n";
|
|
print OUT_FILE " PCHAR BugName = \"$_[0]\";\n";
|
|
print OUT_FILE " PCHAR Description = NULL, ParamDesc[4] = {0};\n\n";
|
|
}
|
|
|
|
sub init_param_array {
|
|
for $i (0..3) {
|
|
if ($FullParamDesc[ $i ] =~ /.+/) { # Non NULL values only
|
|
print OUT_FILE "$_[0]$FullParamDesc[ $i ];\n";
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
sub begin_first_value {
|
|
# $_[0] -> Argument index
|
|
# $_[1] -> Argument value
|
|
print OUT_FILE "$_[2]if (pBugCheck->Args[ $_[0] ] == $_[1]) {\n";
|
|
}
|
|
|
|
sub begin_intermediate_value {
|
|
# $_[0] -> Argument index
|
|
# $_[1] -> Argument value
|
|
# $_[2] -> Indent
|
|
init_param_array($_[2]);
|
|
print OUT_FILE "$_[2]} else if (pBugCheck->Args[ $_[0] ] == $_[1]) {\n";
|
|
}
|
|
|
|
sub begin_intermediate_value_parent {
|
|
# $_[0] -> Argument index
|
|
# $_[1] -> Argument value
|
|
# $_[2] -> Indent
|
|
print OUT_FILE "$_[2]} else if (pBugCheck->Args[ $_[0] ] == $_[1]) {\n";
|
|
}
|
|
|
|
sub end_value {
|
|
# $_[0] -> Indent
|
|
init_param_array($_[0]);
|
|
print OUT_FILE "$_[0]}\n";
|
|
}
|
|
|
|
sub emit_bugcheck_end {
|
|
print OUT_FILE " pBugCheck->Code = Value;\n";
|
|
print OUT_FILE " pBugCheck->szName = BugName;\n";
|
|
print OUT_FILE " pBugCheck->szDescription = Description;\n";
|
|
print OUT_FILE " pBugCheck->szParamsDesc[0] = ParamDesc[0];\n";
|
|
print OUT_FILE " pBugCheck->szParamsDesc[1] = ParamDesc[1];\n";
|
|
print OUT_FILE " pBugCheck->szParamsDesc[2] = ParamDesc[2];\n";
|
|
print OUT_FILE " pBugCheck->szParamsDesc[3] = ParamDesc[3];\n";
|
|
print OUT_FILE "\n}\n\n";
|
|
}
|
|
|
|
#
|
|
# Match the folowing here
|
|
# <BugName> (<num>)
|
|
# <description>
|
|
# <parameters> - done by emit_param_info
|
|
# <more description>
|
|
#
|
|
sub emit_bugcheck_info {
|
|
die "No name Info on line $NumLine\n" if !($BugNameLine = $line) ;
|
|
if (($Name,$Value) = $BugNameLine =~ /^([A-Z][A-Z_0-9]+)\s*\((.*)\)$/) {
|
|
emit_bugcheck_header ( $Name, $Value );
|
|
push (@BugCheckList, $Name);
|
|
|
|
$FullDesc = " Description = ";
|
|
$DescPrinted = 0;
|
|
while (next_line && (!is_new_bugcheck()) && ($line !~ /^\s*PARAMETERS\s*.*$/)) {
|
|
if ($line !~ /^\s*$/) {
|
|
($Desc) = $line =~ /^(.*)\s*$/;
|
|
if ($DescPrinted) {
|
|
$FullDesc = $FullDesc . "\n\t";
|
|
}
|
|
($Desc) =~ s/([\\"])/\\$1/g ;
|
|
$FullDesc = $FullDesc . "\"$Desc\\n\"";
|
|
$DescPrinted++;
|
|
}
|
|
}
|
|
$MoreDesc = 0;
|
|
if ($line =~ /^\s*PARAMETERS\s*.*$/) {
|
|
($line) = $line =~ /^\s*PARAMETERS\s*(.*)$/;
|
|
if (!$line) {
|
|
next_line;
|
|
}
|
|
$MoreDesc = emit_param_info;
|
|
}
|
|
|
|
if ($MoreDesc) {
|
|
# BugCheck description string following parameter description
|
|
while (next_line && (!is_new_bugcheck())) {
|
|
if ($line !~ /^\s*$/) {
|
|
($Desc) = $line =~ /^(.*)\s*$/;
|
|
if ($DescPrinted) {
|
|
$FullDesc = $FullDesc . "\n\t";
|
|
}
|
|
($Desc) =~ s/([\\"])/\\$1/g ;
|
|
$FullDesc = $FullDesc . "\"$Desc\\n\"";
|
|
$DescPrinted++;
|
|
}
|
|
}
|
|
}
|
|
if (!$DescPrinted) { $FullDesc = $FullDesc . "\"\"";}
|
|
print OUT_FILE $FullDesc . ";\n";
|
|
emit_bugcheck_end ;
|
|
} else {
|
|
print "Bad name Info on line $NumLine - $BugNameLine\n"
|
|
}
|
|
}
|
|
|
|
|
|
sub emit_param_info {
|
|
@FullParamDesc = {"", "", "", ""};
|
|
$ParamValueDefined = -1;
|
|
$IsFirstValue = 1;
|
|
@ParamValueRecList = {};
|
|
$Level = 0;
|
|
$MovedLevelUp = 0;
|
|
$FullParamDesc[ 0 ] = "";
|
|
$FullParamDesc[ 1 ] = "";
|
|
$FullParamDesc[ 2 ] = "";
|
|
$FullParamDesc[ 3 ] = "";
|
|
|
|
while (!is_new_bugcheck() && !is_bugcheck_description() && $line) {
|
|
if ($line !~ /^\s*$/) {
|
|
($ParamPrefix, $ParamId, $ParamDesc) = $line =~ /^\s*(\w*)\s*([1234])\s*-\s*(.*)$/;
|
|
if ($ParamId && ($ParamPrefix == "" || $ParamPrefix == "Param" || $ParamPrefix == "Arg" ||
|
|
$ParamPrefix == "Parameter" || $ParamPrefix == "Argument")) {
|
|
|
|
($ParamDesc) =~ s/([\\"])/\\$1/g ;
|
|
$ParamId--; # 0 based index
|
|
$FullParamDesc[ $ParamId ] = " ParamDesc[ $ParamId ] = \"$ParamDesc\"";
|
|
$LastParamId = $ParamId;
|
|
|
|
} elsif ($line =~ /^\s*VALUES\s*:?\s*$/) {
|
|
|
|
# emit the parameter description we have so far since the folowing
|
|
# ones would be relevant to specific values only.
|
|
# code path will automatically remember these if they are not defined later
|
|
init_param_array(" " x ($Level * 4));
|
|
|
|
$ParamValueDefined = $LastParamId;
|
|
$IsFirstValue = 1;
|
|
$ParamValueRec = {
|
|
VALUE => 0,
|
|
PARAMID => $LastParamId,
|
|
PARAM1DESC => $FullParamDesc[ 0 ],
|
|
PARAM2DESC => $FullParamDesc[ 1 ],
|
|
PARAM3DESC => $FullParamDesc[ 2 ],
|
|
PARAM4DESC => $FullParamDesc[ 3 ],
|
|
};
|
|
push (@ParamValueRecList, ($ParamValueRec));
|
|
$Level = $#ParamValueRecList;
|
|
|
|
} elsif ($line =~ /^\s*END_VALUES\s*$/) {
|
|
|
|
$Level = $#ParamValueRecList;
|
|
end_value(" " x ($Level * 4));
|
|
|
|
$IsFirstValue = 0;
|
|
$MovedLevelUp = 1;
|
|
# restore what we had whe we saw VALUES clause
|
|
$LastParamId = $ParamValueRecList[$Level-1]{PARAMID};
|
|
$FullParamDesc[ 0 ] = $ParamValueRecList[$Level-1]{PARAM1DESC};
|
|
$FullParamDesc[ 1 ] = $ParamValueRecList[$Level-1]{PARAM2DESC};
|
|
$FullParamDesc[ 2 ] = $ParamValueRecList[$Level-1]{PARAM3DESC};
|
|
$FullParamDesc[ 3 ] = $ParamValueRecList[$Level-1]{PARAM4DESC};
|
|
if ($Level) {
|
|
pop( @ParamValueRecList );
|
|
} else {
|
|
die "No preivious VALUE clause for END_VALUES on line $NumLine\n";
|
|
}
|
|
$ParamValueDefined = $LastParamId;
|
|
$Level = $#ParamValueRecList;
|
|
if ($Level == 0) {
|
|
$ParamValueDefined = -1;
|
|
}
|
|
} elsif (($ParamValueDefined != -1) &&
|
|
(($Value) = $line =~ /^\s*(0?x?[0-9A-Fa-f]*)\s*:.*$/)) {
|
|
#matched "<Value> : <text>"
|
|
if ($Value !~ /0x.*/) {
|
|
# prepend 0x
|
|
$Value = "0x" . $Value;
|
|
}
|
|
if ($IsFirstValue) {
|
|
$IsFirstValue = 0;
|
|
begin_first_value($ParamValueDefined, $Value, " " x ($Level * 4));
|
|
} elsif ($MovedLevelUp) {
|
|
$MovedLevelUp = 0;
|
|
begin_intermediate_value_parent($ParamValueDefined, $Value, " " x ($Level * 4));
|
|
} else {
|
|
begin_intermediate_value($ParamValueDefined, $Value, " " x ($Level * 4));
|
|
}
|
|
|
|
$ParamDesc = $FullParamDesc[ $ParamValueDefined ];
|
|
|
|
if (($Desc) = $line =~ /^\s*0?x?[0-9A-Fa-f]*\s*:\s*(.*)$/) {
|
|
($Desc) =~ s/([\\"])/\\$1/g ;
|
|
$FullParamDesc[ $ParamValueDefined ] = " ParamDesc[ $ParamValueDefined ] = \"$Desc\"";
|
|
} else {
|
|
$FullParamDesc[ $ParamValueDefined ] = $ParamDesc;
|
|
}
|
|
} else {
|
|
($line) = $line =~ /^\s*(.*)$/;
|
|
($line) =~ s/([\\"])/\\$1/g ; #"/# escape chars
|
|
$temp = "\\n\"";
|
|
$FullParamDesc[ $LastParamId ] = $FullParamDesc[ $LastParamId ] . "\n \"\\n$line\"";
|
|
}
|
|
}
|
|
$line = next_line;
|
|
}
|
|
|
|
if ($ParamValueDefined != -1) {
|
|
end_value(" " x (4));
|
|
} else {
|
|
init_param_array("");
|
|
}
|
|
|
|
$MoreDesc = is_bugcheck_description();
|
|
|
|
return $MoreDesc;
|
|
}
|
|
|
|
sub next_line {
|
|
$line = <BUGC_FILE>;
|
|
$NumLine++;
|
|
while ($line =~ /\s*\%.*$/) {
|
|
# Skip commented lines - ones which beging with %
|
|
$line = <BUGC_FILE>;
|
|
$NumLine++;
|
|
}
|
|
return $line;
|
|
}
|