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.

429 lines
13 KiB

  1. pushdef(_prediv,divnum)divert(-1)dnl Redirect output to /dev/null for now
  2. changecom(`|')
  3. |
  4. | M4 macros for munging dinput.w
  5. |
  6. | begindoc / enddoc
  7. |
  8. | everything between begindoc and enddoc is ignored. They are in the .w
  9. | file so that autodoc can extract the documentation.
  10. |
  11. define(`begindoc',`divert(-1)dnl')
  12. define(`enddoc',`divert('_prediv`)dnl')
  13. |
  14. | Internal macros which persist outside a begin_interface / end_interface
  15. | begin with _ so that they won't collide with words that happen to
  16. | appear in dinput.w
  17. |
  18. | Yeah, it isn't foolproof, but it's close enough for now.
  19. |
  20. |-----------------------------------------------------------------------------
  21. |
  22. | _Quote quotes its argument
  23. |
  24. define(`_Quote', `$@')
  25. |-----------------------------------------------------------------------------
  26. |
  27. | strsubst performs a search-and-replace on its argument
  28. |
  29. | First, the helper functions...
  30. |
  31. | strsubst__ -- Performs one found substitution, or stops
  32. |
  33. | $1 = processed source string (don't rescan)
  34. | $2 = unprocessed source string
  35. | $3 = old
  36. | $4 = new
  37. | $5 = location where `old' was found in $1, or -1 if stop
  38. |
  39. define(`strsubst__',
  40. `ifelse($5,-1,`$1$2',
  41. `strsubst_(`$1'_Quote(substr(`$2',0,$5))`$4',
  42. _Quote(substr(`$2',eval($5+len(`$3')))),
  43. `$3',`$4')')')
  44. | strsubst_ -- Try to perform one substitution, or stop
  45. |
  46. | $1 = processed source string (don't rescan)
  47. | $2 = unprocessed source string
  48. | $3 = old
  49. | $4 = new
  50. |
  51. define(`strsubst_', `strsubst__(`$1',`$2',`$3',`$4',index(`$2',`$3'))')
  52. | strsubst -- Perform a search-and-replace
  53. |
  54. | $1 = source string
  55. | $2 = old
  56. | $3 = new
  57. define(`strsubst', `strsubst_(`',`$1',`$2',`$3')')
  58. |-----------------------------------------------------------------------------
  59. |
  60. | uppercase converts a string to uppercase
  61. |
  62. define(`uppercase',
  63. `translit(`$1', `abcdefghijklmnopqrstuvwxyz',
  64. `ABCDEFGHIJKLMNOPQRSTUVWXYZ')')
  65. |-----------------------------------------------------------------------------
  66. | Interface definition macros. It goes like this:
  67. |
  68. | begin_interface(IMumble%, IUnknown)
  69. | begin_methods
  70. | declare_method(DeleteFeedback,DWORD)
  71. | declare_method(EnumFeedback,LPDIENUMFEEDBACKPROC%, LPVOID)
  72. | end_methods
  73. | end_interface
  74. |
  75. | (Actually, the second parameter to begin_interface is assumed
  76. | to be IUnknown if omitted.)
  77. |
  78. |
  79. | While an interface is being built:
  80. |
  81. | _itf contains the name of the interface
  82. | _itfP contains the name of the interface, sans % sign
  83. | _itfBase contains the name of the base interface
  84. | _itfBase{ contains the name of the base interface, sans % sign
  85. | _ucP contains an uppercase version of _itfP, sans leading `I'
  86. | _cset contains the current character set (W or A)
  87. |
  88. | _methods contains a list of the methods, in the form
  89. |
  90. | _invoke_(RETVAL,Method1,arg1,arg2)_invoke_(RETVAL,Method2,arg1,arg2)...
  91. |
  92. | except that you might find an _invoke2_() inserted when the
  93. | base class methods disappear and the extended methods emerge.
  94. |
  95. | declare_method takes a variable number of parameters. The first
  96. | is the method name. The rest are method argument types.
  97. |
  98. | declare_method_ is like declare_method, except you can override
  99. | the return value.
  100. |
  101. define(`begin_interface',`pushdef(`_itf',`$1')'dnl
  102. `pushdef(`_itfBase', ifelse(`$2',`', `IUnknown', `$2'))dnl')
  103. define(`begin_methods',
  104. `pushdef(`_methods',
  105. `_invoke2_(ifelse(_itfBase, `IUnknown', `_itf', `_itfBase'))')dnl')
  106. define(`declare_method_',
  107. `define(`_methods',defn(`_methods')`_invoke_($*)')dnl')
  108. define(`declare_method', `declare_method_(HRESULT,$*)')
  109. define(`end_base_class_methods',
  110. `define(`_methods',defn(`_methods')`_invoke2_(_itf)')dnl')
  111. define(`end_methods',`_emit_methods`'popdef(`_methods')dnl')
  112. define(`end_interface',`popdef(`_itf')dnl')
  113. |-----------------------------------------------------------------------------
  114. |
  115. | _invoke_per_method calls its argument macro once for each method.
  116. |
  117. | Optional second argument handles _invoke2_'s.
  118. |
  119. define(`_invoke_per_method',
  120. `pushdef(`_invoke_', defn(`$1'))'dnl
  121. `pushdef(`_invoke2_', ifelse(`$2', `', `', defn(`$2')))'dnl
  122. `_methods`'popdef(`_invoke_')popdef(`_invoke2_')')
  123. |-----------------------------------------------------------------------------
  124. |
  125. | _DePercent
  126. |
  127. | Remove percent signs by turning TSTR% into WSTR/STR and other %'s
  128. | into W or A. Turning TSTR% into WSTR/STR is a hack: We have more
  129. | macros that map symbols like LPTSTRW -> LPWSTR.
  130. |
  131. | $1 - W or A
  132. | $2... - the thing to change
  133. |
  134. define(`_DePercent', `translit(`$2', `%', `$1')')
  135. define(`LPTSTRW', `LPWSTR')
  136. define(`LPTSTRA', `LPSTR')
  137. define(`LPCTSTRW', `LPCWSTR')
  138. define(`LPCTSTRA', `LPCSTR')
  139. |-----------------------------------------------------------------------------
  140. |
  141. | _DoItf emits a single interface definition in the appropriate
  142. | character set.
  143. |
  144. | $1 - character set (A or W)
  145. | _itf - temporarily redefined to the de-percentified name
  146. | _TF - interface name uppercased, without the leading "I"
  147. |
  148. define(`_DoItf',
  149. `pushdef(`_cset', `$1')'dnl
  150. `pushdef(`_itf', _DePercent(`$1', _itf))'dnl
  151. `pushdef(`_itfBase', _DePercent(`$1', _itfBase))'dnl
  152. `pushdef(`_TF', uppercase(substr(_itf, 1)))'dnl
  153. `#undef INTERFACE
  154. `#'define INTERFACE _itf
  155. DECLARE_INTERFACE_(_itf, _itfBase)
  156. {
  157. /*** IUnknown methods ***/
  158. STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
  159. STDMETHOD_(ULONG,AddRef)(THIS) PURE;
  160. STDMETHOD_(ULONG,Release)(THIS) PURE;
  161. _invoke_per_method(`_emit_method_definition', `_emit_class_header')};
  162. typedef struct _itf *LP`'_TF;
  163. popdef(`_TF')popdef(`_itf')popdef(`_itfBase')popdef(`_cset')')
  164. |-----------------------------------------------------------------------------
  165. |
  166. | _emit_method_definition
  167. |
  168. | Called once for each method. Generates the STDMETHOD() line.
  169. |
  170. | $1 - return type (usually HRESULT)
  171. | $2 - method name
  172. | $3 - arguments
  173. |
  174. | If the return type is HRESULT, then use STDMETHOD. Otherwise,
  175. | use STDMETHOD_.
  176. |
  177. | If there are no arguments, then use THIS. Otherwise, use THIS_.
  178. |
  179. define(`_emit_method_definition',
  180. `_DePercent(_cset,
  181. ifelse($1,HRESULT,
  182. ` STDMETHOD($2)',
  183. ` STDMETHOD_($1,$2)')`(ifelse($#,2, THIS,
  184. `_Quote(THIS_ shift(shift($*)))')) PURE;
  185. ')')
  186. |-----------------------------------------------------------------------------
  187. |
  188. | _emit_class_header
  189. |
  190. | Called once for each change of class. Generates a happy comment block.
  191. |
  192. define(`_emit_class_header',
  193. `
  194. /*** $1 methods ***/
  195. ')
  196. |-----------------------------------------------------------------------------
  197. |
  198. | _DoAfterItfVariation
  199. |
  200. | Emit $1, first as W, then as A.
  201. |
  202. define(`_DoAfterItfVariation',
  203. `#ifdef UNICODE
  204. _DePercent(`W', `$*')
  205. #else
  206. _DePercent(`A', `$*')
  207. #endif')
  208. |-----------------------------------------------------------------------------
  209. |
  210. | _DoAfterItf emits the follow-up stuff that comes after an interface
  211. | definition. If the interface name contains a percent sign, emit
  212. | the appropriate mix.
  213. |
  214. define(`_DoAfterItf',
  215. `ifelse(_itf, _itfP,, `_DoAfterItfVariation(
  216. `#'define IID_`'_itfP IID_`'_itf
  217. `#'define _itfP _itf
  218. `#'define _itfP`'Vtbl _itf`'Vtbl)
  219. typedef struct _itfP *LP`'_ucP;
  220. ')#if !defined(__cplusplus) || defined(CINTERFACE)
  221. _EmitWrapper(HRESULT, `QueryInterface', REFIID riid, LPVOID * ppvObj)'dnl
  222. `_EmitWrapper(ULONG, `AddRef')'dnl
  223. `_EmitWrapper(ULONG, `Release')'dnl
  224. `_invoke_per_method( `_EmitWrapper')#else
  225. _EmitCPPWrapper(HRESULT, `QueryInterface', REFIID riid, LPVOID * ppvObj)'dnl
  226. `_EmitCPPWrapper(ULONG, `AddRef')'dnl
  227. `_EmitCPPWrapper(ULONG, `Release')'dnl
  228. `_invoke_per_method( `_EmitCPPWrapper')#endif
  229. ')
  230. |-----------------------------------------------------------------------------
  231. |
  232. | _Arity - generate fake arguments based on arity
  233. |
  234. | What comes out is "Method(p,a,b,c)" if arity is 4
  235. |
  236. | Note that we skip `p' in the alphabetical list. Duh.
  237. |
  238. | $1 = method
  239. | $2 = number of arguments (including method itself and return value)
  240. |
  241. define(`_Arity',
  242. `$1(substr(`p,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,q,r,s,t,u,v,w,x,y,z',
  243. 0, eval($2 * 2 - 3)))')
  244. |-----------------------------------------------------------------------------
  245. |
  246. | _ArityCPP - generate fake arguments based on arity
  247. |
  248. | What comes out is "Method(a,b,c)" if arity is 4 (we ate the `p')
  249. |
  250. | Note that we skip `p' in the alphabetical list. Duh.
  251. |
  252. | Note also that we need to special-case the situation where
  253. | the arity is exactly zero, so we don't underflow.
  254. |
  255. | $1 = method
  256. | $2 = number of arguments (including method itself and return value)
  257. |
  258. define(`_ArityCPP',
  259. `$1(ifelse($2,2,,`substr(`a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,q,r,s,t,u,v,w,x,y,z',
  260. 0, eval($2 * 2 - 5))'))')
  261. |-----------------------------------------------------------------------------
  262. |
  263. | _EmitWrapper - generate a wrapper macro
  264. |
  265. | _itfP - interface name without % sign
  266. | $1 - return value name
  267. | $2 - method name
  268. | $3... - other arguments
  269. |
  270. define(`_EmitWrapper',
  271. ``#'define _itfP`'_`'_Arity($2,$#) (p)->lpVtbl->_Arity($2,$#)
  272. ')
  273. |-----------------------------------------------------------------------------
  274. |
  275. | _EmitCPPWrapper - generate a C++ wrapper macro
  276. |
  277. | _itfP - interface name without % sign
  278. | $1 - return value name
  279. | $2 - method name
  280. | $3... - other arguments
  281. |
  282. define(`_EmitCPPWrapper',
  283. ``#'define _itfP`'_`'_Arity($2,$#) (p)->_ArityCPP($2,$#)
  284. ')
  285. |-----------------------------------------------------------------------------
  286. |
  287. | The long-awaited _emit_methods, which drives all the real work.
  288. |
  289. |
  290. |define(`emit_methods', `invoke_per_method(`_DoItf')')
  291. define(`_emit_methods',
  292. `pushdef(`_itfP', translit(_itf, `%'))'dnl
  293. `pushdef(`_ucP', uppercase(substr(_itfP, 1)))'dnl
  294. `ifelse(index(_itf, `%'), -1, `_DoItf(`W')',
  295. `_DoItf(`W')_DoItf(`A')')'dnl
  296. `_DoAfterItf()popdef(`_ucP')popdef(`_itfP')')
  297. |-----------------------------------------------------------------------------
  298. |
  299. | dik_define - remember the definition as an m4 macro before spitting it out
  300. define(`dik_def', `define(strsubst(`_$1',` '),$2)`#'define `$1' $2')
  301. |-----------------------------------------------------------------------------
  302. |
  303. | Message cracker definition macros. It goes like this:
  304. |
  305. | begin_message_cracker(DIDM_,IDirectInputDeviceCallback *,this,CDIDev)
  306. | message_cracker(Acquire,HANDLE,hevt)
  307. | message_cracker(GetDataFormat,,,LPDIDATAFORMAT,pdidf)
  308. | end_message_cracker()
  309. |
  310. |-----------------------------------------------------------------------------
  311. |
  312. | _ifnb - macro which emits its second argument if the first is nonblank
  313. define(`_ifnb', `ifelse(`$1',,,`$2')')
  314. |-----------------------------------------------------------------------------
  315. |
  316. | begin_message_cracker - Begin a set of message crackers
  317. |
  318. | $1 - prefix for messages
  319. | $2 - type of first parameter
  320. | $3 - name of first parameter
  321. | $4 - type of parent object
  322. |
  323. | For example, Windows messages would be
  324. |
  325. | begin_message_cracker(WM_,HWND,hwnd,?)
  326. |
  327. | IDirectInputDeviceCallback would be
  328. |
  329. | begin_message_cracker(DIDM_,IDirectInputDeviceCallback *,this,CDIDev)
  330. |
  331. | Variables used during message cracker macro generation:
  332. |
  333. | _prefix - the prefix for the message
  334. | _type1 - type of the first argument
  335. | _name1 - name of the first argument
  336. | _ptype1 - type of parent object
  337. |
  338. define(`begin_message_cracker',
  339. `pushdef(`_prefix',`$1')'dnl
  340. `pushdef(`_type1',`$2')'dnl
  341. `pushdef(`_name1',`$3')'dnl
  342. `pushdef(`_ptype',`$4')'dnl
  343. `HRESULT NTAPI;internal
  344. _ptype`'_CallDevice(struct _ptype *this, UINT didm, WPARAM wp, LPARAM lp);;internal
  345. ')
  346. define(`end_message_cracker',
  347. `popdef(`_prefix')popdef(`_type1')popdef(`_name1')popdef(`_ptype')')
  348. |-----------------------------------------------------------------------------
  349. |
  350. | message_cracker
  351. |
  352. | $1 - name of message, mixed-case.
  353. | $2 - type of wParam, or null if wParam is ignored
  354. | $3 - name of wParam, or null if wParam is ignored
  355. | $4 - type of lParam, or null if lParam is ignored
  356. | $5 - name of lParam, or null if lParam is ignored
  357. |
  358. | Local variable:
  359. |
  360. | _uc - uppercase version of $1 with _prefix attached
  361. define(`message_cracker',
  362. `pushdef(`_uc', _prefix`'uppercase(`$1'))'dnl
  363. `/*
  364. * HRESULT Cls_On$1('dnl
  365. `_ifnb(`$2$4',`
  366. * ')_type1 _name1`'_ifnb(`$2',`, $2 $3`'')_ifnb(`$4',`, $4 $5'))
  367. */
  368. `#'define HANDLE_`'_uc`'(_name1, wParam, lParam, fn) \
  369. ((fn)((_name1)'dnl
  370. `_ifnb(`$2',`, ($2)(wParam)')'dnl
  371. `_ifnb(`$4',`, ($4)(lParam)')'dnl
  372. `))
  373. `#'define FORWARD_`'_uc`'(_name1`''dnl
  374. `_ifnb(`$2',`, $3`'')'dnl
  375. `_ifnb(`$4',`, $5'), fn) \
  376. ((fn)(_name1, _uc, 'dnl
  377. `ifelse(`$2',,0,`(WPARAM)($3)'), 'dnl
  378. `ifelse(`$4',,0,`(LPARAM)($5)')))
  379. HRESULT static __inline
  380. dcb$1(struct _ptype *this`'_ifnb(`$2',`, $2 $3`'')_ifnb(`$4',`, $4 $5'))
  381. {
  382. return FORWARD_`'_uc`'(this`'_ifnb(`$2',`, $3`'')_ifnb(`$4',`, $5'),'dnl
  383. ` _ptype`'_CallDevice);
  384. }
  385. ')
  386. |-----------------------------------------------------------------------------
  387. | Restore comments and the previous diversion
  388. changecom()
  389. divert(_prediv)popdef(`_prediv')dnl End of macro header file