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.

173 lines
4.5 KiB

  1. #!perl
  2. #
  3. # mkinc [ -Ipath1;path2;path3 ...] [ -1output1 ] [ -2output2 ] header.h...
  4. #
  5. # Looks for header.h, extracts all structures
  6. # from said header file, generates output1 and output2.
  7. #
  8. # Multiple headers can be supplied on the command line; they are all
  9. # combined to form a single output file.
  10. #
  11. # If the -I option is specified, it serves as a search path if the header
  12. # file cannot be found in the current directory. The search path is used
  13. # only for relative paths.
  14. #
  15. # If the -1 and -2 options are specified, they specify the targets
  16. # for the two include files. output1 includes all the headers and
  17. # output2 includes all the structures. output1 defaults to NUL and
  18. # output2 defaults to STDOUT.
  19. # Path helper functions
  20. sub PathIsAbsolute {
  21. my $path = shift;
  22. $path =~ /^\\\\/ || $path =~ /^[a-zA-Z]:\\/;
  23. }
  24. sub PathIsRelative {
  25. !PathIsAbsolute(shift);
  26. }
  27. sub PathCombine {
  28. my ($dir, $file) = @_;
  29. $dir =~ /\\$/ ? "$dir$file" : "$dir\\$file";
  30. }
  31. # Unsubstitute %_NTBINDIR% if it appears at the start of the path.
  32. # This keeps output independent of the user's enlistment.
  33. sub PathPrettify {
  34. my $path = shift;
  35. my $bindir = $ENV{"_NTBINDIR"} . "\\";
  36. if (uc substr($path, 0, length($bindir)) eq uc $bindir) {
  37. "%_NTBINDIR%\\" . substr($path, length($bindir));
  38. } else {
  39. $path;
  40. }
  41. }
  42. sub PathEscapePath {
  43. my $path = shift;
  44. $path =~ s/\\/\\\\/g;
  45. $path;
  46. }
  47. @INC = ();
  48. # Add a semicolon-separated list to the INC list
  49. sub AddInc {
  50. for (split(/\s*;\s*/, shift)) {
  51. push(@INC, $_) if $_;
  52. }
  53. }
  54. # Open a file, searching on the path; returns the opened filename
  55. sub Open {
  56. my $file = shift;
  57. # See if it is fully qualified already
  58. if (open(I, $file)) {
  59. return $file;
  60. }
  61. # Don't look on path if it's already absolute
  62. return undef if PathIsAbsolute($file);
  63. my $dir;
  64. for $dir (@INC) {
  65. $path = PathCombine($dir, $file);
  66. if (open(I, $path)) {
  67. return $path;
  68. }
  69. }
  70. return undef;
  71. }
  72. sub SyntaxError {
  73. my ($file, $structname) = @_;
  74. print O2 "#error $file($.): wacky struct $structname syntax; cannot parse\n";
  75. print STDOUT "$file($.) : error X0000: wacky struct $structname syntax; cannot parse\n";
  76. }
  77. # ProcessFile - The file has been opened as <I>
  78. sub ProcessFile {
  79. my $header = shift;
  80. my $structname, $endstruct;
  81. line:
  82. while (<I>) {
  83. chomp;
  84. s/\/\*.*?\*\///g; # Kill one-line C comment
  85. s/\/\/.*//; # Kill C++ comment
  86. s/\s*$//; # Kill trailing whitespace
  87. next unless /^\s*typedef\s+struct\s+/;
  88. next if /;/; # Forward declaration; ignore
  89. $tag = $';
  90. if ($tag =~ /^(\w+)/) {
  91. $structname = $1;
  92. next line if $structname =~ /Vtbl$/; # Ignore MIDL Vtbls
  93. } else {
  94. $structname = "<unnamed>";
  95. }
  96. # Look for the closing brace of the struct
  97. # The closing brace must be at the same indent level as the
  98. # line containing the opening brace
  99. if (!/\{/) {
  100. $_ = <I>;
  101. if (!/^\s*\{/) {
  102. SyntaxError($header, $structname);
  103. next line;
  104. }
  105. }
  106. /^(\s*)/;
  107. $endstruct = $1 . "}";
  108. while (($_ = <I>) && substr($_, 0, length($endstruct)) ne $endstruct) {
  109. }
  110. if ($_ =~ /\}\s*(\w+)\s*[,;]/) {
  111. print O2 "_($1) /* line $. */\n";
  112. } elsif ($_ eq $endstruct . "\n") {
  113. $_ = <I>;
  114. if ($_ =~ /^(\w+)\s*[,;]/) {
  115. print O2 "_($1) /* line $. */\n";
  116. } else {
  117. SyntaxError($header, $structname);
  118. }
  119. } else {
  120. SyntaxError($header, $structname);
  121. }
  122. }
  123. }
  124. open(O2, ">&STDOUT");
  125. while ($file = shift) {
  126. if ($file =~ /^-I/) { # a -I directive
  127. AddInc($');
  128. } elsif ($file =~ /^-1/) {
  129. open(O1, ">$'") || die "Cannot create $'";
  130. } elsif ($file =~ /^-2/) {
  131. open(O2, ">$'") || die "Cannot create $'";
  132. } else { # a file
  133. if ($path = Open($file)) {
  134. print O1 "#include <$path>\n";
  135. $pretty = PathPrettify($path);
  136. print O2 "// $pretty\n";
  137. print O2 "#define H \"", PathEscapePath($pretty), "\"\n";
  138. ProcessFile($path);
  139. print O2 "#undef H\n";
  140. close(I);
  141. } else {
  142. print O2 "#error Cannot find file $file\n";
  143. }
  144. }
  145. }