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.

455 lines
14 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_method2(DWORD,DeleteFeedback,DWORD)
  72. | declare_method(EnumFeedback,LPDIENUMFEEDBACKPROC%, LPVOID)
  73. | end_methods
  74. | end_interface
  75. |
  76. | (Actually, the second parameter to begin_interface is assumed
  77. | to be IUnknown if omitted.)
  78. |
  79. |
  80. | While an interface is being built:
  81. |
  82. | _itf contains the name of the interface
  83. | _itfP contains the name of the interface, sans % sign
  84. | _itfBase contains the name of the base interface
  85. | _itfBase{ contains the name of the base interface, sans % sign
  86. | _ucP contains an uppercase version of _itfP, sans leading `I'
  87. | _cset contains the current character set (W or A)
  88. |
  89. | _methods contains a list of the methods, in the form
  90. |
  91. | _invoke_(Method1,arg1,arg2)_invoke_(Method2,arg1,arg2)...
  92. |
  93. | except that you might find an _invoke2_() inserted when the
  94. | base class methods disappear and the extended methods emerge.
  95. | and you might find an _invoke3_() inserted when the
  96. | method returns a type other than HRESULT.
  97. |
  98. | declare_method takes a variable number of parameters. The first
  99. | is the method name. The rest are method argument types.
  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(`end_base_class_methods',
  109. `define(`_methods',defn(`_methods')`_invoke2_(_itf)')dnl')
  110. define(`declare_method2',
  111. `define(`_methods',defn(`_methods')`_invoke3_($*)')dnl')
  112. define(`end_methods',`_emit_methods`'popdef(`_methods')dnl')
  113. define(`end_interface',`popdef(`_itf')dnl')
  114. |-----------------------------------------------------------------------------
  115. |
  116. | _invoke_per_method calls its argument macro once for each method.
  117. |
  118. | Optional second argument handles _invoke2_'s.
  119. |
  120. define(`_invoke_per_method',
  121. `pushdef(`_invoke_', defn(`$1'))'dnl
  122. `pushdef(`_invoke3_', defn(`$3'))'dnl
  123. `pushdef(`_invoke2_', ifelse(`$2', `', `', defn(`$2')))'dnl
  124. `_methods`'popdef(`_invoke_')popdef(`_invoke2_')popdef(_invoke3_)')
  125. |-----------------------------------------------------------------------------
  126. |
  127. | _DePercent
  128. |
  129. | Remove percent signs by turning TSTR% into WSTR/STR and other %'s
  130. | into W or A. Turning TSTR% into WSTR/STR is a hack: We have more
  131. | macros that map symbols like LPTSTRW -> LPWSTR.
  132. |
  133. | $1 - W or A
  134. | $2... - the thing to change
  135. |
  136. define(`_DePercent', `translit(`$2', `%', `$1')')
  137. define(`LPTSTRW', `LPWSTR')
  138. define(`LPTSTRA', `LPSTR')
  139. define(`LPCTSTRW', `LPCWSTR')
  140. define(`LPCTSTRA', `LPCSTR')
  141. |-----------------------------------------------------------------------------
  142. |
  143. | _DoItf emits a single interface definition in the appropriate
  144. | character set.
  145. |
  146. | $1 - character set (A or W)
  147. | _itf - temporarily redefined to the de-percentified name
  148. | _TF - interface name uppercased, without the leading "I"
  149. |
  150. define(`_DoItf',
  151. `pushdef(`_cset', `$1')'dnl
  152. `pushdef(`_itf', _DePercent(`$1', _itf))'dnl
  153. `pushdef(`_itfBase', _DePercent(`$1', _itfBase))'dnl
  154. `pushdef(`_TF', uppercase(substr(_itf, 1)))'dnl
  155. `#undef INTERFACE
  156. `#'define INTERFACE _itf
  157. DECLARE_INTERFACE_(_itf, _itfBase)
  158. {
  159. /*** IUnknown methods ***/
  160. STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
  161. STDMETHOD_(ULONG,AddRef)(THIS) PURE;
  162. STDMETHOD_(ULONG,Release)(THIS) PURE;
  163. _invoke_per_method(`_emit_method_definition', `_emit_class_header', `_emit_method2_definition')};
  164. typedef struct _itf *LP`'_TF, *P`'_TF;
  165. popdef(`_TF')popdef(`_itf')popdef(`_itfBase')popdef(`_cset')')
  166. |-----------------------------------------------------------------------------
  167. |
  168. | *emit_method_definition
  169. |
  170. | Called once for each method. Generates the STDMETHOD() line.
  171. |
  172. define(`_emit_method_definition',
  173. `_DePercent(_cset, ` STDMETHOD($1)(ifelse($#,1, THIS,
  174. `_Quote(THIS_ shift($*))')) PURE;
  175. ')')
  176. |-----------------------------------------------------------------------------
  177. |
  178. | *emit_method2_definition
  179. |
  180. | Called once for each method. Generates the STDMETHOD() line.
  181. |
  182. define(`_emit_method2_definition',
  183. `_DePercent(_cset, ` 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, *P`'_ucP;
  220. ')#if !defined(__cplusplus) || defined(CINTERFACE)
  221. _EmitWrapper(`QueryInterface', REFIID riid, void** ppvObj)'dnl
  222. `_EmitWrapper(`AddRef')'dnl
  223. `_EmitWrapper(`Release')'dnl
  224. `_invoke_per_method( `_EmitWrapper', `', `_EmitWrapper2')#else
  225. _EmitCPPWrapper(`QueryInterface', REFIID riid, void** ppvObj)'dnl
  226. `_EmitCPPWrapper(`AddRef')'dnl
  227. `_EmitCPPWrapper(`Release')'dnl
  228. `_invoke_per_method( `_EmitCPPWrapper', `', `_EmitCPPWrapper2')#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)
  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 - 1)))')
  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)
  257. |
  258. define(`_ArityCPP',
  259. `$1(ifelse($2,1,,`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 - 3))'))')
  261. |-----------------------------------------------------------------------------
  262. |
  263. | _EmitWrapper - generate a wrapper macro
  264. |
  265. | _itfP - interface name without % sign
  266. | $1 - method name
  267. | $2... - other arguments
  268. |
  269. define(`_EmitWrapper',
  270. ``#'define _itfP`'_`'_Arity($1,$#) (p)->lpVtbl->_Arity($1,$#)
  271. ')
  272. |-----------------------------------------------------------------------------
  273. |
  274. | _EmitWrapper2 - generate a wrapper macro
  275. |
  276. | _itfP - interface name without % sign
  277. | $2 - method name
  278. | $3... - other arguments
  279. |
  280. define(`_EmitWrapper2',
  281. ``#'define _itfP`'_`'_Arity($2,eval($#-1)) (p)->lpVtbl->_Arity($2,eval($#-1))
  282. ')
  283. |-----------------------------------------------------------------------------
  284. |
  285. | _EmitCPPWrapper - generate a C++ wrapper macro
  286. |
  287. | _itfP - interface name without % sign
  288. | $1 - method name
  289. | $2... - other arguments
  290. |
  291. define(`_EmitCPPWrapper',
  292. ``#'define _itfP`'_`'_Arity($1,$#) (p)->_ArityCPP($1,$#)
  293. ')
  294. |-----------------------------------------------------------------------------
  295. |
  296. | _EmitCPPWrapper2 - generate a C++ wrapper macro
  297. |
  298. | _itfP - interface name without % sign
  299. | $2 - method name
  300. | $3... - other arguments
  301. |
  302. define(`_EmitCPPWrapper2',
  303. ``#'define _itfP`'_`'_Arity($2,eval($#-1)) (p)->_ArityCPP($2,eval($#-1))
  304. ')
  305. |-----------------------------------------------------------------------------
  306. |
  307. | The long-awaited _emit_methods, which drives all the real work.
  308. |
  309. |
  310. |define(`emit_methods', `invoke_per_method(`_DoItf')')
  311. define(`_emit_methods',
  312. `pushdef(`_itfP', translit(_itf, `%'))'dnl
  313. `pushdef(`_ucP', uppercase(substr(_itfP, 1)))'dnl
  314. `ifelse(index(_itf, `%'), -1, `_DoItf(`W')',
  315. `_DoItf(`W')_DoItf(`A')')'dnl
  316. `_DoAfterItf()popdef(`_ucP')popdef(`_itfP')')
  317. |-----------------------------------------------------------------------------
  318. |
  319. | dik_define - remember the definition as an m4 macro before spitting it out
  320. define(`dik_def', `define(strsubst(`_$1',` '),$2)`#'define `$1' $2')
  321. |-----------------------------------------------------------------------------
  322. |
  323. | Message cracker definition macros. It goes like this:
  324. |
  325. | begin_message_cracker(DIDM_,IDirectInputDeviceCallback *,this,CDIDev)
  326. | message_cracker(Acquire,HANDLE,hevt)
  327. | message_cracker(GetDataFormat,,,LPDIDATAFORMAT,pdidf)
  328. | end_message_cracker()
  329. |
  330. |-----------------------------------------------------------------------------
  331. |
  332. | _ifnb - macro which emits its second argument if the first is nonblank
  333. define(`_ifnb', `ifelse(`$1',,,`$2')')
  334. |-----------------------------------------------------------------------------
  335. |
  336. | begin_message_cracker - Begin a set of message crackers
  337. |
  338. | $1 - prefix for messages
  339. | $2 - type of first parameter
  340. | $3 - name of first parameter
  341. | $4 - type of parent object
  342. |
  343. | For example, Windows messages would be
  344. |
  345. | begin_message_cracker(WM_,HWND,hwnd,?)
  346. |
  347. | IDirectInputDeviceCallback would be
  348. |
  349. | begin_message_cracker(DIDM_,IDirectInputDeviceCallback *,this,CDIDev)
  350. |
  351. | Variables used during message cracker macro generation:
  352. |
  353. | _prefix - the prefix for the message
  354. | _type1 - type of the first argument
  355. | _name1 - name of the first argument
  356. | _ptype1 - type of parent object
  357. |
  358. define(`begin_message_cracker',
  359. `pushdef(`_prefix',`$1')'dnl
  360. `pushdef(`_type1',`$2')'dnl
  361. `pushdef(`_name1',`$3')'dnl
  362. `pushdef(`_ptype',`$4')'dnl
  363. `HRESULT NTAPI;internal
  364. _ptype`'_CallDevice(struct _ptype *this, UINT didm, WPARAM wp, LPARAM lp);;internal
  365. ')
  366. define(`end_message_cracker',
  367. `popdef(`_prefix')popdef(`_type1')popdef(`_name1')popdef(`_ptype')')
  368. |-----------------------------------------------------------------------------
  369. |
  370. | message_cracker
  371. |
  372. | $1 - name of message, mixed-case.
  373. | $2 - type of wParam, or null if wParam is ignored
  374. | $3 - name of wParam, or null if wParam is ignored
  375. | $4 - type of lParam, or null if lParam is ignored
  376. | $5 - name of lParam, or null if lParam is ignored
  377. |
  378. | Local variable:
  379. |
  380. | _uc - uppercase version of $1 with _prefix attached
  381. define(`message_cracker',
  382. `pushdef(`_uc', _prefix`'uppercase(`$1'))'dnl
  383. `/*
  384. * HRESULT Cls_On$1('dnl
  385. `_ifnb(`$2$4',`
  386. * ')_type1 _name1`'_ifnb(`$2',`, $2 $3`'')_ifnb(`$4',`, $4 $5'))
  387. */
  388. `#'define HANDLE_`'_uc`'(_name1, wParam, lParam, fn) \
  389. ((fn)((_name1)'dnl
  390. `_ifnb(`$2',`, ($2)(wParam)')'dnl
  391. `_ifnb(`$4',`, ($4)(lParam)')'dnl
  392. `))
  393. `#'define FORWARD_`'_uc`'(_name1`''dnl
  394. `_ifnb(`$2',`, $3`'')'dnl
  395. `_ifnb(`$4',`, $5'), fn) \
  396. ((fn)(_name1, _uc, 'dnl
  397. `ifelse(`$2',,0,`(WPARAM)($3)'), 'dnl
  398. `ifelse(`$4',,0,`(LPARAM)($5)')))
  399. HRESULT static __inline
  400. dcb$1(struct _ptype *this`'_ifnb(`$2',`, $2 $3`'')_ifnb(`$4',`, $4 $5'))
  401. {
  402. return FORWARD_`'_uc`'(this`'_ifnb(`$2',`, $3`'')_ifnb(`$4',`, $5'),'dnl
  403. ` _ptype`'_CallDevice);
  404. }
  405. ')
  406. |-----------------------------------------------------------------------------
  407. | Restore comments and the previous diversion
  408. changecom()
  409. divert(_prediv)popdef(`_prediv')dnl End of macro header file