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.

297 lines
6.8 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. );
  53. if ($#ARGV != 1)
  54. {
  55. $error = "requires 2 arguments...";
  56. Usage($error);
  57. }
  58. my $filename = $ARGV[0];
  59. my $typedstr = $ARGV[1];
  60. if (-e $filename && -T $filename)
  61. {
  62. open(FH, "<$filename") || die "$GENPRINT_CMD: could not open $filename...\n";
  63. }
  64. else
  65. {
  66. $error = "$filename does not exist or is not a text file...";
  67. Usage($error);
  68. }
  69. while ( <FH> )
  70. {
  71. # look for the specified string
  72. if ( ($_ =~ /$typedstr/) && ($_ =~ /^typedef/) && ($_ =~ /\{/) ) {
  73. chop $_;
  74. PrintTypeProlog( $typedstr );
  75. if ( PrintTypeBody( ) )
  76. {
  77. PrintTypeEpilog( $typedstr );
  78. last;
  79. }
  80. else
  81. {
  82. print "Parsing failed...\n";
  83. }
  84. }
  85. }
  86. close(FH);
  87. exit 0;
  88. sub PrintTypeBody
  89. {
  90. # Note: in_comment is really for the section defining the structure.
  91. # I do not handle the case if the structure is inside a comment block.
  92. my $in_comment = 0;
  93. my $index = 0;
  94. LINE:
  95. while (<FH>)
  96. {
  97. local($line) = $_;
  98. #print $line;
  99. if ( $line =~ /^\s*#.*$/ ) {
  100. chop $line;
  101. #print "Found pre-processor macro \"$line\" in $typedstr...\n";
  102. print "$line\n";
  103. next LINE;
  104. }
  105. local($line) = $_;
  106. if ( $in_comment ) {
  107. # Does this line have the end of the C comment?
  108. #
  109. if ($line =~ /\*\//)
  110. {
  111. # Yes. Keep everything after the end of the
  112. # comment and keep going with normal processing
  113. $line = $';
  114. $in_comment = 0;
  115. }
  116. else
  117. {
  118. next LINE;
  119. }
  120. }
  121. # Remove single line C "/* */" comments
  122. $line =~ s/\/\*.*?\*\///g;
  123. # Remove any "//" comments
  124. # Make sure the start of the comment is NOT
  125. # inside a string
  126. if (($line =~ /\/\//) && ($line !~ /\".*?\/\/.*?\"/))
  127. {
  128. $line =~ s/\/\/.*$/ /;
  129. }
  130. # Multi-line C comment?
  131. # Make sure the start of the comment is NOT
  132. # inside a string
  133. if (($line =~ /\/\*/) && ($line !~ /\".*?\/\*.*?\"/))
  134. {
  135. # Grab anything before the comment
  136. # Need to make it look like there's still a EOL marker
  137. $line = $` . "\n";
  138. # Remember that we're in "comment" mode
  139. $in_comment = 1;
  140. next LINE;
  141. }
  142. local($line_pack) = $line;
  143. # Replace spaces between word characters with '#'
  144. $line_pack =~ s/(\w)\s+(\w)/$1#$2/g;
  145. # remove whitespace
  146. $line_pack =~ tr/ \t//d;
  147. # Remove quoted double-quote characters
  148. $line_pack =~ s/'\\?"'/'_'/g;
  149. # Remove any strings
  150. # Note: Doesn't handle quoted quote characters correctly
  151. $line_pack =~ s/"[^"]*"/_/g;
  152. # Remove any "//" comments
  153. $line_pack =~ s/\/\/.*$//;
  154. # For empty lines,
  155. if ( $line_pack eq "\n" )
  156. {
  157. next LINE;
  158. }
  159. if ( $line_pack =~ /^\}/)
  160. {
  161. return $index;
  162. }
  163. # print "line_pack: $line_pack\n";
  164. @words = split(/#/, $line_pack);
  165. local($type) = $words[0];
  166. $words[1] =~ s/;$//;
  167. chop $words[1];
  168. local($field) = $words[1];
  169. # print "type: $type field: $field\n";
  170. if ( $TypeFormat{$type} eq "" )
  171. {
  172. print "\#error genprint.pl: no print format for type $type...\n";
  173. }
  174. local($n) = 0;
  175. # if array, need to process them.
  176. if ( $field =~ s/\[(.*)\]// )
  177. {
  178. $n = $1;
  179. }
  180. elsif ( $field =~ /\[\w\]/ )
  181. {
  182. $n= $1;
  183. }
  184. # print $n;
  185. if ( $n )
  186. {
  187. print "{ int idx; for ( idx = 0; idx < $n; idx++ ) {\n";
  188. PrintTypeN( $type, $field, $n );
  189. print "} }\n";
  190. }
  191. else
  192. {
  193. PrintType1( $type, $field );
  194. }
  195. $index++;
  196. next LINE;
  197. }
  198. return 0;
  199. }
  200. sub PrintType1
  201. {
  202. local($type, $field) = @_;
  203. # FIXFIX: I can't recall the printf TypeFormat for LARGE_INTEGER...
  204. # so create a condition for that type. ugly...
  205. if ( ($type eq "LARGE_INTEGER") || ($type eq "ULARGE_INTEGER") )
  206. {
  207. print " printf(\" $field\t$TypeFormat{\"LONGLONG\"}\\n\", Str->$field.QuadPart);\n";
  208. }
  209. elsif ( $type eq "UNICODE_STRING" )
  210. {
  211. print " printf(\" $field\t\%wZ\\n\", &Str->$field);\n";
  212. }
  213. else
  214. {
  215. print " printf(\" $field\t$TypeFormat{$type}\\n\", Str->$field);\n";
  216. }
  217. }
  218. sub PrintTypeN
  219. {
  220. local($type, $field, @n) = @_;
  221. if ( ($type eq "LARGE_INTEGER") || ($type eq "ULARGE_INTEGER") )
  222. {
  223. print " printf(\" $field\[%ld\]\t$TypeFormat{\"LONGLONG\"}\\n\", idx, Str->$field\[idx\].QuadPart);\n";
  224. }
  225. elsif ( $type eq "UNICODE_STRING")
  226. {
  227. print " printf(\" $field\t\%wZ\\n\", &Str->$field);\n";
  228. }
  229. else
  230. {
  231. print " printf(\" $field\[%ld\]\t$TypeFormat{$type}\\n\", idx, Str->$field\[idx\]);\n";
  232. }
  233. }
  234. sub PrintTypeProlog
  235. {
  236. local($str) = @_;
  237. $str =~ s/^_//;
  238. print "\nvoid\nPrint$str(\n $str \*Str\n );\n";
  239. print "\nvoid\nPrint$str(\n $str \*Str\n )\n{\n";
  240. print " printf(\"\\n$str:\\n\");\n";
  241. }
  242. sub PrintTypeEpilog
  243. {
  244. local($str) = @_;
  245. $str =~ s/^_//;
  246. print " return;\n} \/\/ Print$str\n\n";
  247. }
  248. sub Usage
  249. {
  250. local($error) = @_;
  251. die "$error\n",
  252. "$GENPRINT_VERSION\n",
  253. "Usage : $GENPRINT_CMD filename typed_struct\n",
  254. "Options:\n",
  255. " filename file containing the structure definition\n",
  256. " typed_struct structure\n";
  257. }