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.

187 lines
4.5 KiB

  1. #!perl
  2. #
  3. # hsplit is too lame to handle OLE interfaces, so I have to
  4. # write this program myself. It only handles the OLE stuff;
  5. # I leave hsplit to manage the regular % stuff.
  6. #
  7. # Makes it clearer what's going on when we pass it as a flag
  8. $A = 0;
  9. $W = 1;
  10. #
  11. # Dummy prototype gizmos for EmitWrapper.
  12. #
  13. @proto = (
  14. "p",
  15. "p,a",
  16. "p,a,b",
  17. "p,a,b,c",
  18. "p,a,b,c,d",
  19. "p,a,b,c,d,e",
  20. "p,a,b,c,d,e,f",
  21. "p,a,b,c,d,e,f,g",
  22. "p,a,b,c,d,e,f,g,h",
  23. );
  24. ##############################################################################
  25. #
  26. # Main loop
  27. #
  28. # Things between ";begin_doc" and ";end_doc" are ignored.
  29. #
  30. # Else, echo everything that isn't between ";begin_interface" and
  31. # ";end_interface". For the stuff between, collect it. If the
  32. # interface name contains a "%", then emit separate W and A versions.
  33. #
  34. ##############################################################################
  35. while (<>) {
  36. if (/^;begin_doc$/) {
  37. while (<>) {
  38. last if $_ eq ";end_doc\n";
  39. }
  40. next;
  41. }
  42. ($itf) = /^;begin_interface\s+(\S+)/;
  43. unless ($itf) {
  44. print;
  45. next;
  46. }
  47. # Oh boy, we found the start of an interface.
  48. # Collect the methods.
  49. $_ = <>;
  50. die ";begin_methods expected here" unless $_ eq ";begin_methods\n";
  51. # An interface is an array of methods
  52. # A method is an array, $m[0] is the method name, $m[1] is the arglist
  53. @itf = ();
  54. while (<>) {
  55. last if $_ eq ";end_methods\n";
  56. ($m, $arg) = /^;method\s+(\S+)\s*\((.*)\)$/;
  57. push(@itf, [ $m, $arg ]) if $m;
  58. }
  59. $_ = <>;
  60. die ";end_interface expected here" unless $_ eq ";end_interface\n";
  61. if ($itf =~ /%/) {
  62. &DoItf($W, $itf, @itf);
  63. &DoItf($A, $itf, @itf);
  64. } else {
  65. &DoItf($W, $itf, @itf);
  66. }
  67. &DoAfterItf($itf, @itf);
  68. }
  69. ##############################################################################
  70. #
  71. # Given a line, remove percent signs, converting to W or A accordingly.
  72. #
  73. ##############################################################################
  74. sub DePercent {
  75. my($fW, $line) = @_;
  76. if ($fW) {
  77. $line =~ s/STR%/WSTR/g;
  78. $line =~ s/%/W/g;
  79. } else {
  80. $line =~ s/STR%/STR/g;
  81. $line =~ s/%/A/g;
  82. }
  83. $line;
  84. }
  85. ##############################################################################
  86. #
  87. # Emit the interface definition.
  88. #
  89. ##############################################################################
  90. sub DoItf {
  91. my($fW, $itf, @itf) = @_;
  92. $itf = &DePercent($fW, $itf);
  93. print <<EOI;
  94. #undef INTERFACE
  95. #define INTERFACE $itf
  96. DECLARE_INTERFACE_($itf, IUnknown)
  97. {
  98. /*** IUnknown methods ***/
  99. STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
  100. STDMETHOD_(ULONG,AddRef)(THIS) PURE;
  101. STDMETHOD_(ULONG,Release)(THIS) PURE;
  102. /*** $itf methods ***/
  103. EOI
  104. for (@itf) {
  105. my($m, $arg) = @$_;
  106. print " STDMETHOD($m)(THIS";
  107. print "_ " if $arg;
  108. print &DePercent($fW, $arg);
  109. print ") PURE;\n";
  110. }
  111. print "};\n\n";
  112. my($uc) = uc $itf;
  113. $uc =~s/^I//;
  114. print &DePercent($W, "typedef struct $itf *LP$uc;\n");
  115. print "\n";
  116. }
  117. ##############################################################################
  118. #
  119. # Emit the follow-up stuff that comes after an interface definition.
  120. # If the interface name contains a percent sign, emit the appropriate
  121. # mix.
  122. #
  123. ##############################################################################
  124. sub DoAfterItf {
  125. my($itf, @itf) = @_;
  126. my($uc) = uc $itf;
  127. $uc =~s/^I//;
  128. my($itfP) = $itf;
  129. $itfP =~ s/%//;
  130. my($ucP) = $uc;
  131. $ucP =~ s/%//;
  132. if ($itf =~ /%/) {
  133. print "#ifdef UNICODE\n";
  134. print &DePercent($W, "#define IID_$itfP IID_$itf\n");
  135. print &DePercent($W, "typedef struct $itf $itfP;\n");
  136. print &DePercent($W, "#define ${itfP}Vtbl ${itf}Vtbl\n");
  137. print "#else\n";
  138. print &DePercent($A, "#define IID_$itfP IID_$itf\n");
  139. print &DePercent($A, "typedef struct $itf $itfP;\n");
  140. print &DePercent($A, "#define ${itfP}Vtbl ${itf}Vtbl\n");
  141. print "#endif\n";
  142. print &DePercent($W, "typedef struct $itfP *LP$ucP;\n");
  143. }
  144. # Now the lame-o wrappers.
  145. print "\n#if !defined(__cplusplus) || defined(CINTERFACE)\n";
  146. &EmitWrapper($itfP, "QueryInterface", 2);
  147. &EmitWrapper($itfP, "AddRef", 0);
  148. &EmitWrapper($itfP, "Release", 0);
  149. for (@itf) {
  150. my($m, $arg, $arity) = @$_;
  151. if ($arg) {
  152. $arity = 1 + y/,/,/;
  153. } else {
  154. $arity = 0;
  155. }
  156. &EmitWrapper($itfP, $m, $arity);
  157. }
  158. print "#endif\n";
  159. }
  160. sub EmitWrapper {
  161. my($itf, $m, $arity) = @_;
  162. die "Need to add another arity" if $arity > $#proto;
  163. print "#define ${itf}_$m($proto[$arity]) (p)->lpVtbl->$m($proto[$arity])\n";
  164. }