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.

690 lines
18 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1989-1999 Microsoft Corporation
  3. Module Name:
  4. semutil.cxx
  5. Abstract:
  6. semantic analysis utility routines
  7. Notes:
  8. Author:
  9. GregJen 28-Oct-1993 Created.
  10. Notes:
  11. ----------------------------------------------------------------------------*/
  12. #pragma warning ( disable : 4514 4710 )
  13. /****************************************************************************
  14. * include files
  15. ***************************************************************************/
  16. #include "nulldefs.h"
  17. extern "C" {
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. }
  22. #include "allnodes.hxx"
  23. #include "semantic.hxx"
  24. #include "symtable.hxx"
  25. #include "cmdana.hxx"
  26. /****************************************************************************
  27. * local data
  28. ***************************************************************************/
  29. /****************************************************************************
  30. * externs
  31. ***************************************************************************/
  32. extern SymTable * pBaseSymTbl;
  33. extern ATTR_SUMMARY DisallowedAttrs[INTERNAL_NODE_END];
  34. extern BOOL IsTempName( char * );
  35. extern CMD_ARG * pCommand;
  36. /****************************************************************************
  37. * definitions
  38. ***************************************************************************/
  39. void
  40. WALK_CTXT::FindImportantPosition(tracked_node & Posn)
  41. {
  42. WALK_CTXT * pCurCtxt = this;
  43. WALK_CTXT * pParCtxt;
  44. node_skl * pNode;
  45. // walk up until we find one whose PARENT was not important
  46. while ( (pParCtxt=(WALK_CTXT *)pCurCtxt->GetParentContext()) != 0 &&
  47. ( pParCtxt->IsImportantPosition() ) )
  48. {
  49. pCurCtxt = pParCtxt;
  50. }
  51. // continue walking up until we find one with a position
  52. do
  53. {
  54. pNode = pCurCtxt->GetParent();
  55. pNode->GetPositionInfo( Posn );
  56. pCurCtxt = (WALK_CTXT *) pCurCtxt->GetParentContext();
  57. }
  58. while( !Posn.HasTracking() && pCurCtxt );
  59. }
  60. void
  61. SEM_ANALYSIS_CTXT::CheckAttributes()
  62. {
  63. ATTR_VECTOR & BadAttrs = DisallowedAttrs[ GetParent()->NodeKind() ];
  64. ATTR_VECTOR ExcessAttrs;
  65. ATTR_T Attr;
  66. node_base_attr * pAttr;
  67. char * pAttrName;
  68. MASKED_COPY_ATTR( ExcessAttrs, *(pDownAttrList->GetSummary()), BadAttrs );
  69. while (!IS_CLEAR_ATTR( ExcessAttrs ) )
  70. {
  71. Attr = CLEAR_FIRST_SET_ATTR( ExcessAttrs );
  72. pAttr = ExtractAttribute( Attr );
  73. pAttrName = pAttr->GetNodeNameString();
  74. if (pAttr->IsAcfAttr() )
  75. AcfError( (acf_attr *)pAttr,
  76. GetParent(),
  77. *this,
  78. INAPPLICABLE_ATTRIBUTE,
  79. pAttrName);
  80. else
  81. SemError( GetParent(), *this, INAPPLICABLE_ATTRIBUTE ,pAttrName);
  82. }
  83. }
  84. void
  85. SEM_ANALYSIS_CTXT::RejectAttributes()
  86. {
  87. ATTR_VECTOR ExcessAttrs;
  88. ATTR_T Attr;
  89. node_base_attr * pAttr;
  90. char * pAttrName;
  91. COPY_ATTR( ExcessAttrs, *(pDownAttrList->GetSummary()));
  92. while (!IS_CLEAR_ATTR( ExcessAttrs ) )
  93. {
  94. Attr = CLEAR_FIRST_SET_ATTR( ExcessAttrs );
  95. pAttr = ExtractAttribute( Attr );
  96. pAttrName = pAttr->GetNodeNameString();
  97. if (pAttr->IsAcfAttr() )
  98. AcfError( (acf_attr *)pAttr,
  99. GetParent(),
  100. *this,
  101. INAPPLICABLE_ATTRIBUTE,
  102. pAttrName);
  103. else
  104. SemError( GetParent(), *this, INAPPLICABLE_ATTRIBUTE ,pAttrName);
  105. }
  106. }
  107. //
  108. // resolve forward declarations
  109. //
  110. named_node *
  111. node_forward::ResolveFDecl()
  112. {
  113. if ( !GetChild() )
  114. {
  115. named_node * pRef = pSymTbl->SymSearch( SKey );
  116. if (pRef && ( pRef != this ) && ( pRef->NodeKind() != NODE_FORWARD ) )
  117. {
  118. SetChild( pRef );
  119. }
  120. }
  121. return (named_node *) GetChild();
  122. }
  123. void
  124. node_proc::AddExplicitHandle (
  125. SEM_ANALYSIS_CTXT* pParentCtxt,
  126. unsigned int uParamNumber
  127. )
  128. {
  129. node_skl * pHand;
  130. node_param * pParm;
  131. // only add the handle once
  132. if ( !strcmp( GetChild()->GetSymName(), "IDL_handle" ) )
  133. return;
  134. GetBaseTypeNode( &pHand, SIGN_UNDEF, SIZE_UNDEF, TYPE_HANDLE_T, 0 );
  135. // set up [in] param "IDL_handle", pointing to handle_t, add as first parameter
  136. pParm = new node_param;
  137. pParm->SetSymName( "IDL_handle" );
  138. pParm->SetChild( pHand );
  139. pParm->SetAttribute( new battr( ATTR_IN ) );
  140. if ( uParamNumber == 1 )
  141. {
  142. AddFirstMember( pParm );
  143. }
  144. else
  145. {
  146. AddSecondMember( pParm );
  147. }
  148. // update the information for the parameter
  149. pParm->SemanticAnalysis( pParentCtxt );
  150. fHasExplicitHandle = TRUE;
  151. fHasAtLeastOneIn = TRUE;
  152. }
  153. void
  154. node_proc::AddFullAsyncHandle (
  155. SEM_ANALYSIS_CTXT* pParentCtxt,
  156. node_skl* pType,
  157. char* szTypeName
  158. )
  159. {
  160. const char* szNameSuffix = "_AsyncHandle";
  161. char* szFullName = new char[strlen(GetSymName()) + strlen(szNameSuffix) + 1];
  162. strcpy(szFullName, GetSymName());
  163. strcat(szFullName, szNameSuffix);
  164. node_skl* pAsyncHandle = new node_async_handle( szTypeName );
  165. if ( pType )
  166. {
  167. pAsyncHandle->SetChild( pType );
  168. }
  169. node_param* pParm = new node_param;
  170. pParm->SetSymName( szFullName );
  171. pParm->SetChild( pAsyncHandle );
  172. pParm->SetAttribute( new battr( ATTR_IN ) );
  173. AddFirstMember( pParm );
  174. pParm->SemanticAnalysis( pParentCtxt );
  175. SetHasAsyncHandle();
  176. pParm->SetIsAsyncHandleParam();
  177. fHasAtLeastOneIn = TRUE;
  178. }
  179. BOOL
  180. node_base_type::RangeCheck( __int64 Val )
  181. {
  182. NODE_T Kind = NodeKind();
  183. switch ( Kind )
  184. {
  185. case NODE_BOOLEAN:
  186. return ( Val >= 0 ) && ( Val <= 1 );
  187. case NODE_SHORT:
  188. if ( FInSummary( ATTR_UNSIGNED ) )
  189. return ( Val >= 0 ) && ( Val <= _UI16_MAX );
  190. else
  191. return ( Val >= _I16_MIN ) && ( Val <= _I16_MAX );
  192. case NODE_BYTE:
  193. return ( Val >= 0 ) && ( Val <= 255 );
  194. case NODE_CHAR:
  195. if ( FInSummary( ATTR_UNSIGNED ) )
  196. return ( Val >= 0 ) && ( Val <= 255 );
  197. else if ( FInSummary( ATTR_SIGNED ) )
  198. return ( Val >= -128 ) && ( Val <= 127 );
  199. else if ( pCommand->GetCharOption() == CHAR_SIGNED )
  200. return ( Val >= 0 ) && ( Val <= 255 );
  201. else
  202. return ( Val >= -128 ) && ( Val <= 127 );
  203. case NODE_SMALL:
  204. if ( FInSummary( ATTR_UNSIGNED ) )
  205. return ( Val >= 0 ) && ( Val <= 255 );
  206. else if ( FInSummary( ATTR_SIGNED ) )
  207. return ( Val >= -128 ) && ( Val <= 127 );
  208. else if ( pCommand->GetCharOption() == CHAR_UNSIGNED )
  209. return ( Val >= -128 ) && ( Val <= 127 );
  210. else
  211. return ( Val >= 0 ) && ( Val <= 255 );
  212. case NODE_LONG:
  213. case NODE_INT32:
  214. case NODE_INT:
  215. if ( FInSummary( ATTR_UNSIGNED ) )
  216. return ( Val >= 0 ) && ( Val <= _UI32_MAX );
  217. else
  218. return ( Val >= _I32_MIN ) && ( Val <= _I32_MAX );
  219. case NODE_INT3264:
  220. if ( ! pCommand->Is64BitEnv() )
  221. {
  222. if ( FInSummary( ATTR_UNSIGNED ) )
  223. return ( Val >= 0 ) && ( Val <= _UI32_MAX );
  224. else
  225. return ( Val >= _I32_MIN ) && ( Val <= _I32_MAX );
  226. }
  227. // else fall through to 64b integral
  228. case NODE_HYPER:
  229. case NODE_INT64:
  230. case NODE_INT128:
  231. return TRUE;
  232. }
  233. return TRUE;
  234. }
  235. BOOL
  236. node_base_type::IsAssignmentCompatible( node_base_type * pOther )
  237. {
  238. unsigned long MySize = GetSize();
  239. unsigned long HisSize = pOther->GetSize();
  240. // tbd - fill in more cases
  241. if ( MySize < HisSize )
  242. return FALSE;
  243. // unsigned <= signed
  244. if ( FInSummary( ATTR_UNSIGNED ) &&
  245. !pOther->FInSummary( ATTR_UNSIGNED ) )
  246. return FALSE;
  247. // signed <= unsigned ( only OK if dest is larger )
  248. if ( pOther->FInSummary( ATTR_UNSIGNED ) &&
  249. FInSummary( ATTR_SIGNED ) &&
  250. (MySize <= HisSize) )
  251. return FALSE;
  252. if ( ( NodeKind() == NODE_BOOLEAN ) &&
  253. ( pOther->NodeKind() != NODE_BOOLEAN ) )
  254. return FALSE;
  255. return TRUE;
  256. }
  257. char *
  258. GetErrorNamePrefix( node_skl * pNode )
  259. {
  260. if ( !pNode )
  261. return NULL;
  262. switch ( pNode->NodeKind() )
  263. {
  264. case NODE_FIELD:
  265. return " Field ";
  266. case NODE_STRUCT:
  267. return " Struct ";
  268. case NODE_UNION:
  269. return " Union ";
  270. case NODE_ENUM:
  271. return " Enum ";
  272. case NODE_PARAM:
  273. return " Parameter ";
  274. case NODE_PROC:
  275. return " Procedure ";
  276. case NODE_INTERFACE:
  277. case NODE_INTERFACE_REFERENCE:
  278. return " Interface ";
  279. case NODE_PIPE_INTERFACE:
  280. return " Object Pipe ";
  281. case NODE_DEF:
  282. return " Type ";
  283. case NODE_LIBRARY:
  284. return " Library ";
  285. case NODE_MODULE:
  286. return " Module ";
  287. case NODE_COCLASS:
  288. return " Coclass ";
  289. case NODE_DISPINTERFACE:
  290. return " Dispinterface ";
  291. default:
  292. return NULL;
  293. }
  294. }
  295. #define SUFFIX_SIZE 1000
  296. #define CONTEXT_STR_SIZE 1000
  297. void
  298. GetSemContextString(
  299. char * pResult,
  300. node_skl * pNode,
  301. WALK_CTXT * pCtxt )
  302. {
  303. node_skl * pBase = NULL;
  304. node_skl * pParent = NULL;
  305. node_skl * pUsage = NULL;
  306. char * pPrefix;
  307. pResult[0] = '\0';
  308. if ( !pNode )
  309. {
  310. pNode = ( pCtxt ) ? pCtxt->GetParent() : NULL;
  311. }
  312. // compute base part and parent part
  313. while ( pCtxt && !pParent && pNode )
  314. {
  315. switch ( pNode->NodeKind() )
  316. {
  317. case NODE_FIELD:
  318. case NODE_PARAM:
  319. pBase = pNode;
  320. break;
  321. case NODE_STRUCT:
  322. case NODE_UNION:
  323. case NODE_ENUM:
  324. case NODE_PROC:
  325. case NODE_INTERFACE:
  326. case NODE_PIPE_INTERFACE:
  327. case NODE_INTERFACE_REFERENCE:
  328. case NODE_DEF:
  329. case NODE_LIBRARY:
  330. case NODE_MODULE:
  331. case NODE_COCLASS:
  332. case NODE_DISPINTERFACE:
  333. pParent = pNode;
  334. break;
  335. }
  336. pCtxt = pCtxt->GetParentContext();
  337. pNode = ( pCtxt ) ? pCtxt->GetParent() : NULL;
  338. }
  339. // compute usage part (param or proc or interface)
  340. // note that pCtxt is one level up above the current pNode
  341. pCtxt = pCtxt->GetParentContext();
  342. while ( pCtxt && ! pUsage )
  343. {
  344. switch ( pCtxt->GetParent()->NodeKind() )
  345. {
  346. // stop at the top-most level ( child of interface, or proc )
  347. // therefore highest type/proc/param
  348. case NODE_INTERFACE:
  349. case NODE_PIPE_INTERFACE:
  350. case NODE_PROC:
  351. case NODE_LIBRARY:
  352. case NODE_MODULE:
  353. case NODE_COCLASS:
  354. case NODE_DISPINTERFACE:
  355. pUsage = pNode;
  356. break;
  357. }
  358. pNode = ( pCtxt ) ? pCtxt->GetParent() : NULL;
  359. pCtxt = pCtxt->GetParentContext();
  360. }
  361. if ( pBase || pParent || pUsage )
  362. {
  363. strcat( pResult, "[");
  364. if ( pBase )
  365. {
  366. pPrefix = GetErrorNamePrefix( pBase );
  367. if ( pPrefix )
  368. strcat( pResult, pPrefix );
  369. if ( !IsTempName( pBase->GetSymName() ) )
  370. {
  371. strcat( pResult, "'");
  372. strcat( pResult, pBase->GetSymName() );
  373. strcat( pResult, "' ");
  374. }
  375. }
  376. if ( pParent )
  377. {
  378. if ( !IsTempName( pParent->GetSymName() ) )
  379. {
  380. if ( pBase )
  381. strcat(pResult, "of");
  382. pPrefix = GetErrorNamePrefix( pParent );
  383. if ( pPrefix )
  384. strcat( pResult, pPrefix );
  385. strcat( pResult, "'");
  386. strcat( pResult, pParent->GetSymName() );
  387. strcat( pResult, "' ");
  388. }
  389. else
  390. {
  391. pPrefix = GetErrorNamePrefix( pBase );
  392. if ( pPrefix && !pBase )
  393. strcat( pResult, pPrefix );
  394. }
  395. }
  396. if ( pUsage )
  397. {
  398. strcat( pResult, "(");
  399. pPrefix = GetErrorNamePrefix( pUsage );
  400. if ( pPrefix )
  401. strcat( pResult, pPrefix );
  402. strcat( pResult, "'");
  403. strcat( pResult, pUsage->GetSymName() );
  404. strcat( pResult, "' )");
  405. }
  406. strcat( pResult, " ]");
  407. }
  408. }
  409. void
  410. SemError(
  411. node_skl * pNode,
  412. WALK_CTXT & Ctxt,
  413. STATUS_T ErrNum,
  414. char * pExtra )
  415. {
  416. ErrorInfo ErrStats( ErrNum );
  417. // if the error is not relevant to this compile, return right away
  418. if ( !ErrStats.IsRelevant() )
  419. return;
  420. short CurLen = 1; // for the null byte
  421. char Suffix[SUFFIX_SIZE];
  422. char ContextStr[ CONTEXT_STR_SIZE ];
  423. char * pSuffix = Suffix;
  424. char * pFile;
  425. short Line;
  426. tracked_node Posn((void*)NULL);
  427. WALK_CTXT * pCurCtxt;
  428. // extract file and line info, and context info
  429. pCurCtxt = &Ctxt;
  430. GetSemContextString( ContextStr, pNode, &Ctxt );
  431. CurLen = short( CurLen + strlen( ContextStr ) );
  432. // unless the string is REALLY long, just use stack space
  433. if ( CurLen + 1 > SUFFIX_SIZE )
  434. pSuffix = new char [CurLen + 1];
  435. if ( pExtra || strlen( ContextStr ) )
  436. {
  437. strcpy( pSuffix, ": " );
  438. if ( pExtra )
  439. strcat( pSuffix, pExtra );
  440. // make sure pSuffix has a trailing space at this point
  441. if ( pSuffix[ strlen(pSuffix) - 1 ] != ' ' )
  442. {
  443. strcat( pSuffix, " " );
  444. }
  445. if ( strlen(ContextStr) )
  446. {
  447. strcat( pSuffix, ContextStr );
  448. }
  449. }
  450. else
  451. strcpy( pSuffix, "" );
  452. // fetch the file position from the context stack
  453. Ctxt.FindImportantPosition(Posn);
  454. Posn.GetLineInfo( pFile, Line);
  455. ErrStats.ReportError( pFile,
  456. Line,
  457. pSuffix );
  458. // clean up if we had to allocate space
  459. if ( pSuffix != Suffix )
  460. delete pSuffix;
  461. }
  462. void
  463. AcfError(
  464. acf_attr * pAttr,
  465. node_skl * ,
  466. WALK_CTXT & ,
  467. STATUS_T ErrNum,
  468. char * pExtra )
  469. {
  470. short CurLen = 1; // for the null byte
  471. char Suffix[SUFFIX_SIZE];
  472. char * pSuffix = Suffix;
  473. char * pName;
  474. char * pFile;
  475. short Line;
  476. tracked_node Posn((void*)NULL);
  477. // extract file and line info, and context info
  478. pName = pAttr->GetNodeNameString();
  479. // <name>[: <extra>]
  480. CurLen = short( CurLen + strlen(pName) );
  481. CurLen = short( CurLen + ( (pExtra) ? strlen(pExtra) + 2 : 0 ) );
  482. // unless the string is REALLY long, just use stack space
  483. if ( CurLen + 1 > SUFFIX_SIZE )
  484. pSuffix = new char [CurLen + 1];
  485. strcpy( pSuffix, pName );
  486. if (pExtra)
  487. {
  488. strcat( pSuffix, ": " );
  489. strcat( pSuffix, pExtra );
  490. }
  491. // fetch the file position from the context stack
  492. pAttr->Position.GetLineInfo( pFile, Line);
  493. RpcError( pFile,
  494. Line,
  495. ErrNum,
  496. pSuffix );
  497. // clean up if we had to allocate space
  498. if ( pSuffix != Suffix )
  499. delete pSuffix;
  500. }
  501. BOOL CIDLIST::AddId(__int64 lId, char * szName)
  502. {
  503. IDLISTMEM ** pThis = &pHead;
  504. while (*pThis && (*pThis)->lId < lId)
  505. {
  506. pThis = &((*pThis)->pNext);
  507. }
  508. if (*pThis && (*pThis)->lId == lId)
  509. {
  510. if (_stricmp(szName, (*pThis)->szName))
  511. return FALSE;
  512. else
  513. return TRUE;
  514. }
  515. IDLISTMEM * pNew = new IDLISTMEM;
  516. pNew->lId = lId;
  517. pNew->pNext = *pThis;
  518. pNew->szName = szName;
  519. *pThis = pNew;
  520. return TRUE;
  521. }
  522. /*
  523. Nishad
  524. bool
  525. node_base_type::IsCompatibleType(
  526. TypeSet set
  527. )
  528. {
  529. bool fReturnCode = false;
  530. NODE_T nodeKind = NodeKind();
  531. switch ( set )
  532. {
  533. case ts_UnsignedFixedPoint:
  534. fReturnCode = (
  535. nodeKind == NODE_INT128 ||
  536. nodeKind == NODE_HYPER ||
  537. nodeKind == NODE_INT64 ||
  538. nodeKind == NODE_INT32 ||
  539. nodeKind == NODE_LONG ||
  540. nodeKind == NODE_LONGLONG ||
  541. nodeKind == NODE_SHORT ||
  542. nodeKind == NODE_INT ||
  543. nodeKind == NODE_SMALL ||
  544. nodeKind == NODE_CHAR ||
  545. nodeKind == NODE_BOOLEAN ||
  546. nodeKind == NODE_BYTE
  547. )
  548. &&
  549. IsUnsigned();
  550. break;
  551. case ts_FixedPoint:
  552. fReturnCode = (
  553. nodeKind == NODE_INT128 ||
  554. nodeKind == NODE_HYPER ||
  555. nodeKind == NODE_INT64 ||
  556. nodeKind == NODE_INT32 ||
  557. nodeKind == NODE_LONG ||
  558. nodeKind == NODE_LONGLONG ||
  559. nodeKind == NODE_SHORT ||
  560. nodeKind == NODE_INT ||
  561. nodeKind == NODE_SMALL ||
  562. nodeKind == NODE_CHAR ||
  563. nodeKind == NODE_BOOLEAN ||
  564. nodeKind == NODE_BYTE
  565. );
  566. break;
  567. case ts_FloatingPoint:
  568. fReturnCode = ( nodeKind == NODE_FLOAT ||
  569. nodeKind == NODE_DOUBLE ||
  570. nodeKind == NODE_FLOAT80 ||
  571. nodeKind == NODE_FLOAT128 );
  572. break;
  573. case ts_Character:
  574. fReturnCode = ( nodeKind == NODE_CHAR || nodeKind == NODE_BYTE || nodeKind == NODE_WCHAR_T );
  575. break;
  576. case ts_String:
  577. // TBD
  578. break;
  579. case ts_Interface:
  580. // TBD
  581. break;
  582. }
  583. return fReturnCode;
  584. }
  585. */