Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
11 KiB

  1. #Copyright (c) 1992-2000 Microsoft Corporation
  2. #
  3. #Module Name:
  4. #
  5. # gnbugcds.pl
  6. #
  7. #Abstract:
  8. #
  9. # WinDbg Extension Api
  10. #
  11. #Environment:
  12. #
  13. # User Mode.
  14. #
  15. #Revision History:
  16. #
  17. # Kshitix K. Sharma (kksharma)
  18. #
  19. #
  20. # Parse bugcodes.txt file to generate C-relevant info for bugcheck codes
  21. #
  22. # Expected format of a bugcheck description:
  23. #
  24. # BUGCHECK
  25. # <bugcheck name> (<numericvalue>)
  26. # optional - <multiline description string about bugcheck>
  27. # optional - PARAMETERS <parameters description as follows>
  28. # Param [1|2|3|4] - <string>
  29. # OR
  30. # Param [1|2|3|4]
  31. # VALUES:
  32. # [<value> : <Rest of parameter description>]*
  33. # END_VALUES <required only in case of nesting>
  34. #DESCRIPTION
  35. #<additional description string>
  36. #
  37. sub emit_file_header;
  38. sub emit_bugcheck_info;
  39. sub emit_param_info;
  40. sub next_line;
  41. sub is_new_bugcheck;
  42. sub is_bugcheck_description;
  43. #
  44. # main
  45. #
  46. $NumLine = 0;
  47. @BugCheckList = {};
  48. @FullParamDesc = {"", "", "", ""};
  49. $ParamValueRec = {
  50. VALUE => 0,
  51. PARAMID => -1,
  52. PARAM1DESC => "",
  53. PARAM2DESC => "",
  54. PARAM3DESC => "",
  55. PARAM4DESC => "",
  56. };
  57. @ParamValueRecList = {};
  58. while ($arg = shift) {
  59. if ($arg eq "-o") {
  60. $OutFileName = shift;
  61. } elsif ($arg eq "-i") {
  62. $BugCheckTxtFile = shift;
  63. } else {
  64. $BugCheckTxtFile = $arg;
  65. }
  66. }
  67. die "Cannot open file $BugCheckTxtFile\n" if !open(BUGC_FILE, $BugCheckTxtFile);
  68. emit_file_header();
  69. while (is_new_bugcheck() || next_line ) {
  70. $line = $_ if !is_new_bugcheck();
  71. if (is_new_bugcheck()) {
  72. emit_bugcheck_info;
  73. }
  74. } continue {
  75. close BUGC_FILE if eof;
  76. }
  77. # emit a list of APIS for quick reference
  78. print OUT_FILE "BUGDESC_APIREFS g_BugDescApiRefs[] = {\n";
  79. for $i(1..$#BugCheckList) {
  80. printf (OUT_FILE " { %30s, &BugCheck%s},\n", $BugCheckList[ $i ], $BugCheckList[ $i ]);
  81. }
  82. print OUT_FILE "};\n";
  83. print OUT_FILE "ULONG g_NumBugDescApiRefs = sizeof(g_BugDescApiRefs) / sizeof(BUGDESC_APIREFS);\n";
  84. #
  85. # Subroutines
  86. #
  87. sub is_new_bugcheck {
  88. if ($line =~ /^BUGCHECK$/) {
  89. next_line;
  90. }
  91. if ($line =~ /^([A-Z][A-Z_0-9]+)\s*\((.*)\)$/) {
  92. return 1;
  93. }
  94. return 0;
  95. }
  96. sub is_bugcheck_description {
  97. if ($line =~ /^DESCRIPTION\s*$/) {
  98. return 1;
  99. }
  100. return 0;
  101. }
  102. sub emit_file_header {
  103. die "Cannot open file $OutFileName\n" if !open(OUT_FILE, ">" . $OutFileName);
  104. print OUT_FILE "//-------------------------------------".
  105. "--------------------------------------\n";
  106. print OUT_FILE "//\n";
  107. print OUT_FILE "// IMPORTANT: This file is automatically generated.\n";
  108. print OUT_FILE "// Do not edit by hand.\n";
  109. print OUT_FILE "//\n";
  110. print OUT_FILE "// Generated from $BugCheckTxtFile " . localtime() . "\n";
  111. print OUT_FILE "//\n";
  112. print OUT_FILE "//-------------------------------------".
  113. "--------------------------------------\n\n";
  114. print OUT_FILE "#include \"precomp.h\"\n";
  115. print OUT_FILE "\n\n";
  116. }
  117. sub emit_bugcheck_header {
  118. print OUT_FILE "//\n";
  119. print OUT_FILE "// DescriptionRoutine for $_[0] ($_[1])\n";
  120. print OUT_FILE "//\n";
  121. print OUT_FILE "void\nBugCheck$_[0] ( \n";
  122. print OUT_FILE " PBUGCHECK_ANALYSIS pBugCheck\n";
  123. print OUT_FILE " )\n";
  124. print OUT_FILE "{\n";
  125. print OUT_FILE " ULONG Value = $_[0];\n";
  126. print OUT_FILE " PCHAR BugName = \"$_[0]\";\n";
  127. print OUT_FILE " PCHAR Description = NULL, ParamDesc[4] = {0};\n\n";
  128. }
  129. sub init_param_array {
  130. for $i (0..3) {
  131. if ($FullParamDesc[ $i ] =~ /.+/) { # Non NULL values only
  132. print OUT_FILE "$_[0]$FullParamDesc[ $i ];\n";
  133. }
  134. }
  135. }
  136. sub begin_first_value {
  137. # $_[0] -> Argument index
  138. # $_[1] -> Argument value
  139. print OUT_FILE "$_[2]if (pBugCheck->Args[ $_[0] ] == $_[1]) {\n";
  140. }
  141. sub begin_intermediate_value {
  142. # $_[0] -> Argument index
  143. # $_[1] -> Argument value
  144. # $_[2] -> Indent
  145. init_param_array($_[2]);
  146. print OUT_FILE "$_[2]} else if (pBugCheck->Args[ $_[0] ] == $_[1]) {\n";
  147. }
  148. sub begin_intermediate_value_parent {
  149. # $_[0] -> Argument index
  150. # $_[1] -> Argument value
  151. # $_[2] -> Indent
  152. print OUT_FILE "$_[2]} else if (pBugCheck->Args[ $_[0] ] == $_[1]) {\n";
  153. }
  154. sub end_value {
  155. # $_[0] -> Indent
  156. init_param_array($_[0]);
  157. print OUT_FILE "$_[0]}\n";
  158. }
  159. sub emit_bugcheck_end {
  160. print OUT_FILE " pBugCheck->Code = Value;\n";
  161. print OUT_FILE " pBugCheck->szName = BugName;\n";
  162. print OUT_FILE " pBugCheck->szDescription = Description;\n";
  163. print OUT_FILE " pBugCheck->szParamsDesc[0] = ParamDesc[0];\n";
  164. print OUT_FILE " pBugCheck->szParamsDesc[1] = ParamDesc[1];\n";
  165. print OUT_FILE " pBugCheck->szParamsDesc[2] = ParamDesc[2];\n";
  166. print OUT_FILE " pBugCheck->szParamsDesc[3] = ParamDesc[3];\n";
  167. print OUT_FILE "\n}\n\n";
  168. }
  169. #
  170. # Match the folowing here
  171. # <BugName> (<num>)
  172. # <description>
  173. # <parameters> - done by emit_param_info
  174. # <more description>
  175. #
  176. sub emit_bugcheck_info {
  177. die "No name Info on line $NumLine\n" if !($BugNameLine = $line) ;
  178. if (($Name,$Value) = $BugNameLine =~ /^([A-Z][A-Z_0-9]+)\s*\((.*)\)$/) {
  179. emit_bugcheck_header ( $Name, $Value );
  180. push (@BugCheckList, $Name);
  181. $FullDesc = " Description = ";
  182. $DescPrinted = 0;
  183. while (next_line && (!is_new_bugcheck()) && ($line !~ /^\s*PARAMETERS\s*.*$/)) {
  184. if ($line !~ /^\s*$/) {
  185. ($Desc) = $line =~ /^(.*)\s*$/;
  186. if ($DescPrinted) {
  187. $FullDesc = $FullDesc . "\n\t";
  188. }
  189. ($Desc) =~ s/([\\"])/\\$1/g ;
  190. $FullDesc = $FullDesc . "\"$Desc\\n\"";
  191. $DescPrinted++;
  192. }
  193. }
  194. $MoreDesc = 0;
  195. if ($line =~ /^\s*PARAMETERS\s*.*$/) {
  196. ($line) = $line =~ /^\s*PARAMETERS\s*(.*)$/;
  197. if (!$line) {
  198. next_line;
  199. }
  200. $MoreDesc = emit_param_info;
  201. }
  202. if ($MoreDesc) {
  203. # BugCheck description string following parameter description
  204. while (next_line && (!is_new_bugcheck())) {
  205. if ($line !~ /^\s*$/) {
  206. ($Desc) = $line =~ /^(.*)\s*$/;
  207. if ($DescPrinted) {
  208. $FullDesc = $FullDesc . "\n\t";
  209. }
  210. ($Desc) =~ s/([\\"])/\\$1/g ;
  211. $FullDesc = $FullDesc . "\"$Desc\\n\"";
  212. $DescPrinted++;
  213. }
  214. }
  215. }
  216. if (!$DescPrinted) { $FullDesc = $FullDesc . "\"\"";}
  217. print OUT_FILE $FullDesc . ";\n";
  218. emit_bugcheck_end ;
  219. } else {
  220. print "Bad name Info on line $NumLine - $BugNameLine\n"
  221. }
  222. }
  223. sub emit_param_info {
  224. @FullParamDesc = {"", "", "", ""};
  225. $ParamValueDefined = -1;
  226. $IsFirstValue = 1;
  227. @ParamValueRecList = {};
  228. $Level = 0;
  229. $MovedLevelUp = 0;
  230. $FullParamDesc[ 0 ] = "";
  231. $FullParamDesc[ 1 ] = "";
  232. $FullParamDesc[ 2 ] = "";
  233. $FullParamDesc[ 3 ] = "";
  234. while (!is_new_bugcheck() && !is_bugcheck_description() && $line) {
  235. if ($line !~ /^\s*$/) {
  236. ($ParamPrefix, $ParamId, $ParamDesc) = $line =~ /^\s*(\w*)\s*([1234])\s*-\s*(.*)$/;
  237. if ($ParamId && ($ParamPrefix == "" || $ParamPrefix == "Param" || $ParamPrefix == "Arg" ||
  238. $ParamPrefix == "Parameter" || $ParamPrefix == "Argument")) {
  239. ($ParamDesc) =~ s/([\\"])/\\$1/g ;
  240. $ParamId--; # 0 based index
  241. $FullParamDesc[ $ParamId ] = " ParamDesc[ $ParamId ] = \"$ParamDesc\"";
  242. $LastParamId = $ParamId;
  243. } elsif ($line =~ /^\s*VALUES\s*:?\s*$/) {
  244. # emit the parameter description we have so far since the folowing
  245. # ones would be relevant to specific values only.
  246. # code path will automatically remember these if they are not defined later
  247. init_param_array(" " x ($Level * 4));
  248. $ParamValueDefined = $LastParamId;
  249. $IsFirstValue = 1;
  250. $ParamValueRec = {
  251. VALUE => 0,
  252. PARAMID => $LastParamId,
  253. PARAM1DESC => $FullParamDesc[ 0 ],
  254. PARAM2DESC => $FullParamDesc[ 1 ],
  255. PARAM3DESC => $FullParamDesc[ 2 ],
  256. PARAM4DESC => $FullParamDesc[ 3 ],
  257. };
  258. push (@ParamValueRecList, ($ParamValueRec));
  259. $Level = $#ParamValueRecList;
  260. } elsif ($line =~ /^\s*END_VALUES\s*$/) {
  261. $Level = $#ParamValueRecList;
  262. end_value(" " x ($Level * 4));
  263. $IsFirstValue = 0;
  264. $MovedLevelUp = 1;
  265. # restore what we had whe we saw VALUES clause
  266. $LastParamId = $ParamValueRecList[$Level-1]{PARAMID};
  267. $FullParamDesc[ 0 ] = $ParamValueRecList[$Level-1]{PARAM1DESC};
  268. $FullParamDesc[ 1 ] = $ParamValueRecList[$Level-1]{PARAM2DESC};
  269. $FullParamDesc[ 2 ] = $ParamValueRecList[$Level-1]{PARAM3DESC};
  270. $FullParamDesc[ 3 ] = $ParamValueRecList[$Level-1]{PARAM4DESC};
  271. if ($Level) {
  272. pop( @ParamValueRecList );
  273. } else {
  274. die "No preivious VALUE clause for END_VALUES on line $NumLine\n";
  275. }
  276. $ParamValueDefined = $LastParamId;
  277. $Level = $#ParamValueRecList;
  278. if ($Level == 0) {
  279. $ParamValueDefined = -1;
  280. }
  281. } elsif (($ParamValueDefined != -1) &&
  282. (($Value) = $line =~ /^\s*(0?x?[0-9A-Fa-f]*)\s*:.*$/)) {
  283. #matched "<Value> : <text>"
  284. if ($Value !~ /0x.*/) {
  285. # prepend 0x
  286. $Value = "0x" . $Value;
  287. }
  288. if ($IsFirstValue) {
  289. $IsFirstValue = 0;
  290. begin_first_value($ParamValueDefined, $Value, " " x ($Level * 4));
  291. } elsif ($MovedLevelUp) {
  292. $MovedLevelUp = 0;
  293. begin_intermediate_value_parent($ParamValueDefined, $Value, " " x ($Level * 4));
  294. } else {
  295. begin_intermediate_value($ParamValueDefined, $Value, " " x ($Level * 4));
  296. }
  297. $ParamDesc = $FullParamDesc[ $ParamValueDefined ];
  298. if (($Desc) = $line =~ /^\s*0?x?[0-9A-Fa-f]*\s*:\s*(.*)$/) {
  299. ($Desc) =~ s/([\\"])/\\$1/g ;
  300. $FullParamDesc[ $ParamValueDefined ] = " ParamDesc[ $ParamValueDefined ] = \"$Desc\"";
  301. } else {
  302. $FullParamDesc[ $ParamValueDefined ] = $ParamDesc;
  303. }
  304. } else {
  305. ($line) = $line =~ /^\s*(.*)$/;
  306. ($line) =~ s/([\\"])/\\$1/g ; #"/# escape chars
  307. $temp = "\\n\"";
  308. $FullParamDesc[ $LastParamId ] = $FullParamDesc[ $LastParamId ] . "\n \"\\n$line\"";
  309. }
  310. }
  311. $line = next_line;
  312. }
  313. if ($ParamValueDefined != -1) {
  314. end_value(" " x (4));
  315. } else {
  316. init_param_array("");
  317. }
  318. $MoreDesc = is_bugcheck_description();
  319. return $MoreDesc;
  320. }
  321. sub next_line {
  322. $line = <BUGC_FILE>;
  323. $NumLine++;
  324. while ($line =~ /\s*\%.*$/) {
  325. # Skip commented lines - ones which beging with %
  326. $line = <BUGC_FILE>;
  327. $NumLine++;
  328. }
  329. return $line;
  330. }