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.

1229 lines
29 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1990-1992 **/
  4. /**********************************************************************/
  5. /*
  6. uixport.c
  7. This program parses the output of the "COFF -DUMP -SYMBOLS" command
  8. and extract all public symbols. This is used to generate .DEF files
  9. for DLLs.
  10. FILE HISTORY:
  11. KeithMo 09-Aug-1992 00.00.00 Created.
  12. KeithMo 14-Sep-1992 00.00.01 Strip stdcall decoration from symbols.
  13. KeithMo 16-Oct-1992 00.00.02 Handle goofy []()* in coff output.
  14. DavidHov 18-Sep-1993 00.00.04 Added exclusion list processing.
  15. The exlusion list is generated
  16. mechanically and constiutes all the
  17. symbols which are not imported
  18. by any known NETUI/RAS/MAC (et al.)
  19. binary.
  20. DavidHov 22-Sep-1993 00.00.05 Added symbol ignore table and logic.
  21. The ignore table at this time ignores
  22. only the gigantic symbols generated
  23. by C8 when /Gf is used; these names
  24. are strings which are to be merged
  25. at link time.
  26. DaveWolfe 06-Jul-1994 00.01.01 (Motorola) Added -ppc option for
  27. PowerPC to strip entry point symbols
  28. generated for PPC TOC.
  29. */
  30. #include <ctype.h>
  31. #include <stdarg.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <search.h>
  36. //
  37. // This is the maximum length (in characters) of any line we'll
  38. // receive from COFF. If we receive a longer line, the program
  39. // won't crash, but we may miss a public symbol.
  40. //
  41. #define MAX_LINE_FROM_COFF 2000
  42. //
  43. // This is the maximum length (in characters) of any symbol we'll
  44. // receive from COFF.
  45. //
  46. #define MAX_SYMBOL 247
  47. //
  48. // This is the maximum length (in characters) of any error message
  49. // we'll display.
  50. //
  51. #define MAX_ERROR_MESSAGE 256
  52. //
  53. // This is the length (in characters) of the header->output copy buffer.
  54. //
  55. #define HEADER_COPY_BUFFER_SIZE 256
  56. //
  57. // Messages.
  58. //
  59. char _szBanner[] = "%s version 00.01.01\n";
  60. char _szCannotOpenForRead[] = "Cannot open %s for read access.";
  61. char _szCannotOpenForWrite[] = "Cannot open %s for write access.";
  62. char _szErrorCopyingHeader[] = "Error copying header to output.";
  63. char _szInvalidSwitch[] = "Invalid switch '%c'.\n\n";
  64. char _szSymbolTooLong[] = "Symbol %s exceeds max symbol length!\n";
  65. char _szExclusionError[] = "Error processing exclusion list file; ignored" ;
  66. char _szExclusionEmpty[] = "Exclusion list file specified is empty; ignored" ;
  67. //
  68. // Globals.
  69. //
  70. char * _pszProgramName;
  71. FILE * _fileIn;
  72. FILE * _fileOut;
  73. FILE * _fileHeader;
  74. int _fStripLeadingUnderscore;
  75. int _fNukeStdcallDecoration;
  76. int _fPowerPC;
  77. int _fIA64;
  78. char * _pszExclusionListFile = NULL ;
  79. void * _pvExclusionBlock = NULL ;
  80. char * * _apszExclusionArray = NULL ;
  81. int _cExclusionItems = -1 ;
  82. int _cExcludedItems = 0 ;
  83. int _cIgnoredItems = 0 ;
  84. // This table contains the prefixes of symbol names to ignore
  85. // while building the DEF file. See ValidSymbol().
  86. static char * apszIgnore [] =
  87. {
  88. "??_C@_", // Ignore generated string symbol names
  89. NULL
  90. };
  91. //
  92. // Prototypes.
  93. //
  94. int __cdecl main( int cArgs,
  95. char * pArgs[] );
  96. void Cleanup( void );
  97. void CopyHeaderToOutput( FILE * fHeader,
  98. FILE * fOutput );
  99. int ExtractSymbol( char * pszLineFromCoff,
  100. char * pszSymbol );
  101. void __cdecl FatalError( int err,
  102. char * pszFmt,
  103. ... );
  104. void __cdecl NonFatalError( char * pszFmt,
  105. ... );
  106. int IsHexNumber( char * pszHexNumber );
  107. char * NoPath( char * pszPathName );
  108. void ProcessCommandLine( int cArgs,
  109. char * pArgs[] );
  110. void StripStdcallDecoration( char * pszSymbol );
  111. void Usage( void );
  112. // Create the exclusion list.
  113. int CreateExclusionList ( char * pszFileName,
  114. void * * pvData,
  115. char * * * apszStrings ) ;
  116. // Check the excluded symbol list for this name
  117. int ExcludedSymbol ( char * pszSymbol ) ;
  118. int ValidSymbol ( const char * psz ) ;
  119. /*******************************************************************
  120. NAME: main
  121. SYNOPSIS: C program entrypoint.
  122. ENTRY: cArgs - Number of command line arguments.
  123. pArgs - An array of pointers to the
  124. command line arguments.
  125. RETURNS: int - 0 if everything ran OK,
  126. !0 if an error occurred.
  127. NOTES: See the Usage() function for valid command line arguments.
  128. HISTORY:
  129. KeithMo 09-Aug-1992 Created.
  130. KeithMo 14-Sep-1992 Strip stdcall decoration from symbols.
  131. ********************************************************************/
  132. int __cdecl main( int cArgs,
  133. char * pArgs[] )
  134. {
  135. //
  136. // A line read from COFF.
  137. //
  138. char szLineFromCoff[MAX_LINE_FROM_COFF+1];
  139. //
  140. // A symbol extracted from the COFF line.
  141. //
  142. char szSymbol[MAX_SYMBOL+1];
  143. //
  144. // Get the program name, for our messages.
  145. //
  146. _pszProgramName = NoPath( pArgs[0] );
  147. //
  148. // Announce ourselves.
  149. //
  150. fprintf( stderr,
  151. _szBanner,
  152. _pszProgramName );
  153. //
  154. // Parse the command line arguments.
  155. //
  156. ProcessCommandLine( cArgs, pArgs );
  157. //
  158. // If requested, copy the header file before processing
  159. // the COFF output.
  160. //
  161. if( _fileHeader != NULL )
  162. {
  163. CopyHeaderToOutput( _fileHeader, _fileOut );
  164. }
  165. //
  166. // If an exclusion list file was specified, process it.
  167. // If it's empty, ignore it.
  168. //
  169. if ( _pszExclusionListFile )
  170. {
  171. _cExclusionItems = CreateExclusionList( _pszExclusionListFile,
  172. & _pvExclusionBlock,
  173. & _apszExclusionArray ) ;
  174. if ( _cExclusionItems < 0 )
  175. {
  176. _pszExclusionListFile = NULL ;
  177. NonFatalError( _szExclusionError ) ;
  178. }
  179. else
  180. if ( _cExclusionItems == 0 )
  181. {
  182. _pszExclusionListFile = NULL ;
  183. NonFatalError( _szExclusionEmpty ) ;
  184. }
  185. }
  186. //
  187. // Read the lines from coff, extract the symbols, and
  188. // write them to the output file.
  189. //
  190. while( fgets( szLineFromCoff, MAX_LINE_FROM_COFF, _fileIn ) != NULL )
  191. {
  192. char * pszDisplay = szSymbol;
  193. if( !ExtractSymbol( szLineFromCoff, szSymbol ) )
  194. {
  195. continue;
  196. }
  197. if ( ! _fNukeStdcallDecoration )
  198. {
  199. StripStdcallDecoration( szSymbol );
  200. }
  201. if ( ! ValidSymbol( pszDisplay ) )
  202. {
  203. _cIgnoredItems++ ;
  204. continue ;
  205. }
  206. if ( _pszExclusionListFile && ExcludedSymbol( szSymbol ) )
  207. {
  208. _cExcludedItems++ ;
  209. continue ;
  210. }
  211. if( _fStripLeadingUnderscore && ( *pszDisplay == '_' ) )
  212. {
  213. pszDisplay++;
  214. }
  215. fprintf( _fileOut, "%s\n", pszDisplay );
  216. }
  217. fprintf( _fileOut, "\032" );
  218. // Give a synopsis of exclusion file processesing.
  219. fprintf( stdout, "\nSymbols ignored: %ld\n", _cIgnoredItems ) ;
  220. if ( _pszExclusionListFile )
  221. {
  222. fprintf( stdout, "\nExcluded symbols registered: %ld, excluded: %ld\n",
  223. _cExclusionItems, _cExcludedItems ) ;
  224. }
  225. //
  226. // Cleanup any open files, then exit.
  227. //
  228. Cleanup();
  229. return 0;
  230. } // main
  231. /*******************************************************************
  232. NAME: Cleanup
  233. SYNOPSIS: Cleanup the app just before termination. Closes any
  234. open files, frees memory buffers, etc.
  235. HISTORY:
  236. KeithMo 09-Aug-1992 Created.
  237. ********************************************************************/
  238. void Cleanup( void )
  239. {
  240. if( _fileHeader != NULL )
  241. {
  242. fclose( _fileHeader );
  243. }
  244. if( _fileIn != stdin )
  245. {
  246. fclose( _fileIn );
  247. }
  248. if( _fileOut != stdout )
  249. {
  250. fclose( _fileOut );
  251. }
  252. if ( _pvExclusionBlock )
  253. {
  254. free( _pvExclusionBlock ) ;
  255. }
  256. if ( _apszExclusionArray )
  257. {
  258. free( _apszExclusionArray ) ;
  259. }
  260. } // Cleanup
  261. /*******************************************************************
  262. NAME: CopyHeaderToOutput
  263. SYNOPSIS: Copies the specified header file to the output file.
  264. ENTRY: fHeader - An open file stream (read access)
  265. to the header file.
  266. fOutput - An open file stream (write access)
  267. to the output file.
  268. NOTES: If any errors occur, FatalError() is called to terminate
  269. the app.
  270. HISTORY:
  271. KeithMo 09-Aug-1992 Created.
  272. ********************************************************************/
  273. void CopyHeaderToOutput( FILE * fHeader,
  274. FILE * fOutput )
  275. {
  276. char achBuffer[HEADER_COPY_BUFFER_SIZE];
  277. size_t cbRead;
  278. while( ( cbRead = fread( achBuffer,
  279. sizeof(char),
  280. HEADER_COPY_BUFFER_SIZE,
  281. fHeader ) ) != 0 )
  282. {
  283. if( fwrite( achBuffer,
  284. sizeof(char),
  285. cbRead,
  286. fOutput ) < cbRead )
  287. {
  288. break;
  289. }
  290. }
  291. if( ferror( fHeader ) || ferror( fOutput ) )
  292. {
  293. FatalError( 2, _szErrorCopyingHeader );
  294. }
  295. } // CopyHeaderToOutput
  296. /*******************************************************************
  297. NAME: ExtractSymbol
  298. SYNOPSIS: Extracts a public symbol from a COFF output line.
  299. ENTRY: pszLineFromCoff - A text line output from the
  300. "COFF -DUMP -SYM" command.
  301. Note: The text in the line
  302. will be modified by the strtok()
  303. function!
  304. pszSymbol - Will receive the extracted symbol,
  305. if one is found.
  306. RETURNS: int - !0 if a symbol was extracted,
  307. 0 otherwise.
  308. NOTES: Here's an example of the input (output from LINK32).
  309. The symbol -$- indicates places where I broke the line
  310. for clarity. This just one line:
  311. 009 00000000 SECT2 notype () External | -$-
  312. ??0APPLICATION@@IAE@PAUHINSTANCE__@@HIIII@Z -$-
  313. (protected: __thiscall APPLICATION::APPLICATION( -$-
  314. struct HINSTANCE__ *,int,unsigned int,unsigned int,-$-
  315. unsigned int,unsigned int))
  316. We choose only symbols which are part of a SECT and are
  317. marked as "notype" and "External"
  318. HISTORY:
  319. KeithMo 09-Aug-1992 Created.
  320. DavidHov 20-Oct-1993 update to new LINK32 output form.
  321. ********************************************************************/
  322. int ExtractSymbol( char * pszLineFromCoff,
  323. char * pszSymbol )
  324. {
  325. char * pszDelimiters = " \t\n";
  326. char * pszSect = "SECT";
  327. char * pszNoType = "notype";
  328. char * pszExternal = "External";
  329. char * pszToken;
  330. char * pszPotentialSymbol;
  331. char * pszScan;
  332. //
  333. // Verify that the first token is a hex number.
  334. //
  335. pszToken = strtok( pszLineFromCoff, pszDelimiters );
  336. if( ( pszToken == NULL ) || !IsHexNumber( pszToken ) )
  337. {
  338. return 0;
  339. }
  340. //
  341. // Verify that the second token is a hex number.
  342. //
  343. pszToken = strtok( NULL, pszDelimiters );
  344. if( ( pszToken == NULL ) || !IsHexNumber( pszToken ) )
  345. {
  346. return 0;
  347. }
  348. //
  349. // The third token must be SECTn (where n is one
  350. // or more hex digits).
  351. //
  352. pszToken = strtok( NULL, pszDelimiters );
  353. if( pszToken == NULL )
  354. {
  355. return 0;
  356. }
  357. if( ( _strnicmp( pszToken, pszSect, 4 ) )
  358. || ! IsHexNumber( pszToken + 4 ) )
  359. {
  360. return 0 ;
  361. }
  362. //
  363. // Next, we have to have "notype"
  364. //
  365. pszToken = strtok( NULL, pszDelimiters );
  366. if( pszToken == NULL ||
  367. _stricmp( pszToken, pszNoType ) )
  368. {
  369. return 0;
  370. }
  371. //
  372. // Functions have a () next, data exports don't.
  373. //
  374. pszToken = strtok( NULL, pszDelimiters );
  375. if( pszToken == NULL )
  376. {
  377. return 0;
  378. }
  379. if ( strcmp( pszToken, "()" ) != 0 )
  380. {
  381. return 0;
  382. }
  383. //
  384. // Next, we need "External"
  385. //
  386. pszToken = strtok( NULL, pszDelimiters );
  387. if( pszToken == NULL )
  388. {
  389. return 0;
  390. }
  391. if( pszToken == NULL ||
  392. _stricmp( pszToken, pszExternal ) )
  393. {
  394. return 0;
  395. }
  396. //
  397. // Now, the symbol introducer: "|"
  398. //
  399. pszToken = strtok( NULL, pszDelimiters );
  400. if( pszToken == NULL ||
  401. _stricmp( pszToken, "|" ) )
  402. {
  403. return 0;
  404. }
  405. //
  406. // Finally, the mangled (decorated) symbol itself.
  407. //
  408. pszPotentialSymbol = strtok( NULL, pszDelimiters );
  409. if( pszPotentialSymbol == NULL )
  410. {
  411. return 0;
  412. }
  413. //
  414. // Strip prefix from PowerPC function symbols
  415. //
  416. if( _fPowerPC )
  417. {
  418. pszPotentialSymbol += 2 ;
  419. }
  420. //
  421. // Strip prefix from IA-64 function symbols
  422. //
  423. if( _fIA64 )
  424. {
  425. pszPotentialSymbol += 1 ;
  426. }
  427. if( strlen( pszPotentialSymbol ) > MAX_SYMBOL )
  428. {
  429. fprintf( stderr,
  430. _szSymbolTooLong,
  431. pszPotentialSymbol );
  432. return 0;
  433. }
  434. //
  435. // Got one.
  436. //
  437. strcpy( pszSymbol, pszPotentialSymbol );
  438. return 1;
  439. } // ExtractSymbol
  440. /*******************************************************************
  441. NAME: FatalError and NonFatalError
  442. SYNOPSIS: Prints an error message to stderr, then terminates
  443. the application.
  444. ENTRY: err - An error code for the exit()
  445. stdlib function.
  446. pszFmt - A format string for vsprintf().
  447. ... - Any other arguments required
  448. by the format string.
  449. HISTORY:
  450. KeithMo 09-Aug-1992 Created.
  451. ********************************************************************/
  452. void __cdecl NonFatalError (
  453. char * pszFmt,
  454. ... )
  455. {
  456. char szBuffer[MAX_ERROR_MESSAGE+1];
  457. va_list ArgPtr;
  458. va_start( ArgPtr, pszFmt );
  459. fprintf( stderr, "%s => ", _pszProgramName );
  460. vsprintf( szBuffer, pszFmt, ArgPtr );
  461. fprintf( stderr, "%s\n", szBuffer );
  462. va_end( ArgPtr );
  463. } // NonFatalError
  464. void __cdecl FatalError( int err,
  465. char * pszFmt,
  466. ... )
  467. {
  468. char szBuffer[MAX_ERROR_MESSAGE+1];
  469. va_list ArgPtr;
  470. va_start( ArgPtr, pszFmt );
  471. fprintf( stderr, "%s => ", _pszProgramName );
  472. vsprintf( szBuffer, pszFmt, ArgPtr );
  473. fprintf( stderr, "%s\n", szBuffer );
  474. va_end( ArgPtr );
  475. Cleanup();
  476. exit( err );
  477. } // FatalError
  478. /*******************************************************************
  479. NAME: IsHexNumber
  480. SYNOPSIS: Determines if the specified string contains a hexadecimal
  481. number.
  482. ENTRY: pszHexNumber - The hex number.
  483. EXIT: int - !0 if it *is* a hex number,
  484. 0 if it isn't.
  485. HISTORY:
  486. KeithMo 12-Aug-1992 Created.
  487. ********************************************************************/
  488. int IsHexNumber( char * pszHexNumber )
  489. {
  490. int fResult = 1;
  491. char ch;
  492. while( ch = *pszHexNumber++ )
  493. {
  494. if( !isxdigit( ch ) )
  495. {
  496. fResult = 0;
  497. break;
  498. }
  499. }
  500. return fResult;
  501. } // IsHexNumber
  502. /*******************************************************************
  503. NAME: NoPath
  504. SYNOPSIS: Extracts the filename portion of a path.
  505. ENTRY: pszPathName - Contains a path name. The name
  506. is not necessarily canonicalized,
  507. and may contain just a filename
  508. component.
  509. EXIT: char * - The filename component.
  510. HISTORY:
  511. KeithMo 09-Aug-1992 Created.
  512. ********************************************************************/
  513. char * NoPath( char * pszPathName )
  514. {
  515. char * pszTmp;
  516. char ch;
  517. pszTmp = pszPathName;
  518. while( ( ch = *pszPathName++ ) != '\0' )
  519. {
  520. if( ( ch == '\\' ) || ( ch == ':' ) )
  521. {
  522. pszTmp = pszPathName;
  523. }
  524. }
  525. return pszTmp;
  526. } // NoPath
  527. /*******************************************************************
  528. NAME: ProcessCommandLine
  529. SYNOPSIS: Parse command line arguments, setting appropriate globals.
  530. ENTRY: cArgs - Number of command line arguments.
  531. pArgs - An array of pointers to the
  532. command line arguments.
  533. NOTES: See the Usage() function for valid command line arguments.
  534. HISTORY:
  535. KeithMo 12-Aug-1992 Broke out of main().
  536. DaveWolfe 06-Jul-1994 Added -ppc.
  537. ********************************************************************/
  538. void ProcessCommandLine( int cArgs,
  539. char * pArgs[] )
  540. {
  541. int i;
  542. char chSwitch;
  543. //
  544. // Setup our defaults.
  545. //
  546. _fileIn = stdin;
  547. _fileOut = stdout;
  548. _fileHeader = NULL;
  549. _fStripLeadingUnderscore = 0;
  550. _fNukeStdcallDecoration = 0;
  551. _fPowerPC = 0;
  552. _fIA64 = 0;
  553. //
  554. // Parse the command line arguments.
  555. //
  556. for( i = 1 ; i < cArgs ; i++ )
  557. {
  558. //
  559. // Get the argument.
  560. //
  561. char * pszArg = pArgs[i];
  562. char * pszParam;
  563. //
  564. // All of our valid arguments *must* start
  565. // with a switch character. Enforce this.
  566. //
  567. if( ( *pszArg != '-' ) && ( *pszArg != '/' ) )
  568. {
  569. Usage();
  570. }
  571. chSwitch = *++pszArg;
  572. //
  573. // pszParam will either be NULL (for switches such
  574. // as -s) or point to the text just past the colon
  575. // (for switches such as -i:file).
  576. //
  577. if( ( pszArg[1] == ':' ) && ( pszArg[2] != '\0' ) )
  578. {
  579. pszParam = pszArg + 2;
  580. }
  581. else
  582. {
  583. pszParam = NULL;
  584. }
  585. //
  586. // Check for valid arguments.
  587. //
  588. switch( chSwitch )
  589. {
  590. case 'p' :
  591. case 'P' :
  592. //
  593. // -ppc
  594. //
  595. // Strip prefix ".." from "..symbol".
  596. //
  597. if( _stricmp( pszArg, "ppc") != 0 )
  598. {
  599. Usage();
  600. }
  601. _fPowerPC = 1;
  602. break;
  603. case 'h' :
  604. case 'H' :
  605. //
  606. // -h:header_file
  607. //
  608. // If a header file has already been specified, or
  609. // if there is no parameter after the switch, bag-out.
  610. //
  611. if( ( _fileHeader != NULL ) || ( pszParam == NULL ) )
  612. {
  613. Usage();
  614. }
  615. _fileHeader = fopen( pszParam, "r" );
  616. if( _fileHeader == NULL )
  617. {
  618. FatalError( 1, _szCannotOpenForRead, pszParam );
  619. }
  620. break;
  621. case 'i' :
  622. case 'I' :
  623. if (pszParam == NULL) {
  624. //
  625. // -ia64
  626. //
  627. // Strip prefix "." from ".symbol".
  628. //
  629. if( _stricmp( pszArg, "ia64") != 0 )
  630. {
  631. Usage();
  632. }
  633. _fIA64 = 1;
  634. } else {
  635. //
  636. // -i:input_file
  637. //
  638. // If an input file has already been specified, or
  639. // if there is no parameter after the switch, bag-out.
  640. //
  641. if( ( _fileIn != stdin ) || ( pszParam == NULL ) )
  642. {
  643. Usage();
  644. }
  645. _fileIn = fopen( pszParam, "r" );
  646. if( _fileIn == NULL )
  647. {
  648. FatalError( 1, _szCannotOpenForRead, pszParam );
  649. }
  650. }
  651. break;
  652. case 'o' :
  653. case 'O' :
  654. //
  655. // -o:output_file
  656. //
  657. // If an output file has already been specified, or
  658. // if there is no parameter after the switch, bag-out.
  659. //
  660. if( ( _fileOut != stdout ) || ( pszParam == NULL ) )
  661. {
  662. Usage();
  663. }
  664. _fileOut = fopen( pszParam, "w" );
  665. if( _fileOut == NULL )
  666. {
  667. FatalError( 1, _szCannotOpenForWrite, pszParam );
  668. }
  669. break;
  670. case 's' :
  671. case 'S' :
  672. //
  673. // -s
  674. //
  675. // If this switch has already been specified, bag-out.
  676. //
  677. if( _fStripLeadingUnderscore )
  678. {
  679. Usage();
  680. }
  681. _fStripLeadingUnderscore = 1;
  682. break;
  683. case 'n' :
  684. case 'N' :
  685. _fNukeStdcallDecoration = 1 ;
  686. break ;
  687. case 'x' :
  688. case 'X' :
  689. _pszExclusionListFile = pszParam ;
  690. break ;
  691. case '?' :
  692. //
  693. // -?
  694. //
  695. // Give the poor user a clue.
  696. //
  697. Usage();
  698. break;
  699. default :
  700. //
  701. // Invalid switch.
  702. //
  703. // Tell the user the bad news, then bag-out.
  704. //
  705. fprintf( stderr, _szInvalidSwitch, chSwitch );
  706. Usage();
  707. break;
  708. }
  709. }
  710. } // ProcessCommandLine
  711. /*******************************************************************
  712. NAME: StripStdcallDecoration
  713. SYNOPSIS: Stdcall builds use a weak form of type-safe linkage.
  714. This is implemented by appending "@nn" to the end
  715. of each symbol, where "nn" is the number of *bytes*
  716. passed as parameters.
  717. COFF, on the other hand, does *not* want to see
  718. this symbol decoration in .DEF files. So, we remove
  719. it here.
  720. ENTRY: pszSymbol - The symbol to munge.
  721. NOTES: This routine is *NOT* DBCS safe! Do we care?
  722. HISTORY:
  723. KeithMo 14-Sep-1992 Created.
  724. ********************************************************************/
  725. void StripStdcallDecoration( char * pszSymbol )
  726. {
  727. int count = 0 ;
  728. //
  729. // Find the last character.
  730. //
  731. pszSymbol += strlen( pszSymbol ) - 1;
  732. //
  733. // Skip any *decimal* numbers.
  734. //
  735. while( isdigit( *pszSymbol ) )
  736. {
  737. pszSymbol--;
  738. count++ ;
  739. }
  740. //
  741. // If we're now pointing at a "@", terminate the string here.
  742. //
  743. if( count && *pszSymbol == '@' )
  744. {
  745. *pszSymbol = '\0';
  746. }
  747. } // StripStdcallDecoration
  748. /*******************************************************************
  749. NAME: Usage
  750. SYNOPSIS: Displays usage information if the user gives us a
  751. bogus command line.
  752. HISTORY:
  753. KeithMo 09-Aug-1992 Created.
  754. DaveWolfe 06-Jul-1994 Added -ppc option.
  755. ********************************************************************/
  756. void Usage( void )
  757. {
  758. fprintf( stderr, "use: %s [options]\n", _pszProgramName );
  759. fprintf( stderr, "\n" );
  760. fprintf( stderr, "Valid options are:\n" );
  761. fprintf( stderr, " -i:input_file = source file\n" );
  762. fprintf( stderr, " -o:output_file = destination file\n" );
  763. fprintf( stderr, " -h:header_file = header to prepend before symbols\n" );
  764. fprintf( stderr, " -s = strip first leading underscore from symbols\n" );
  765. fprintf( stderr, " -n = do not strip __stdcall decoration @nn\n" );
  766. fprintf( stderr, " -x:excl_file = name of file containing excluded symbols\n" );
  767. fprintf( stderr, " -ppc = input is PowerPC symbol dump\n" );
  768. fprintf( stderr, " -ia64 = input is IA-64 symbol dump\n" );
  769. fprintf( stderr, " -? = show this help\n" );
  770. fprintf( stderr, "\n" );
  771. fprintf( stderr, "Defaults are:\n" );
  772. fprintf( stderr, " input_file = stdin\n" );
  773. fprintf( stderr, " output_file = stdout\n" );
  774. fprintf( stderr, " header_file = none\n" );
  775. fprintf( stderr, " don't strip first leading underscore from symbol\n" );
  776. fprintf( stderr, " input is not PowerPC symbol dump\n" );
  777. Cleanup();
  778. exit( 1 );
  779. } // Usage
  780. /*******************************************************************
  781. NAME: CreateExclusionList
  782. SYNOPSIS: Reads a text file of excluded export names into memory,
  783. sorts it and builds a lookup table compatible with
  784. bsearch().
  785. Returns -1 if failure or the count of the number
  786. of items in the created array.
  787. HISTORY:
  788. ********************************************************************/
  789. int __cdecl qsortStrings ( const void * pa, const void * pb )
  790. {
  791. return strcmp( *((const char * *) pa), *((const char * *) pb) ) ;
  792. }
  793. int CreateExclusionList ( char * pszFileName,
  794. void * * pvData,
  795. char * * * apszStrings )
  796. {
  797. int cItems, i ;
  798. int result = -1 ;
  799. long cbFileSize, cbBlockSize ;
  800. char * pszData = NULL,
  801. * psz,
  802. * pszNext ;
  803. char * * ppszArray = NULL ;
  804. char chRec [ MAX_LINE_FROM_COFF ] ;
  805. FILE * pf = NULL ;
  806. do
  807. {
  808. pf = fopen( pszFileName, "r" ) ;
  809. if ( pf == NULL )
  810. break;
  811. if (fseek( pf, 0, SEEK_END ) == -1)
  812. break;
  813. cbFileSize = ftell( pf ) ;
  814. if (fseek( pf, 0, SEEK_SET ) == -1)
  815. break;
  816. cbBlockSize = cbFileSize + (cbFileSize / 2) ;
  817. pszData = (char *) malloc( cbBlockSize ) ;
  818. if ( pszData == NULL )
  819. break ;
  820. for ( cItems = 0, pszNext = pszData ;
  821. (!feof( pf )) && (psz = fgets( chRec, sizeof chRec, pf )) ; )
  822. {
  823. int lgt ;
  824. char * pszEnd ;
  825. while ( *psz <= ' ' && *psz != 0 )
  826. {
  827. psz++ ;
  828. }
  829. if ( (lgt = strlen( psz )) == 0 )
  830. continue ;
  831. pszEnd = psz + lgt ;
  832. do
  833. {
  834. --pszEnd ;
  835. } while ( pszEnd > psz && *pszEnd <= ' ' ) ;
  836. lgt = (int)(++pszEnd - psz) ;
  837. *pszEnd = 0 ;
  838. if ( pszNext + lgt - pszData >= cbBlockSize )
  839. {
  840. cItems = -1 ;
  841. break ;
  842. }
  843. strcpy( pszNext, psz ) ;
  844. pszNext += lgt+1 ;
  845. cItems++ ;
  846. }
  847. *pszNext = 0 ;
  848. if ( cItems <= 0 )
  849. {
  850. if ( cItems == 0 )
  851. result = 0 ;
  852. break ;
  853. }
  854. ppszArray = (char * *) malloc( cItems * sizeof (char *) ) ;
  855. if ( ppszArray == NULL )
  856. break ;
  857. for ( i = 0, pszNext = pszData ;
  858. *pszNext ;
  859. pszNext += strlen( pszNext ) + 1 )
  860. {
  861. ppszArray[i++] = pszNext ;
  862. }
  863. qsort( (void *) ppszArray,
  864. cItems,
  865. sizeof (char *),
  866. & qsortStrings ) ;
  867. result = cItems ;
  868. } while ( 0 ) ;
  869. if ( pf != NULL )
  870. {
  871. fclose( pf ) ;
  872. }
  873. if ( result <= 0 )
  874. {
  875. if ( pszData )
  876. {
  877. free( pszData ) ;
  878. pszData = NULL ;
  879. }
  880. if ( ppszArray )
  881. {
  882. free( ppszArray ) ;
  883. ppszArray = NULL ;
  884. }
  885. }
  886. *pvData = (void *) pszData ;
  887. *apszStrings = ppszArray ;
  888. return result ;
  889. }
  890. int ExcludedSymbol ( char * pszSymbol )
  891. {
  892. if ( _apszExclusionArray == NULL )
  893. {
  894. return 0 ;
  895. }
  896. return bsearch( (void *) & pszSymbol,
  897. (void *) _apszExclusionArray,
  898. _cExclusionItems,
  899. sizeof (char *),
  900. & qsortStrings ) != NULL ;
  901. }
  902. int ValidSymbol ( const char * psz )
  903. {
  904. int i = 0 ;
  905. for ( ; apszIgnore[i] ; i++ )
  906. {
  907. if ( _strnicmp( apszIgnore[i],
  908. psz,
  909. strlen( apszIgnore[i] ) ) == 0 )
  910. return 0 ;
  911. }
  912. return 1 ;
  913. }
  914. // End of UIXPORT.C