Leaked source code of windows server 2003
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.

298 lines
7.1 KiB

  1. # genprint.pl
  2. # Thierry Fevrier 25-Feb-2000
  3. #
  4. # Perl script to generate C code to dump typed structures.
  5. # Used initially to parse kernel header files.
  6. #
  7. # Caveats:
  8. # sorry but it is my first perl script...
  9. # and it was done very quickly to satisfy the needs
  10. # of a simple program.
  11. #
  12. require 5.001;
  13. # Forward declarations
  14. sub Usage;
  15. sub PrintTypeProlog;
  16. sub PrintTypeBody;
  17. sub PrintTypeEpilog;
  18. sub PrintType1;
  19. sub PrintTypeN;
  20. #
  21. # The following subroutines will be used in a next implementation.
  22. # This will be the functions to call to format specific types.
  23. # For now, they play the role of holding a value in the array
  24. # and have a specific name related to the type they are related to.
  25. #
  26. sub FormatLargeInteger;
  27. sub FormatUnicodeString;
  28. # Contants
  29. my $SCRIPT_VERSION = "1.00";
  30. my $GENPRINT_CMD = "genprint.pl";
  31. my $GENPRINT_VERSION = "GENPRINT.PL Version $SCRIPT_VERSION";
  32. my %TypeFormat = (
  33. "CCHAR" => "\%d",
  34. "UCHAR" => "\%d",
  35. "CHAR" => "\%d",
  36. "BOOLEAN" => "\%d",
  37. "SHORT" => "\%d",
  38. "USHORT" => "\%u",
  39. "LONG" => "\%ld",
  40. "ULONG" => "\%ld",
  41. "LONG_PTR" => "0x\%Ix",
  42. "ULONG_PTR" => "0x\%Ix",
  43. "SSIZE_T" => "0x\%Ix",
  44. "SIZE_T" => "0x\%Ix",
  45. "LONGLONG" => "0x\%I64x",
  46. "ULONGLONG" => "0x\%I64x",
  47. "PVOID" => "0x%p",
  48. "HANDLE" => "0x%p",
  49. "LARGE_INTEGER" => "FormatLargeInteger",
  50. "ULARGE_INTEGER" => "FormatLargeInteger",
  51. "UNICODE_STRING" => "FormatUnicodeString",
  52. "SYSINF_PAGE_COUNT"=> "0x\%ld",
  53. );
  54. if ($#ARGV != 1)
  55. {
  56. $error = "requires 2 arguments...";
  57. Usage($error);
  58. }
  59. my $filename = $ARGV[0];
  60. my $typedstr = $ARGV[1];
  61. if (-e $filename && -T $filename)
  62. {
  63. open(FH, "<$filename") || die "$GENPRINT_CMD: could not open $filename...\n";
  64. }
  65. else
  66. {
  67. $error = "$filename does not exist or is not a text file...";
  68. Usage($error);
  69. }
  70. while ( <FH> )
  71. {
  72. # look for the specified string
  73. if ( ($_ =~ /$typedstr/) && ($_ =~ /^typedef/) && ($_ =~ /\{/) ) {
  74. chop $_;
  75. PrintTypeProlog( $typedstr );
  76. if ( PrintTypeBody( ) )
  77. {
  78. PrintTypeEpilog( $typedstr );
  79. last;
  80. }
  81. else
  82. {
  83. print "Parsing failed...\n";
  84. }
  85. }
  86. }
  87. close(FH);
  88. exit 0;
  89. sub PrintTypeBody
  90. {
  91. # Note: in_comment is really for the section defining the structure.
  92. # I do not handle the case if the structure is inside a comment block.
  93. my $in_comment = 0;
  94. my $index = 0;
  95. LINE:
  96. while (<FH>)
  97. {
  98. local($line) = $_;
  99. #print $line;
  100. if ( $line =~ /^\s*#.*$/ ) {
  101. chop $line;
  102. #print "Found pre-processor macro \"$line\" in $typedstr...\n";
  103. print "$line\n";
  104. next LINE;
  105. }
  106. local($line) = $_;
  107. if ( $in_comment ) {
  108. # Does this line have the end of the C comment?
  109. #
  110. if ($line =~ /\*\//)
  111. {
  112. # Yes. Keep everything after the end of the
  113. # comment and keep going with normal processing
  114. $line = $';
  115. $in_comment = 0;
  116. }
  117. else
  118. {
  119. next LINE;
  120. }
  121. }
  122. # Remove single line C "/* */" comments
  123. $line =~ s/\/\*.*?\*\///g;
  124. # Remove any "//" comments
  125. # Make sure the start of the comment is NOT
  126. # inside a string
  127. if (($line =~ /\/\//) && ($line !~ /\".*?\/\/.*?\"/))
  128. {
  129. $line =~ s/\/\/.*$/ /;
  130. }
  131. # Multi-line C comment?
  132. # Make sure the start of the comment is NOT
  133. # inside a string
  134. if (($line =~ /\/\*/) && ($line !~ /\".*?\/\*.*?\"/))
  135. {
  136. # Grab anything before the comment
  137. # Need to make it look like there's still a EOL marker
  138. $line = $` . "\n";
  139. # Remember that we're in "comment" mode
  140. $in_comment = 1;
  141. next LINE;
  142. }
  143. local($line_pack) = $line;
  144. # Replace spaces between word characters with '#'
  145. $line_pack =~ s/(\w)\s+(\w)/$1#$2/g;
  146. # remove whitespace
  147. $line_pack =~ tr/ \t//d;
  148. # Remove quoted double-quote characters
  149. $line_pack =~ s/'\\?"'/'_'/g;
  150. # Remove any strings
  151. # Note: Doesn't handle quoted quote characters correctly
  152. $line_pack =~ s/"[^"]*"/_/g;
  153. # Remove any "//" comments
  154. $line_pack =~ s/\/\/.*$//;
  155. # For empty lines,
  156. if ( $line_pack eq "\n" )
  157. {
  158. next LINE;
  159. }
  160. if ( $line_pack =~ /^\}/)
  161. {
  162. return $index;
  163. }
  164. # print "line_pack: $line_pack\n";
  165. @words = split(/#/, $line_pack);
  166. local($type) = $words[0];
  167. $words[1] =~ s/;$//;
  168. chop $words[1];
  169. local($field) = $words[1];
  170. # print "type: $type field: $field\n";
  171. if ( $TypeFormat{$type} eq "" )
  172. {
  173. print "\#error genprint.pl: no print format for type $type...\n";
  174. }
  175. local($n) = 0;
  176. # if array, need to process them.
  177. if ( $field =~ s/\[(.*)\]// )
  178. {
  179. $n = $1;
  180. }
  181. elsif ( $field =~ /\[\w\]/ )
  182. {
  183. $n= $1;
  184. }
  185. # print $n;
  186. if ( $n )
  187. {
  188. print "{ int idx; for ( idx = 0; idx < $n; idx++ ) {\n";
  189. PrintTypeN( $type, $field, $n );
  190. print "} }\n";
  191. }
  192. else
  193. {
  194. PrintType1( $type, $field );
  195. }
  196. $index++;
  197. next LINE;
  198. }
  199. return 0;
  200. }
  201. sub PrintType1
  202. {
  203. local($type, $field) = @_;
  204. # FIXFIX: I can't recall the printf TypeFormat for LARGE_INTEGER...
  205. # so create a condition for that type. ugly...
  206. if ( ($type eq "LARGE_INTEGER") || ($type eq "ULARGE_INTEGER") )
  207. {
  208. print " printf(\" $field\t$TypeFormat{\"LONGLONG\"}\\n\", Str->$field.QuadPart);\n";
  209. }
  210. elsif ( $type eq "UNICODE_STRING" )
  211. {
  212. print " printf(\" $field\t\%wZ\\n\", &Str->$field);\n";
  213. }
  214. else
  215. {
  216. print " printf(\" $field\t$TypeFormat{$type}\\n\", Str->$field);\n";
  217. }
  218. }
  219. sub PrintTypeN
  220. {
  221. local($type, $field, @n) = @_;
  222. if ( ($type eq "LARGE_INTEGER") || ($type eq "ULARGE_INTEGER") )
  223. {
  224. print " printf(\" $field\[%ld\]\t$TypeFormat{\"LONGLONG\"}\\n\", idx, Str->$field\[idx\].QuadPart);\n";
  225. }
  226. elsif ( $type eq "UNICODE_STRING")
  227. {
  228. print " printf(\" $field\t\%wZ\\n\", &Str->$field);\n";
  229. }
  230. else
  231. {
  232. print " printf(\" $field\[%ld\]\t$TypeFormat{$type}\\n\", idx, Str->$field\[idx\]);\n";
  233. }
  234. }
  235. sub PrintTypeProlog
  236. {
  237. local($str) = @_;
  238. $str =~ s/^_//;
  239. print "\nvoid\nPrint$str(\n $str \*Str\n );\n";
  240. print "\nvoid\nPrint$str(\n $str \*Str\n )\n{\n";
  241. print " printf(\"\\n$str:\\n\");\n";
  242. }
  243. sub PrintTypeEpilog
  244. {
  245. local($str) = @_;
  246. $str =~ s/^_//;
  247. print " return;\n} \/\/ Print$str\n\n";
  248. }
  249. sub Usage
  250. {
  251. local($error) = @_;
  252. die "$error\n",
  253. "$GENPRINT_VERSION\n",
  254. "Usage : $GENPRINT_CMD filename typed_struct\n",
  255. "Options:\n",
  256. " filename file containing the structure definition\n",
  257. " typed_struct structure\n";
  258. }