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.

503 lines
12 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. makexpr.cxx
  5. Abstract:
  6. This file contains specialized routines for creating complex expressions
  7. from the basic expressions.
  8. Notes:
  9. History:
  10. ----------------------------------------------------------------------------*/
  11. #pragma warning ( disable : 4514 )
  12. /****************************************************************************
  13. * include files
  14. ***************************************************************************/
  15. #include "nulldefs.h"
  16. extern "C"
  17. {
  18. #include <stdio.h>
  19. }
  20. #include "makexpr.hxx"
  21. #include "gramutil.hxx"
  22. /****************************************************************************
  23. * local definitions
  24. ***************************************************************************/
  25. /****************************************************************************
  26. * local data
  27. ***************************************************************************/
  28. /****************************************************************************
  29. * externs
  30. ***************************************************************************/
  31. /****************************************************************************/
  32. expr_node *
  33. MakeReferentExpressionIfNecessary(
  34. expr_node * pExpr )
  35. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  36. Routine Description:
  37. Create a reference expression out of this expression.
  38. Arguments:
  39. pExpr - The input expression for making another reference expr.
  40. Return Value:
  41. The final generated expression.
  42. Notes:
  43. If the input expression is a simple variable, make a &(variable) expression
  44. out of it. If it is already a pointer, return the same expression.
  45. The method is implemented for this situation: I have an expression with me,
  46. I dont really want to know if it is a pointer or not. I just know that this
  47. expression represents the final data location for me to unmarshall into or
  48. marshall from. Given that , generate an expression that will effectively
  49. point to this piece of data. So if it is already a pointer, just return the
  50. same expression, if it is a variable, return the address of this variable,
  51. if it is already a pointer, just dont do anything.
  52. ----------------------------------------------------------------------------*/
  53. {
  54. node_skl * pNode = pExpr->GetType();
  55. NODE_T NT = pExpr->GetType()->NodeKind();
  56. if( (NT == NODE_PARAM) || (NT == NODE_ID) || (NT == NODE_FIELD) )
  57. {
  58. pNode = pNode->GetBasicType();
  59. NT = pNode->NodeKind();
  60. }
  61. if( IS_BASE_TYPE_NODE( NT ) )
  62. {
  63. return MakeAddressExpressionNoMatterWhat( pExpr );
  64. }
  65. switch( NT )
  66. {
  67. default:
  68. MIDL_ASSERT( FALSE );
  69. case NODE_POINTER:
  70. return pExpr;
  71. }
  72. }
  73. expr_node *
  74. MakeDereferentExpressionIfNecessary(
  75. expr_node * pExpr )
  76. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  77. Routine Description:
  78. Create a de-reference expression out of this expression.
  79. Arguments:
  80. pExpr - The input expression for making another de-reference expr.
  81. Return Value:
  82. The final generated expression.
  83. Notes:
  84. If the input expression is a simple variable, return just that.
  85. If it is already a pointer, return a deref expression.
  86. The method is implemented for this situation: I have an expression with me,
  87. I dont really want to know if it is a variable or not. I just know that this
  88. expression represents the final data address for me to unmarshall into or
  89. marshall from. Given that , generate an expression that will effectively
  90. be a dereference of this piece of data. So if it is already a variable,
  91. just return the same expression, if it is a pointer, return the deref of
  92. this expression.
  93. ----------------------------------------------------------------------------*/
  94. {
  95. expr_node * pENew;
  96. node_skl * pNode = pExpr->GetType();
  97. NODE_T NT = pNode->NodeKind();
  98. if( (NT == NODE_PARAM) || (NT == NODE_FIELD) || (NT == NODE_ID) )
  99. {
  100. pNode = pNode->GetBasicType();
  101. NT = pNode->NodeKind();
  102. }
  103. if( IS_BASE_TYPE_NODE( NT ) )
  104. {
  105. return pExpr;
  106. }
  107. switch( NT )
  108. {
  109. default:
  110. // MIDL_ASSERT( FALSE );
  111. case NODE_POINTER:
  112. pENew = new expr_u_deref( pExpr );
  113. pENew->SetType( pNode->GetBasicType() );
  114. return pENew;
  115. }
  116. }
  117. expr_node *
  118. MakeAddressExpressionNoMatterWhat(
  119. expr_node * pExpr )
  120. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  121. Routine Description:
  122. Make an address expression out of this one, ie generate &(expr).
  123. Arguments:
  124. pExpr - A pointer to the expression to manipulate.
  125. Return Value:
  126. The final expression.
  127. Notes:
  128. ----------------------------------------------------------------------------*/
  129. {
  130. expr_node * pENew = (expr_node *) new expr_u_address( pExpr );
  131. node_skl * pNode = new node_pointer();
  132. pNode->SetBasicType( pExpr->GetType() );
  133. pNode->SetEdgeType( EDGE_USE );
  134. pENew->SetType( pNode );
  135. return pENew;
  136. }
  137. expr_node *
  138. MakeDerefExpressionOfCastPtrToType(
  139. node_skl * pType,
  140. expr_node * pExpr )
  141. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  142. Routine Description:
  143. Make an deref expression of a pointer cast to the type.
  144. Arguments:
  145. pType - The type to cast to.
  146. pExpr - A pointer to the expression to manipulate.
  147. Return Value:
  148. The final expression.
  149. Notes:
  150. ----------------------------------------------------------------------------*/
  151. {
  152. node_skl * pPtr = new node_pointer();
  153. pPtr->SetBasicType( pType );
  154. pPtr->SetEdgeType( EDGE_USE );
  155. pExpr = new expr_cast( pPtr, pExpr );
  156. pExpr = new expr_u_deref( pExpr );
  157. pExpr->SetType( pType );
  158. return pExpr;
  159. }
  160. expr_node *
  161. MakeExpressionOfCastPtrToType(
  162. node_skl * pType,
  163. expr_node * pExpr )
  164. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  165. Routine Description:
  166. Make an expression of a pointer cast to the type.
  167. (type *) expr
  168. Arguments:
  169. pType - The type to cast to.
  170. pExpr - A pointer to the expression to manipulate.
  171. Return Value:
  172. The final expression.
  173. Notes:
  174. ----------------------------------------------------------------------------*/
  175. {
  176. node_skl * pPtr = new node_pointer();
  177. pPtr->SetBasicType( pType );
  178. pPtr->SetEdgeType( EDGE_USE );
  179. pExpr = new expr_cast( pPtr, pExpr );
  180. return pExpr;
  181. }
  182. expr_node *
  183. MakeExpressionOfCastToTypeName(
  184. PNAME pName,
  185. expr_node * pExpr )
  186. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  187. Routine Description:
  188. Make an expression of a cast to the type whose name is specified.
  189. (name) expr
  190. Arguments:
  191. pName - The type name to cast to.
  192. pExpr - A pointer to the expression to manipulate.
  193. Return Value:
  194. The final expression.
  195. Notes:
  196. ----------------------------------------------------------------------------*/
  197. {
  198. node_skl * pDef = new node_def( (char *)pName );
  199. pDef->SetBasicType( 0 );
  200. pDef->SetEdgeType( EDGE_USE );
  201. pExpr = new expr_cast( pDef, pExpr );
  202. return pExpr;
  203. }
  204. expr_proc_call *
  205. MakeProcCallOutOfParamExprList(
  206. PNAME pName,
  207. node_skl * pType,
  208. ITERATOR& ParamExprList )
  209. /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  210. Routine Description:
  211. Make a procedure call expression given a list of param expressions.
  212. Arguments:
  213. pName - The name of the procedure.
  214. pType - The return type of the procedure.
  215. ParamExprList - The list of expressions (sans the expr_param nodes)
  216. Return Value:
  217. Notes:
  218. ----------------------------------------------------------------------------*/
  219. {
  220. expr_node * pExpr = 0;
  221. expr_proc_call * pProc = new expr_proc_call( pName );
  222. pProc->SetType( pType );
  223. if( ITERATOR_GETCOUNT( ParamExprList ) )
  224. {
  225. while( ITERATOR_GETNEXT( ParamExprList, pExpr ) )
  226. {
  227. pProc->SetParam( new expr_param( pExpr ) );
  228. }
  229. }
  230. return pProc;
  231. }
  232. expr_node *
  233. MakeRefExprOutOfDeref(
  234. expr_node * pExpr )
  235. {
  236. if( pExpr->GetOperator() == OP_UNARY_INDIRECTION )
  237. {
  238. return pExpr->GetLeft();
  239. }
  240. return pExpr;
  241. }
  242. expr_node *
  243. MakeAddressOfPointer(
  244. expr_node * pExpr )
  245. {
  246. if( pExpr->GetOperator() == OP_UNARY_INDIRECTION )
  247. {
  248. return pExpr->GetLeft();
  249. }
  250. else
  251. {
  252. return MakeAddressExpressionNoMatterWhat( pExpr );
  253. }
  254. }
  255. expr_node *
  256. MakeCastExprPtrToUChar(
  257. expr_node * pExpr )
  258. {
  259. node_skl * pType;
  260. node_skl * pP;
  261. GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_CHAR, TYPE_INT );
  262. pP = new node_pointer();
  263. pP->SetBasicType( pType );
  264. pP->SetEdgeType( EDGE_USE );
  265. return new expr_cast( pP, pExpr );
  266. }
  267. expr_node *
  268. MakeCastExprPtrToPtrToUChar(
  269. expr_node * pExpr )
  270. {
  271. node_skl * pType;
  272. node_skl * pP;
  273. node_skl * pP1;
  274. GetBaseTypeNode( &pType, SIGN_UNSIGNED, SIZE_CHAR, TYPE_INT );
  275. pP = new node_pointer();
  276. pP->SetBasicType( pType );
  277. pP->SetEdgeType( EDGE_USE );
  278. pP1 = new node_pointer();
  279. pP1->SetBasicType( pP );
  280. pP1->SetEdgeType( EDGE_USE );
  281. return new expr_cast( pP1, pExpr );
  282. }
  283. expr_node *
  284. MakeCastExprPtrToVoid(
  285. expr_node * pExpr )
  286. {
  287. node_skl * pType;
  288. node_skl * pP;
  289. GetBaseTypeNode( &pType, SIGN_UNDEF, SIZE_UNDEF, TYPE_VOID );
  290. pP = new node_pointer();
  291. pP->SetBasicType( pType );
  292. pP->SetEdgeType( EDGE_USE );
  293. return new expr_cast( pP, pExpr );
  294. }
  295. void
  296. SetPrefixes(
  297. ITERATOR& VarList,
  298. char * pPrefix,
  299. expr_node * pTarget )
  300. {
  301. short Count;
  302. ITERATOR_INIT(VarList);
  303. for( Count = pTarget->MakeListOfVars( VarList),
  304. ITERATOR_INIT( VarList) ;
  305. Count > 0 ;
  306. Count-- )
  307. {
  308. expr_variable * pE = 0;
  309. ITERATOR_GETNEXT( VarList, pE );
  310. pE->SetPrefix( pPrefix );
  311. }
  312. }
  313. void
  314. ResetPrefixes(
  315. ITERATOR& VarList,
  316. expr_node * pTarget )
  317. {
  318. short Count;
  319. ITERATOR_INIT(VarList);
  320. for( Count = pTarget->MakeListOfVars( VarList),
  321. ITERATOR_INIT( VarList) ;
  322. Count > 0 ;
  323. Count-- )
  324. {
  325. expr_variable * pE = 0;
  326. ITERATOR_GETNEXT( VarList, pE );
  327. pE->SetPrefix( 0 );
  328. }
  329. }
  330. expr_node *
  331. Make_1_ArrayExpressionFromVarName(
  332. PNAME pName,
  333. int Dimension )
  334. {
  335. expr_variable * pEV = new expr_variable( pName, 0 );
  336. expr_index * pIV = new expr_index( pEV,
  337. new expr_constant( (long) Dimension)
  338. );
  339. return pIV;
  340. }
  341. // This method combines all expressions in the list wiht logical ANDs. There is
  342. // guaranteed to be at least 1 member in the list.
  343. expr_node *
  344. CombineIntoLogicalAndExpr(
  345. ITERATOR& List )
  346. {
  347. expr_node * pExpr = 0;
  348. expr_node * pExpr1 = 0;
  349. ITERATOR_INIT( List );
  350. ITERATOR_GETNEXT( List, pExpr );
  351. while( ITERATOR_GETNEXT( List, pExpr1 ) )
  352. {
  353. pExpr = new expr_op_binary( OP_LOGICAL_AND, pExpr, pExpr1 );
  354. }
  355. return pExpr;
  356. }
  357. /*******************************************************************
  358. We need to generate an expression to check that any pointers that
  359. are used in the expression are non-null, otherwise we will end
  360. up generating a deref of those pointers and GP fault.
  361. For example, a length_is expression of *pLengthIs should generate
  362. code like so:
  363. _StubMsg.ActualCount = (pLengthIs) ? *pLengthIs : 0;
  364. Return the same expression if there is no pointer deref in the expr.
  365. *******************************************************************/
  366. expr_node *
  367. MakeAttrExprWithNullPtrChecks(
  368. expr_node * pAttrExpr )
  369. {
  370. ITERATOR List;
  371. if( pAttrExpr->MakeListOfDerefedVars( List ) )
  372. {
  373. expr_node * pExpr;
  374. // There is at least 1 deref expression here.
  375. pExpr = CombineIntoLogicalAndExpr( List );
  376. pAttrExpr = new expr_ternary( OP_QM,
  377. pExpr,
  378. pAttrExpr,
  379. new expr_constant( 0L ) );
  380. }
  381. return pAttrExpr;
  382. }