xref: /aoo41x/main/soltools/ldump/ldump.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_soltools.hxx"
30 
31 #include <string.h>
32 #include <direct.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 
36 #include "ldump.hxx"
37 #include "hashtbl.hxx"
38 
39 #define MAXSYM     65536
40 #define MAXBASE    98304
41 #define MAX_MAN		4096
42 
43 int	bFilter = 0;
44 int bLdump3 = 0;
45 int bUseDirectives = 0;
46 int bVerbose = 0;
47 int bExportByName = 0;
48 
49 class ExportSet : public HashTable
50 {
51 public:
52     ExportSet
53     (
54         unsigned long lSize,
55         double	dMaxLoadFactor = HashTable::m_defMaxLoadFactor,
56         double	dGrowFactor = HashTable::m_defDefGrowFactor
57     )
58         : HashTable(lSize,false,dMaxLoadFactor,dGrowFactor) {}
59 
60     virtual ~ExportSet() {}
61 
62     LibExport *  Find (char * const& Key) const
63     { return (LibExport *) HashTable::Find((char *) Key); }
64 
65     bool Insert (char * const& Key, LibExport * Object)
66     { return HashTable::Insert((char *) Key, (void*) Object); }
67 
68     LibExport *  Delete (char * const&Key)
69     { return (LibExport *) HashTable::Delete ((char *) Key); }
70 };
71 
72 LibDump::LibDump( char *cFileName, int bExportByName )
73 				: cBName( NULL ),
74 				cAPrefix( NULL ),
75 				cLibName( NULL ),
76 				cFilterName( NULL ),
77 				cModName( NULL )
78 {
79 	fprintf( stderr, "LIB-NT File Dumper v4.00 (C) 2000 Sun Microsystems, Inc.\n\n" );
80 	fprintf( stderr, "%s ", cFileName );
81 
82     bExportName = bExportByName;
83 
84 	unsigned long nSlots =  0xfffff;
85 	pBaseTab = new ExportSet( nSlots );
86 	pIndexTab = new ExportSet( nSlots );
87 	pFilterLines = new char * [MAXFILT];
88 	CheckLibrary(cFileName);
89 	bBase = 0;
90 	bAll = false;
91 	nDefStart = 0;
92 	nBaseLines = 0;
93 	nFilterLines = 0;
94 	bDef = true;
95 	cAPrefix = new char[ 1 ];
96 	cAPrefix[ 0 ] = 0;
97     if (!bExportName)
98 	    CheckDataBase();
99 }
100 
101 bool LibDump::Dump()
102 {
103 	FILE *pList;
104     char  aBuf[MAX_MAN];
105     int   nLen;
106     char  aName[MAX_MAN];
107 
108     pList = fopen( cLibName, "rb");
109 	if (!pList)
110 		DumpError(10);
111 
112     // forget about offset when working on linker directives
113     if ( !bUseDirectives )
114     {
115         // calculating offset for name section
116     	unsigned char TmpBuffer[4];
117 	    fread( TmpBuffer, 1, 4, pList);
118     	// anzahl bigendian mal laenge + ueberspringen der naechsten laengenangabe
119     	unsigned long nOffSet = (unsigned long) ( TmpBuffer[2] * 256 + TmpBuffer[3] ) * 4 + 4;
120     	fseek( pList, (long) nOffSet, 0);
121     }
122 
123 	char aTmpBuf[4096];
124 	// reading file containing symbols
125     while( !feof( pList ) )
126     {
127    		int i = 0;
128         if ( !bUseDirectives )
129         {
130 	    	// symbol komplett einlesen
131             for (;;)
132             {
133                 int c = fgetc( pList );
134                 if ( c == '\0' )
135                 {
136                     break;
137                 }
138                 if ( ((c >= 33) && (c <= 126)) && ( c!=40 && c!=41) )
139                 	aBuf[i] = static_cast< char >(c);
140                 else
141                 {
142                     aBuf[0] = '\0';
143                     break;
144                 }
145             	i++;
146             }
147     		// Namen found
148             aBuf[i] = '\0';
149         }
150         else
151         {
152             fgets( aTmpBuf, 4096, pList );
153             char * pEnd = 0;
154             char *pFound = 0;
155             aBuf[0] = '\0';
156             pFound = strchr( aTmpBuf, 'E' );
157             while ( pFound )
158             {
159                 if ( strncmp( "EXPORT:", pFound, 7) == 0 )
160                 {
161                     pFound += 7;
162                     pEnd = strchr( pFound, ',');
163                     if ( pEnd )
164                         *pEnd = '\0';
165                     strncpy( aBuf, pFound, strlen( pFound));
166                     aBuf[ strlen( pFound) ] = '\0';
167 //                    fprintf( stderr, "\n--- %s\n", aBuf);
168                     break;
169                 }
170                 else
171                 {
172                     pFound++;
173                     pFound = strchr( pFound, 'E' );
174                 }
175             }
176         }
177 
178 	    if ((aBuf[0] =='?') || !strncmp(aBuf, "__CT",4))
179 		{
180 			nLen = (int) strlen(aBuf);
181             memset( aName, 0, sizeof( aName ) );
182             int nName = 0;
183             for( i = 0; i < nLen; i++ )
184             {
185                 if ( (aBuf[i] != '\n') && (aBuf[i] != '\r') )
186                 {
187                     aName[nName] = aBuf[i];
188                     nName++;
189                 }
190             }
191 			// und raus damit
192             PrintSym( aName, bExportByName );
193 		}
194 		else if ( bAll == true )
195 		{
196 			int nPreLen = (int) strlen( cAPrefix );
197 
198             nLen = (int) strlen(aBuf);
199             memset( aName, 0, sizeof( aName ) );
200             int nName = 0;
201 
202             for( i = 0; i < nLen; i++ )
203             {
204               if ( (aBuf[i] != '\n') && (aBuf[i] != '\r') )
205               {
206                   aName[nName] = aBuf[i];
207                   nName++;
208 			  }
209 			}
210 			//fprintf( stderr, "Gefundenen Prefix : %s %d \n", aTmpBuf, nPreLen );
211 			// den ersten _ raus
212             nLen = (int) strlen(aName);
213             if (aName[0] == '_')
214 				strcpy( aBuf , &aName[1] );
215 			strncpy ( aTmpBuf, aBuf, (size_t) nPreLen );
216 			aTmpBuf[nPreLen] = '\0';
217 			if ( !strcmp( aTmpBuf, cAPrefix ))
218 			{
219 				if ( bLdump3 ) {
220 					int nChar = '@';
221 					char *pNeu = strchr( aBuf, nChar );
222 					int nPos = pNeu - aBuf + 1;
223 					if ( nPos > 0 )
224 					{
225 						char aOldBuf[MAX_MAN];
226 						strcpy( aOldBuf, aBuf );
227 						char pChar[MAX_MAN];
228 						strncpy( pChar, aBuf, (size_t) (nPos -1) );
229 						pChar[nPos-1] = '\0';
230 						strcpy( aBuf, pChar );
231 						strcat( aBuf, "=" );
232 						strcat( aBuf, aOldBuf );
233 						strcpy( pChar, "" );
234 					}
235 				}
236 				// und raus damit
237             	PrintSym( aBuf, true );
238 			}
239 		}
240     }
241 	fclose(pList);
242 	return true;
243 }
244 
245 bool LibDump::ReadFilter( char * cFilterName )
246 {
247 	FILE* pfFilter = 0;
248     char  aBuf[MAX_MAN];
249     char* pStr;
250     int   nLen;
251 
252     pfFilter = fopen( cFilterName, "r" );
253 
254     if ( !pfFilter )
255     {
256         ::bFilter = 0;
257         DumpError( 500 );
258     }
259 
260     while( fgets( aBuf, MAX_MAN, pfFilter ) != 0 )
261     {
262         nLen = (int) strlen(aBuf);
263         pStr = new char[(unsigned int) nLen];
264         if ( !pStr )
265             DumpError( 98 );
266         memcpy( pStr, aBuf, (unsigned int) nLen );
267         if ( *(pStr+nLen-1) == '\n' )
268             *(pStr+nLen-1) = '\0';
269 		pFilterLines[nFilterLines] = pStr;
270 		nFilterLines++;
271 		if ( nFilterLines >= MAXFILT )
272 				DumpError( 510 );
273     }
274 
275 	fclose( pfFilter );
276 	return true;
277 }
278 
279 bool LibDump::PrintSym(char *pName, bool bName )
280 {
281 	LibExport *pData;
282 
283 
284     // Filter auswerten
285     if ( Filter( pName ) )
286     {
287         if ( strlen( pName ) > 3 )
288         {
289             if ( bDef )
290 		    {
291 		        if (!bBase)
292                     if (bExportName) {
293 						fprintf( stdout, "\t%s\n", pName );
294                     } else {
295 						fprintf( stdout, "\t%s\t\t@%lu\n", pName, nDefStart );
296                     }
297 				else
298 				{
299 					 pData = pBaseTab->Find( pName );
300 					 if ( pData )
301 					 {
302 						pData->bExport = true;
303 						if ( bName )
304 							pData->bByName = true;
305 						else
306 							pData->bByName = false;
307 						if ( bVerbose )
308 							fprintf(stderr,".");
309 					 }
310 					 else
311 					 {
312 					 	// neuen Export eintragen
313 					 	pData = new LibExport;
314 						pData->cExportName = new char[ strlen( pName ) + 1 ];
315 						strcpy( pData->cExportName, pName );
316 						pData->nOrdinal = nBaseLines++;
317 						pData->bExport = true;
318 						if ( bName )
319 							pData->bByName = true;
320 						else
321 							pData->bByName = false;
322 						pBaseTab->Insert( pData->cExportName, pData );
323 						char *cBuffer = new char[ 30 ];
324 						sprintf( cBuffer, "%lu", pData->nOrdinal );
325 						pIndexTab->Insert( cBuffer, pData );
326 						delete [] cBuffer;
327 						if ( bVerbose )
328 							fprintf(stderr,"n");
329 					 }
330 				}
331 		    }
332             else
333                 printf( "%s\n", pName );
334             nDefStart++;
335         }
336     }
337 	return true;
338 }
339 
340 bool LibDump::IsFromAnonymousNamespace (char *pExportName) {
341     char* pattern1 = "@?A0x";
342 
343     if (strstr(pExportName, pattern1)) {
344         return true;
345     };
346     return false;
347 };
348 
349 bool LibDump::Filter(char *pExportName)
350 {
351 	unsigned long i;
352 	char pTest[256];
353 
354     // filter out symbols from anonymous namespaces
355     if (IsFromAnonymousNamespace (pExportName))
356         return false;
357 
358     // Kein Filter gesetzt
359     if ( ::bFilter == 0 )
360         return true;
361 
362 	for ( i=0; i<nFilterLines; i++ )
363 	{
364 		//Zum vergleichen mu� das Plus abgeschnitteb werden
365 		if(pFilterLines[i][0] != '+')
366 		{
367 			if ( strstr( pExportName, pFilterLines[i]))
368 				return false;
369 		}
370 		else
371 		{
372 			strcpy(pTest,&pFilterLines[i][1]);
373 			if ( strstr( pExportName, pTest))
374 				return true;
375 		}
376 	}
377     return true;
378 }
379 
380 bool LibDump::SetFilter(char * cFilterName)
381 {
382 	ReadFilter( cFilterName );
383 	return true;
384 }
385 
386 bool LibDump::CheckLibrary(char * cName)
387 {
388 	delete [] cLibName;
389 	cLibName = new char[ strlen( cName ) + 1 ];
390 	strcpy( cLibName, cName );
391 	return true;
392 }
393 
394 bool LibDump::ReadDataBase()
395 {
396 	FILE* pfBase = 0;
397     char  aBuf[MAX_MAN];
398     char* pStr;
399     char  cBuffer[ 30 ];
400     int   nLen;
401 	LibExport *pData;
402 
403     pfBase = fopen( cBName, "r" );
404 
405     if ( !pfBase )
406     {
407         bBase = 0;
408         DumpError( 600 );
409     }
410 
411 	bool bRet = true;
412 	while( fgets( aBuf, MAX_MAN, pfBase ) != 0 )
413     {
414         nLen = (int) strlen(aBuf);
415         pStr = new char[(unsigned int) nLen];
416         if ( !pStr )
417             DumpError( 98 );
418         memcpy( pStr, aBuf, (size_t) nLen );
419         if ( *(pStr+nLen-1) == '\n' )
420             *(pStr+nLen-1) = '\0';
421 		pData = new LibExport;
422 		pData->cExportName = pStr;
423 		pData->nOrdinal = nBaseLines;
424 		pData->bExport=false;
425 
426 		if (pBaseTab->Insert(pData->cExportName, pData ) == NULL)
427 			bRet = false;
428         ltoa( (long) pData->nOrdinal, cBuffer, 10 );
429 		if (pIndexTab->Insert( cBuffer, pData ) == NULL)
430 			bRet = false;
431         nBaseLines++;
432         if ( nBaseLines >= MAXBASE )
433             DumpError( 610 );
434     }
435     fclose( pfBase );
436 	return bRet;
437 }
438 
439 class ExportSetIter : public HashTableIterator
440 {
441 public:
442     ExportSetIter(HashTable const& aTable)
443 		: HashTableIterator(aTable)	{}
444 
445     LibExport * GetFirst()
446     { return (LibExport *)HashTableIterator::GetFirst(); }
447     LibExport * GetNext()
448     { return (LibExport *)HashTableIterator::GetNext();  }
449     LibExport * GetLast()
450     { return (LibExport *)HashTableIterator::GetLast();  }
451     LibExport * GetPrev()
452     { return (LibExport *)HashTableIterator::GetPrev();  }
453 
454 private:
455     void operator =(ExportSetIter &); // not defined
456 };
457 
458 bool LibDump::PrintDataBase()
459 {
460     if (bExportName)
461         return true;
462 	FILE *pFp;
463 	pFp = fopen (cBName,"w+");
464 	if (!pFp)
465 		fprintf( stderr, "Error opening DataBase File\n" );
466 
467 	LibExport *pData;
468 	for ( unsigned long i=0; i < nBaseLines+10; i++ )
469 	{
470 		char * cBuffer = new char[ 30 ];
471 		sprintf( cBuffer, "%lu", i );
472 		pData = pIndexTab->Find( cBuffer );
473 		delete [] cBuffer;
474 		if ( pData )
475 			fprintf(pFp,"%s\n",pData->cExportName);
476 	}
477 	fclose(pFp);
478 	return true;
479 }
480 
481 bool LibDump::PrintDefFile()
482 {
483 #ifdef FAST
484 	ExportSetIter aIterator( *pBaseTab );
485 	for ( LibExport *pData = aIterator.GetFirst(); pData != NULL;
486 										pData = aIterator.GetNext() )
487 	{
488 		if ( pData->bExport )
489 		{
490 			if ( pData->bByName )
491 			{
492 				fprintf(stdout,"\t%s\n",
493 					pData->sExportName.GetBuffer());
494 			}
495 			else
496 			{
497 				fprintf(stdout,"\t%s\t\t@%d NONAME\n",
498 					pData->sExportName.GetBuffer(), pData->nOrdinal+nBegin);
499 			}
500 		}
501 	}
502 #else
503 	// sortiert nach Ordinals;
504 	LibExport *pData;
505 	for ( unsigned long i=0; i<nBaseLines+1; i++)
506 	{
507 		char * cBuffer = new char[ 30 ];
508 		sprintf( cBuffer, "%lu", i );
509 		pData = pIndexTab->Find( cBuffer );
510 		delete [] cBuffer;
511 		if ( pData )
512 			if ( pData->bExport )
513 			{
514 				if ( pData->bByName )
515 				{
516 					if ( strlen( pData->cExportName ))
517 						fprintf(stdout,"\t%s\n",
518 							pData->cExportName);
519 				}
520 				else
521 				{
522 					if ( strlen( pData->cExportName ))
523 						fprintf(stdout,"\t%s\t\t@%d NONAME\n",
524 							pData->cExportName, pData->nOrdinal+nBegin);
525 				}
526 			}
527 	}
528 #endif
529 	return true;
530 }
531 
532 bool LibDump::CheckDataBase()
533 {
534     // existiert eine Datenbasis ?
535     if (!bBase)
536     {
537 		cBName = new char[ 2048 ];
538 		char *pTmp = "defs\\";
539 
540     	FILE *fp;
541 #ifdef OS2
542 		_mkdir ("defs", 0777);
543 #else
544 		_mkdir ("defs");
545 #endif
546 		strcpy(cBName,pTmp);
547 #ifdef OS2
548 		strcat(cBName,"gcc");
549 #else
550 		strcat(cBName,getenv ("COMP_ENV"));
551 #endif
552 
553 		fp = fopen (cBName,"r");
554 		if (fp)
555 		{
556 			bBase = true;
557 		}
558 		else
559 		{
560 			fp = fopen (cBName,"w+");
561 			bBase = true;
562 		}
563 		fclose (fp);
564     }
565     // lese Datenbasis !
566     if (bBase)
567 	{
568     	ReadDataBase();
569 	}
570 	return true;
571 }
572 
573 LibDump::~LibDump()
574 {
575 	delete [] cBName;
576 	delete [] cAPrefix;
577 //	delete [] cLibName;
578 	delete [] cFilterName;
579 	delete [] cModName;
580 }
581 
582 void LibDump::SetCExport( char* pName )
583 {
584 	delete [] cAPrefix;
585 	cAPrefix = new char[ strlen( pName ) + 1 ];
586 	strcpy( cAPrefix, pName );bAll = true;
587 }
588 
589 //******************************************************************
590 //* Error() - Gibt Fehlermeldumg aus
591 //******************************************************************
592 
593 void LibDump::DumpError( unsigned long n )
594 {
595     char *p;
596 
597     switch (n)
598     {
599         case 1:  p = "Input error in library file"; break;
600         case 2:  p = "Position error in library file (no THEADR set)"; break;
601         case 3:  p = "Overflow of symbol table"; break;
602 #ifdef WNT
603         case 10: p = "EXP file not found"; break;
604         case 11: p = "No valid EXP file"; break;
605 #else
606         case 10: p = "Library file not found"; break;
607         case 11: p = "No valid library file"; break;
608 #endif
609         case 98: p = "Out of memory"; break;
610         case 99: p = "LDUMP [-LD3] [-D] [-N] [-A] [-E nn] [-F name] Filename[.LIB]\n"
611 					 "-LD3   : Supports feature set of ldump3 (default: ldump/ldump2)\n"
612                      "-A     : all symbols (default: only C++)\n"
613                      "-E nn  : gerenration of export table beginning with number nn\n"
614                      "-F name: Filter file\n"
615                      "-D     : file contains \"dumpbin\" directives\n"
616                      "-N     : export by name\n"
617                      "-V     : be verbose\n"; break;
618         case 500: p = "Unable to open filter file\n"; break;
619         case 510: p = "Overflow of filter table\n"; break;
620         case 600: p = "Unable to open base database file\n"; break;
621         case 610: p = "Overflow in base database table\n"; break;
622         default: p = "Unspecified error";
623     }
624 	fprintf( stdout, "%s\n", p );
625     exit (1);
626 }
627 
628 /*********************************************************************
629 		Test Funktionen
630 *********************************************************************/
631 
632 
633 void usage()
634 {
635 	LibDump::DumpError(99);
636 }
637 
638 #define STATE_NON		0x0000
639 #define STATE_BEGIN		0x0001
640 #define STATE_FILTER	0x0002
641 #define STATE_CEXPORT	0x0003
642 
643 int
644 #ifdef WNT
645 __cdecl
646 #endif
647 main( int argc, char **argv )
648 {
649 	char *pLibName = NULL, *pFilterName = NULL, *pCExport= NULL;
650 	unsigned short nBegin=1;
651 
652 	unsigned short nState = STATE_NON;
653 
654 	if ( argc == 1 ) {
655 		usage();
656 	}
657 
658 	for ( int i = 1; i < argc; i++ ) {
659 		if (( !strcmp( argv[ i ], "-H" )) ||
660 			( !strcmp( argv[ i ], "-h" )) ||
661 			( !strcmp( argv[ i ], "-?" )))
662 		{
663 			usage();
664 		}
665 		else if (( !strcmp( argv[ i ], "-LD3" )) ||
666 			( !strcmp( argv[ i ], "-Ld3" )) ||
667 			( !strcmp( argv[ i ], "-ld3" )) ||
668 			( !strcmp( argv[ i ], "-lD3" )))
669 		{
670 			if ( nState != STATE_NON ) {
671 				usage();
672 			}
673 			bLdump3 = 1;
674 		}
675 		else if (( !strcmp( argv[ i ], "-E" )) || ( !strcmp( argv[ i ], "-e" ))) {
676 			if ( nState != STATE_NON ) {
677 				usage();
678 			}
679 			nState = STATE_BEGIN;
680 		}
681 		else if (( !strcmp( argv[ i ], "-F" )) || ( !strcmp( argv[ i ], "-f" ))) {
682 			if ( nState != STATE_NON ) {
683 				usage();
684 			}
685 			nState = STATE_FILTER;
686 		}
687 		else if (( !strcmp( argv[ i ], "-A" )) || ( !strcmp( argv[ i ], "-a" ))) {
688 			if ( nState != STATE_NON ) {
689 				usage();
690 			}
691 			nState = STATE_CEXPORT;
692 			pCExport = new char[ 1 ];
693 			pCExport[ 0 ] = 0;
694 		}
695 		else if (( !strcmp( argv[ i ], "-D" )) || ( !strcmp( argv[ i ], "-d" ))) {
696 			if ( nState != STATE_NON ) {
697 				usage();
698 			}
699             bUseDirectives = 1;
700 		}
701 		else if (( !strcmp( argv[ i ], "-N" )) || ( !strcmp( argv[ i ], "-n" ))) {
702 			if ( nState != STATE_NON ) {
703 				usage();
704 			}
705             bExportByName = 1;
706 		}
707 		else if (( !strcmp( argv[ i ], "-V" )) || ( !strcmp( argv[ i ], "-v" ))) {
708 			if ( nState != STATE_NON ) {
709 				usage();
710 			}
711             bVerbose = 1;
712 		}
713 		else {
714 			switch ( nState ) {
715 				case STATE_BEGIN:
716 					nBegin = static_cast< unsigned short >(atoi( argv[ i ] ));
717 					nState = STATE_NON;
718 				break;
719 				case STATE_FILTER:
720 					pFilterName = new char[ strlen( argv[ i ] ) + 1 ];
721 					strcpy( pFilterName, argv[ i ] );
722 					bFilter = 1;
723 					nState = STATE_NON;
724 				break;
725 				case STATE_CEXPORT:
726 					delete [] pCExport;
727 					pCExport = new char[ strlen( argv[ i ] ) + 1 ];
728 					strcpy( pCExport, argv[ i ] );
729 					nState = STATE_NON;
730 				break;
731 				default:
732 					pLibName = new char[ strlen( argv[ i ] ) + 1 ];
733 					strcpy( pLibName, argv[ i ] );
734 				break;
735 			}
736 		}
737 	}
738 
739 	if ( !pLibName ) {
740 		usage();
741 	}
742 
743 	LibDump *pDump = new LibDump( pLibName, bExportByName );
744 	pDump->SetBeginExport(nBegin);
745 	if ( bFilter != 0 )
746 		pDump->SetFilter( pFilterName );
747 	if ( pCExport )
748 		pDump->SetCExport( pCExport );
749 	else {
750 		char *pEmpty = "";
751 		pDump->SetCExport( pEmpty );
752 	}
753 	pDump->Dump();
754 	pDump->PrintDefFile();
755 	pDump->PrintDataBase();
756 	delete pDump;
757 	return 0;
758 }
759