Kaydet (Commit) a6f361b0 authored tarafından Peter Foley's avatar Peter Foley

remove dmake-only utils

Change-Id: Id0723277613cf1867b28dbd98c2249ff9ea73649
üst 84374b2d
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
$(eval $(call gb_Helper_register_executables,NONE, \ $(eval $(call gb_Helper_register_executables,NONE, \
HelpIndexer \ HelpIndexer \
HelpLinker \ HelpLinker \
adjustvisibility \
bestreversemap \ bestreversemap \
bmp \ bmp \
bmpsum \ bmpsum \
...@@ -45,8 +44,6 @@ $(eval $(call gb_Helper_register_executables,NONE, \ ...@@ -45,8 +44,6 @@ $(eval $(call gb_Helper_register_executables,NONE, \
gsicheck \ gsicheck \
helpex \ helpex \
idxdict \ idxdict \
javadepend \
ldump4 \
lngconvex \ lngconvex \
localize \ localize \
makedepend \ makedepend \
......
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
$(eval $(call gb_Executable_Executable,adjustvisibility))
ifeq ($(COM),MSC)
$(eval $(call gb_Executable_use_packages,adjustvisibility,\
soltools_inc \
))
endif
$(eval $(call gb_Executable_add_exception_objects,adjustvisibility,\
soltools/adjustvisibility/adjustvisibility \
))
# vim:set noet sw=4 ts=4:
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
$(eval $(call gb_Executable_Executable,javadep))
ifeq ($(COM),MSC)
$(eval $(call gb_Executable_use_packages,javadep,\
soltools_inc \
))
endif
$(eval $(call gb_Executable_add_cobjects,javadep,\
soltools/javadep/javadep \
))
# vim:set noet sw=4 ts=4:
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
$(eval $(call gb_Executable_Executable,ldump4))
$(eval $(call gb_Executable_add_exception_objects,ldump4,\
soltools/ldump/hashtbl \
soltools/ldump/ldump \
))
# vim:set noet sw=4 ts=4:
...@@ -12,21 +12,12 @@ $(eval $(call gb_Module_Module,soltools)) ...@@ -12,21 +12,12 @@ $(eval $(call gb_Module_Module,soltools))
ifneq ($(CROSS_COMPILING),YES) ifneq ($(CROSS_COMPILING),YES)
$(eval $(call gb_Module_add_targets,soltools,\ $(eval $(call gb_Module_add_targets,soltools,\
Executable_cpp \ Executable_cpp \
Executable_javadep \
Executable_makedepend \ Executable_makedepend \
)) ))
ifeq ($(OS)$(COM),SOLARISC52)
$(eval $(call gb_Module_add_targets,soltools,\
Executable_adjustvisibility \
))
endif # SOLARISC52
endif # CROSS_COMPILING endif # CROSS_COMPILING
ifeq ($(OS)$(COM),WNTMSC) ifeq ($(OS)$(COM),WNTMSC)
$(eval $(call gb_Module_add_targets,soltools,\ $(eval $(call gb_Module_add_targets,soltools,\
Executable_ldump4 \
Package_inc \ Package_inc \
)) ))
endif # WNTMSC endif # WNTMSC
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/*
* adjustvisibilty -- a tool to adjust the visibility of the so called
* 'fix and continue' globalized symbols generated by
* the Sun Studio 8 compiler from 'DEFAULT' to 'HIDDEN'
*
* References: "Linker and Libraries Guide", Solaris 9 documentation
* "Stabs Interface", SunStudio 8 documentation
*/
#include <string>
#include <cstring>
#include <iostream>
#include <exception>
#include <stdexcept>
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#include <libelf.h>
#include <gelf.h>
#include <utime.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits>
#include <stdio.h>
// Note: There is no GELF_ST_VISIBILITY macro in gelf.h, we roll our own.
#define GELF_ST_VISIBILITY(o) ((o)&0x3) // See "Linker and Libraries Guide".
// See "Linker and Libraries Guide", ELF object format description.
static const char* SymbolType[STT_NUM] = {
"NOTYPE",
"OBJECT",
"FUNC ",
"SECT ",
"FILE ",
"COMM ",
"TLS "
};
static const char* SymbolBinding[STB_NUM] = {
"LOCAL ",
"GLOBAL",
"WEAK "
};
static const char* SymbolVisibility[4] = { // Note: There is no STV_NUM macro
"DEFAULT ",
"INTERNAL ",
"HIDDEN ",
"PROTECTED"
};
class ElfError : public std::exception
{
public:
ElfError(const std::string& rFile, const std::string& rMessage);
~ElfError() throw() {};
virtual const char* what() const throw() { return m_sMessage.c_str(); }
private:
std::string m_sMessage;
};
ElfError::ElfError(const std::string& rFile, const std::string& rMessage)
{
if ( rFile != "" ) {
m_sMessage = rFile;
m_sMessage += ": ";
}
m_sMessage += rMessage;
const char *pElfMsg = elf_errmsg(0);
if ( pElfMsg ) {
m_sMessage += ": ";
m_sMessage += pElfMsg;
}
}
void initElfLib()
{
if ( elf_version(EV_CURRENT) == EV_NONE) {
throw ElfError("", "elf_version() failed");
}
return;
}
bool isFixAndContinueSymbol(const std::string& rSymbol)
{
// The globalized 'fix and continue' symbols have the following
// form, see "Stabs interface", page 164:
// {.$}X{ABC}uniquepattern[.function_name][EQUIVn][.variable_name]
char c0 = rSymbol[0];
char c1 = rSymbol[1];
char c2 = rSymbol[2];
if ( c0 == '.' || c0 == '$' ) {
if ( c1 == 'X' ) {
if ( c2 == 'A' || c2 == 'B' || c2 == 'C' || c2 == 'D' ) {
return true;
}
}
}
return false;
}
void adjustVisibility( const std::string& rFile, int fd, bool bVerbose)
{
if ( bVerbose ) {
std::cout << "File: " << rFile << ": adjusting 'fix and continue' symbol visibility\n";
}
try {
Elf* pElf;
if ((pElf = elf_begin(fd, ELF_C_RDWR, 0)) == NULL) {
throw ElfError(rFile, "elf_begin() failed");
}
// Check if file is ELF file.
if ( elf_kind(pElf) != ELF_K_ELF ) {
throw ElfError(rFile, "elf_kind() failed, file is not an ELF object file");
}
// Iterate over sections.
Elf_Scn* pScn = 0;
while ( (pScn = elf_nextscn(pElf, pScn)) != 0 ) {
GElf_Shdr aShdr;
if ( gelf_getshdr(pScn, &aShdr) == 0 ) {
throw ElfError(rFile, "gelf_getshdr() failed");
}
if ( aShdr.sh_type != SHT_SYMTAB ) {
continue;
}
// Section is a symbol section. Get the assiociated data.
Elf_Data* pSymbolData;
if ( (pSymbolData = elf_getdata(pScn, 0)) == NULL ) {
throw ElfError(rFile, "elf_getdata() failed");
}
// Iterate over symbol table.
GElf_Xword nSymbols = aShdr.sh_size / aShdr.sh_entsize;
if ( nSymbols > std::numeric_limits< int >::max() )
{
throw ElfError(rFile, "too many symbols");
}
for ( int nIndex = 0; nIndex < nSymbols; ++nIndex) {
// Get symbol.
GElf_Sym aSymbol;
if ( gelf_getsym(pSymbolData, nIndex, &aSymbol) == NULL )
{
throw ElfError(rFile, "gelf_getsym() failed");
}
std::string sSymbolName(elf_strptr(pElf, aShdr.sh_link, aSymbol.st_name));
if ( isFixAndContinueSymbol(sSymbolName) ) {
// Get the symbol visibility.
unsigned int nSymbolVisibility = GELF_ST_VISIBILITY(aSymbol.st_other);
if ( bVerbose ) {
// Get the symbol type and binding.
unsigned int nSymbolType = GELF_ST_TYPE(aSymbol.st_info);
unsigned int nSymbolBind = GELF_ST_BIND(aSymbol.st_info);
std::cout << "Symbol: " << sSymbolName << ", "
<< "Type: ";
if ( SymbolType[nSymbolType] ) {
std::cout << SymbolType[nSymbolType];
} else {
std::cout << nSymbolType;
}
std::cout << ", Binding: ";
if ( SymbolBinding[nSymbolBind] ) {
std::cout << SymbolBinding[nSymbolBind];
} else {
std::cout << nSymbolBind;
}
std::cout << ", Visibility: ";
if ( SymbolVisibility[nSymbolVisibility] ) {
std::cout << SymbolVisibility[nSymbolVisibility];
} else {
std::cout << nSymbolVisibility;
}
std::cout << "-> " << SymbolVisibility[STV_HIDDEN] << "\n";
}
// Toggle visibility to "hidden".
aSymbol.st_other = GELF_ST_VISIBILITY(STV_HIDDEN);
// Write back symbol data to underlying structure.
if ( gelf_update_sym(pSymbolData, nIndex, &aSymbol) == NULL )
{
throw ElfError(rFile, "gelf_update_sym() failed");
}
}
}
}
// Write changed object file to disk.
if ( elf_update(pElf, ELF_C_WRITE) == -1 ) {
throw ElfError(rFile, "elf_update() failed");
}
elf_end(pElf);
} catch (const ElfError& e) {
close(fd);
throw;
}
return;
}
void processObject(const std::string& rFile, bool bPreserve, bool bVerbose)
{
int fd;
struct stat aStatBuf;
if ((fd = open(rFile.c_str(), O_RDWR)) == -1) {
std::string sMessage("adjustVisibilty() failed: can't open file ");
sMessage += rFile;
sMessage += ": ";
sMessage += std::strerror(errno);
throw std::runtime_error(sMessage);
}
if ( bPreserve ) {
if ( fstat(fd, &aStatBuf) == -1) {
close(fd);
std::string sMessage("adjustVisibilty() failed: can't stat file ");
sMessage += rFile;
sMessage += ": ";
sMessage += std::strerror(errno);
throw std::runtime_error(sMessage);
}
}
adjustVisibility(rFile, fd, bVerbose);
close(fd);
if ( bPreserve ) {
struct utimbuf aUtimBuf = {aStatBuf.st_atime, aStatBuf.st_mtime};
if ( utime(rFile.c_str(), &aUtimBuf) == -1 ) {
std::string sMessage("adjustVisibilty() failed: can't reset timestamp ");
sMessage += rFile;
sMessage += ": ";
sMessage += std::strerror(errno);
throw std::runtime_error(sMessage);
}
}
return;
}
int main(int argc, char* argv[])
{
int c;
bool bPreserve = false;
bool bVerbose = false;
while ( (c = getopt(argc, argv, "pv")) != -1 ) {
switch(c) {
case 'p':
bPreserve = true;
break;
case 'v':
bVerbose = true;
break;
case '?':
std::cerr << "Unrecognized option: -" << optopt << "\n";
break;
default:
break;
}
}
if ( optind == argc ) {
std::cout << "usage: " << argv[0] << " [-pv] <elf-object> ...\n";
std::cout << " -p preserve time stamps\n";
std::cout << " -v verbose\n";
return 1;
}
try {
initElfLib();
for ( ; optind < argc; optind++ ) {
processObject(std::string(argv[optind]), bPreserve, bVerbose);
}
} catch (const std::exception& e) {
std::cerr << argv[0] << ": " << e.what() << "\n";
return 1;
}
return 0;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/* All Java Virtual Machine Specs are from
* "The Java Virtual Machine Specification", T. Lindholm, F. Yellin
* (JVMS)
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#if defined(UNX)
#include <unistd.h>
#include <netinet/in.h> /* ntohl(), ntohs() */
#elif defined(WNT)
#include <io.h>
#define access _access
#define vsnprintf _vsnprintf
#define CDECL _cdecl
#define F_OK 00
#define PATH_MAX _MAX_PATH
#define ntohl(x) ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#define ntohs(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
#endif
/* max. length of line in response file */
#define RES_FILE_BUF 65536
struct file {
char *pname;
FILE *pfs;
};
struct growable {
int ncur;
int nmax;
char **parray;
};
typedef struct file file_t;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
struct utf8 {
uint16 nlen;
void *pdata;
};
typedef struct utf8 utf8_t;
/* The contents of the Constant_pool is described in JVMS p. 93
*/
enum {
CONSTANT_Class = 7,
CONSTANT_Fieldref = 9,
CONSTANT_Methodref = 10,
CONSTANT_InterfaceMethodref = 11,
CONSTANT_String = 8,
CONSTANT_Integer = 3,
CONSTANT_Float = 4,
CONSTANT_Long = 5,
CONSTANT_Double = 6,
CONSTANT_NameAndType = 12,
CONSTANT_Utf8 = 1
};
enum { NGROW_INIT = 10, NGROW = 2 };
static char *pprogname = "javadep";
static char csep = ';';
#if defined (UNX)
#define CDECL
static char cpathsep = '/';
#elif defined (WNT)
static char cpathsep = '\\';
#endif
static FILE *pfsout = NULL;
static char *pout_file = NULL;
/* prototypes */
uint8 read_uint8(const file_t *pfile);
uint16 read_uint16(const file_t *pfile);
uint32 read_uint32(const file_t *pfile);
void skip_bytes(const file_t *pfile, const long nnum);
char *escape_slash(const char *pstr);
int is_inner(const char *pstr);
void print_dependencies(const struct growable *pdep,
const char* pclass_file);
void process_class_file(const char *pfilenamem,
const struct growable *pfilt);
char *utf8tolatin1(const utf8_t a_utf8);
void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size);
void *xrealloc(void *ptr, size_t size);
void grow_if_needed (struct growable *pgrow);
int append_to_growable(struct growable *, char *);
struct growable *allocate_growable(void);
void free_growable(struct growable *pgrowvoid);
void create_filters(struct growable *pfilt, const struct growable *pinc);
void usage(void);
void err_quit(const char *, ...);
void silent_quit(void);
#ifdef WNT
/* poor man's getopt() */
int simple_getopt(char *pargv[], const char *poptstring);
char *optarg = NULL;
int optind = 1;
int optopt = 0;
int opterr = 0;
#endif
uint8
read_uint8(const file_t *pfile)
{
/* read a byte from classfile */
size_t nread;
uint8 ndata;
nread = fread(&ndata, sizeof(uint8), 1, pfile->pfs);
if ( !nread ) {
fclose(pfile->pfs);
err_quit("%s: truncated class file", pfile->pname);
}
return ndata;
}
uint16
read_uint16(const file_t *pfile)
{
/* read a short from classfile and convert it to host format */
size_t nread;
uint16 ndata;
nread = fread(&ndata, sizeof(uint16), 1, pfile->pfs);
if ( !nread ) {
fclose(pfile->pfs);
err_quit("%s: truncated class file", pfile->pname);
}
ndata = ntohs(ndata);
return ndata;
}
uint32
read_uint32(const file_t *pfile)
{
/* read an int from classfile and convert it to host format */
size_t nread;
uint32 ndata;
nread = fread(&ndata, sizeof(uint32), 1, pfile->pfs);
if ( !nread ) {
fclose(pfile->pfs);
err_quit("%s: truncated class file", pfile->pname);
}
ndata = ntohl(ndata);
return ndata;
}
utf8_t
read_utf8(const file_t *pfile)
{
/* Read a java utf-8-string with uint16 length prependend
* from class file. Returns utf8 struct
* with fresh allocated datablock,
* caller is responsible for freeing.
* Data is still in network byteorder
*/
utf8_t a_utf8;
size_t nread;
a_utf8.pdata = NULL;
a_utf8.nlen = read_uint16(pfile);
if (a_utf8.nlen > 0) {
a_utf8.pdata = xmalloc(a_utf8.nlen*sizeof(char));
nread = fread(a_utf8.pdata, a_utf8.nlen*sizeof(char), 1, pfile->pfs);
if ( !nread ) {
fclose(pfile->pfs);
err_quit("%s: truncated class file", pfile->pname);
}
}
return a_utf8;
}
char *utf8tolatin1(const utf8_t a_utf8)
{
/* function returns fresh allocated zero terminated string,
* caller is responsible for freeing
*/
/* JVMS p. 101: the null byte is encoded using a two byte format,
* Java Virtual Machine Utf8 strings differ in this respect from
* standard UTF-8 strings
*/
/* Multibyte data is in network byte order */
char *p;
char *pp;
char *pstr;
pstr = pp = xmalloc((a_utf8.nlen+1) * sizeof(char));
for ( p = (char*)a_utf8.pdata;
p < (char*)a_utf8.pdata+a_utf8.nlen;
p++ ) {
if ( *p & 0x80 ) {
err_quit("sorry, real UTF8 decoding not yet implemented\n");
} else {
*pp++ = *p;
}
}
*pp = '\0';
return pstr;
}
void
skip_bytes(const file_t *pfile, const long nnumber)
{
/* skip a nnumber of bytes in classfile */
if ( fseek(pfile->pfs, nnumber, SEEK_CUR) == -1 )
err_quit("%s: %s", pfile->pname, strerror(errno));
}
void
add_to_dependencies(struct growable *pdep,
const struct growable *pfilt,
char *pdepstr,
const char *pclass_file)
{
/* create dependencies */
int i;
size_t nlen_filt, nlen_str, nlen_pdepstr;
char *pstr, *ptrunc;
char path[PATH_MAX+1];
char cnp_class_file[PATH_MAX+1];
char cnp_str[PATH_MAX+1];
nlen_pdepstr = strlen(pdepstr);
pstr = xmalloc((nlen_pdepstr+6+1)*sizeof(char));
memcpy(pstr, pdepstr, nlen_pdepstr+1);
strncat(pstr, ".class", 6);
if ( pfilt->ncur == 0 ) { /* no filters */
if ( access(pstr, F_OK) == 0 ) {
append_to_growable(pdep, strdup(pstr));
}
} else {
nlen_str = strlen(pstr);
for ( i = 0; i < pfilt->ncur; i++ ) {
nlen_filt = strlen(pfilt->parray[i]);
if ( nlen_filt + 1 + nlen_str > PATH_MAX )
err_quit("path to long");
memcpy(path, pfilt->parray[i], nlen_filt);
path[nlen_filt] = '/';
memcpy( path+nlen_filt+1, pstr, nlen_str+1);
if ( access(path, F_OK) != 0 ) {
free(pstr);
pstr = NULL;
return; /* path doesn't represent a real file, don't bother */
}
/* get the canonical path */
#if defined (UNX)
if ( !(realpath(pclass_file, cnp_class_file)
&& realpath(path, cnp_str) ) ) {
err_quit("can't get the canonical path");
}
#else
if ( !(_fullpath(cnp_class_file, pclass_file, sizeof(cnp_class_file))
&& _fullpath(cnp_str, path, sizeof(cnp_str)) ) ) {
err_quit("can't get the canonical path");
}
#endif
/* truncate so that only the package prefix remains */
ptrunc = strrchr(cnp_str, cpathsep);
*ptrunc = '\0';
ptrunc = strrchr(cnp_class_file, cpathsep);
*ptrunc = '\0';
if ( !strcmp(cnp_str, cnp_class_file) ) {
free(pstr);
pstr = NULL;
return; /* identical, don't bother with this one */
}
append_to_growable(pdep, strdup(path));
}
}
free(pstr);
return;
}
char *
escape_slash(const char *pstr)
{
/* returns a fresh allocated string with all cpathsep escaped exchanged
* with "$/"
*
* caller is responsible for freeing
*/
const char *pp = pstr;
char *p, *pnp;
char *pnew_str;
size_t nlen_pnp, nlen_pp;
int i = 0;
while ( (p=strchr(pp, cpathsep)) != NULL ) {
++i;
pp = ++p;
}
nlen_pnp = strlen(pstr) + i;
pnp = pnew_str = xmalloc((nlen_pnp+1) * sizeof(char));
pp = pstr;
if ( i > 0 ) {
while ( (p=strchr(pp, cpathsep)) != NULL ) {
memcpy(pnp, pp, p-pp);
pnp += p-pp;
*pnp++ = '$';
*pnp++ = '/';
pp = ++p;
}
}
nlen_pp = strlen(pp);
memcpy(pnp, pp, nlen_pp+1);
return pnew_str;
}
void
print_dependencies(const struct growable *pdep, const char* pclass_file)
{
char *pstr;
int i;
pstr = escape_slash(pclass_file);
fprintf(pfsout, "%s:", pstr);
free(pstr);
for( i=0; i<pdep->ncur; ++i) {
fprintf(pfsout, " \\\n");
pstr=escape_slash(pdep->parray[i]);
fprintf(pfsout, "\t%s", pstr);
free(pstr);
}
fprintf(pfsout,"\n\n");
return;
}
int
is_inner(const char *pstr)
{
/* return true if character '$' is found in classname */
/*
* note that a '$' in a classname is not an exact indicator
* for an inner class. Java identifier may legally contain
* this chararcter, and so may classnames. In the context
* of javadep this doesn't matter since the makefile system
* can't cope with classfiles with '$'s in the filename
* anyway.
*
*/
if ( strchr(pstr, '$') != NULL )
return 1;
return 0;
}
void
process_class_file(const char *pfilename, const struct growable *pfilt)
{
/* read class file and extract object information
* java class files are in bigendian data format
* (JVMS, p. 83)
*/
int i;
uint32 nmagic;
uint16 nminor, nmajor;
uint16 ncnt;
uint16 nclass_cnt;
utf8_t* pc_pool;
uint16* pc_class;
file_t file;
struct growable *pdepen;
file.pname = (char*)pfilename;
file.pfs = fopen(file.pname,"rb");
if ( !file.pfs )
silent_quit();
nmagic = read_uint32(&file);
if ( nmagic != 0xCAFEBABE ) {
fclose(file.pfs);
err_quit("%s: invalid magic", file.pname);
}
nminor = read_uint16(&file);
nmajor = read_uint16(&file);
/* get number of entries in constant pool */
ncnt = read_uint16(&file);
#ifdef DEBUG
printf("Magic: %x\n", nmagic);
printf("Major %d, Minor %d\n", nmajor, nminor);
printf("Const_pool_count %d\n", ncnt);
#else
(void)nmajor;
(void)nminor;
#endif
/* There can be ncount entries in the constant_pool table
* so at most ncount-1 of them can be of type CONSTANT_Class
* (at leat one CONSTANT_Utf8 entry must exist).
* Usually way less CONSTANT_Class entries exists, of course
*/
pc_pool = xcalloc(ncnt,sizeof(utf8_t));
pc_class = xmalloc((ncnt-1)*sizeof(uint16));
/* pc_pool[0] is reserved to the java virtual machine and does
* not exist in the class file
*/
nclass_cnt = 0;
for (i = 1; i < ncnt; i++) {
uint8 ntag;
uint16 nindex;
utf8_t a_utf8;
ntag = read_uint8(&file);
/* we are only interested in CONSTANT_Class entries and
* Utf8 string entries, because they might belong to
* CONSTANT_Class entries
*/
switch(ntag) {
case CONSTANT_Class:
nindex = read_uint16(&file);
pc_class[nclass_cnt++] = nindex;
break;
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
skip_bytes(&file, 4L);
break;
case CONSTANT_String:
skip_bytes(&file, 2L);
break;
case CONSTANT_Integer:
case CONSTANT_Float:
skip_bytes(&file, 4L);
break;
case CONSTANT_Long:
case CONSTANT_Double:
skip_bytes(&file, 8L);
/* Long and Doubles take 2(!)
* entries in constant_pool_table
*/
i++;
break;
case CONSTANT_NameAndType:
skip_bytes(&file, 4L);
break;
case CONSTANT_Utf8:
a_utf8 = read_utf8(&file);
pc_pool[i] = a_utf8;
break;
default:
/* Unknown Constant_pool entry, this means we are
* in trouble
*/
err_quit("corrupted class file\n");
break;
}
}
fclose(file.pfs);
pdepen = allocate_growable();
for (i = 0; i < nclass_cnt; i++) {
char *pstr, *ptmpstr;
pstr = ptmpstr = utf8tolatin1(pc_pool[pc_class[i]]);
/* we are not interested in inner classes */
if ( is_inner(pstr) ) {
free(pstr);
pstr = NULL;
continue;
}
/* strip off evt. array indicators */
if ( *ptmpstr == '[' ) {
while ( *ptmpstr == '[' )
ptmpstr++;
/* we only interested in obj. arrays, which are marked with 'L' */
if ( *ptmpstr == 'L' ) {
char *p = pstr;
pstr = strdup(++ptmpstr);
/* remove final ';' from object array name */
pstr[strlen(pstr)-1] = '\0';
free(p);
} else {
free(pstr);
pstr = NULL;
}
}
if (pstr) {
add_to_dependencies(pdepen, pfilt, pstr, file.pname);
free(pstr);
}
}
print_dependencies(pdepen, file.pname);
free_growable(pdepen);
pdepen = NULL;
for (i = 0; i < ncnt; i++)
free(pc_pool[i].pdata);
free(pc_class);
free(pc_pool);
}
void *
xmalloc(size_t size)
{
void *ptr;
ptr = malloc(size);
if ( !ptr )
err_quit("out of memory");
return ptr;
}
void *
xcalloc(size_t nmemb, size_t size)
{
void *ptr;
ptr = calloc(nmemb, size);
if ( !ptr )
err_quit("out of memory");
return ptr;
}
void *
xrealloc(void *ptr, size_t size)
{
void *newptr = realloc(ptr, size);
if (newptr)
ptr = newptr;
else
err_quit("out of memory");
return ptr;
}
void
err_quit(const char* fmt, ...)
{
/* No dependency file must be generated for any error condition,
* just print message and exit.
*/
va_list args;
char buffer[PATH_MAX];
va_start(args, fmt);
if ( pprogname )
fprintf(stderr, "%s: ", pprogname);
vsnprintf(buffer, sizeof(buffer), fmt, args);
fputs(buffer, stderr);
fputc('\n', stderr);
va_end(args);
/* clean up */
if ( pfsout && pfsout != stdout ) {
fclose(pfsout);
unlink(pout_file);
}
exit(1);
}
void
silent_quit()
{
/* In some cases we should just do a silent exit */
/* clean up */
if ( pfsout && pfsout != stdout ) {
fclose(pfsout);
unlink(pout_file);
}
exit(0);
}
int append_to_growable(struct growable *pgrow, char *pstr)
{
/* append an element pstr to pgrow,
* return new number of elements
*/
grow_if_needed(pgrow);
pgrow->parray[pgrow->ncur++] = pstr;
return pgrow->ncur;
}
void
grow_if_needed(struct growable *pgrow)
{
/* grow growable arrays */
if ( pgrow->ncur >= pgrow->nmax ) {
pgrow->parray = xrealloc(pgrow->parray,
(NGROW*pgrow->nmax)*sizeof(char*));
pgrow->nmax *= NGROW;
}
return;
}
struct growable *allocate_growable(void)
{
/* allocate an growable array,
* initialize with NGROW_INIT elements
*/
struct growable *pgrow;
pgrow = xmalloc(sizeof(struct growable));
pgrow->parray = xmalloc(NGROW_INIT*sizeof(char *));
pgrow->nmax = NGROW_INIT;
pgrow->ncur = 0;
return pgrow;
}
void
free_growable(struct growable *pgrow)
{
int i;
for( i = 0; i < pgrow->ncur; i++ )
free(pgrow->parray[i]);
free(pgrow->parray);
free(pgrow);
}
void
create_filters(struct growable *pfilt, const struct growable *pinc)
{
char *p, *pp, *pstr;
int i;
size_t nlen, nlen_pstr;
/* break up includes into filter list */
for ( i = 0; i < pinc->ncur; i++ ) {
pp = pinc->parray[i];
while ( (p = strchr(pp, csep)) != NULL) {
nlen = p - pp;
pstr = xmalloc((nlen+1)*sizeof(char*));
memcpy(pstr, pp, nlen);
pstr[nlen] = '\0';
append_to_growable(pfilt, pstr);
pp = p + 1;
}
nlen_pstr = strlen(pp);
pstr = xmalloc((nlen_pstr+1)*sizeof(char*));
memcpy(pstr, pp, nlen_pstr+1);
append_to_growable(pfilt, pstr);
}
}
void
usage()
{
fprintf(stderr,
"usage: %s [-i|-I includepath ... -s|-S seperator "
"-o|-O outpath -v|-V -h|-H] <file> ....\n",
pprogname);
}
#ifdef WNT
/* my very simple minded implementation of getopt()
* it's to sad that getopt() is not available everywhere
* note: this is not a full POSIX conforming getopt()
*/
int simple_getopt(char *pargv[], const char *poptstring)
{
char *parg = pargv[optind];
/* skip all response file arguments */
if ( parg ) {
while ( *parg == '@' )
parg = pargv[++optind];
if ( parg[0] == '-' && parg[1] != '\0' ) {
char *popt;
int c = parg[1];
if ( (popt = strchr(poptstring, c)) == NULL ) {
optopt = c;
if ( opterr )
fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
return '?';
}
if ( *(++popt) == ':') {
if ( parg[2] != '\0' ) {
optarg = ++parg;
} else {
optarg = pargv[++optind];
}
} else {
optarg = NULL;
}
++optind;
return c;
}
}
return -1;
}
#endif
int CDECL
main(int argc, char *argv[])
{
int bv_flag = 0;
struct growable *presp, *pincs, *pfilters;
int c, i, nall_argc;
char **pall_argv;
presp = allocate_growable();
/* FIXME: cleanup the option parsing */
/* search for response file, read it */
for ( i = 1; i < argc; i++ ) {
char *parg = argv[i];
char buffer[RES_FILE_BUF];
if ( *parg == '@' ) {
FILE *pfile = fopen(++parg, "r");
if ( !pfile )
err_quit("%s: %s", parg, strerror(errno));
while ( !feof(pfile) ) {
char *p, *token;
if ( fgets(buffer, RES_FILE_BUF, pfile) ) {;
p = buffer;
while ( (token = strtok(p, " \t\n")) != NULL ) {
p = NULL;
append_to_growable(presp, strdup(token));
}
}
}
fclose(pfile);
}
}
/* copy all arguments incl. response file in one array
* for parsing with getopt
*/
nall_argc = argc + presp->ncur;
pall_argv = xmalloc((nall_argc+1)*sizeof(char *));
memcpy(pall_argv, argv, argc*sizeof(char *));
memcpy(pall_argv+argc, presp->parray, presp->ncur*sizeof(char *));
*(pall_argv+argc+presp->ncur) = '\0'; /* terminate */
opterr = 0;
pincs = allocate_growable();
#ifdef WNT
while( (c = simple_getopt(pall_argv, ":i:I:s:S:o:OhHvV")) != -1 ) {
#else
while( (c = getopt(nall_argc, pall_argv, ":i:I:s:S:o:OhHvV")) != -1 ) {
#endif
switch(c) {
case 'i':
case 'I':
append_to_growable(pincs, strdup(optarg));
break;
case 's':
case 'S':
csep = optarg[0];
break;
case 'o':
case 'O':
pout_file = optarg;
break;
case 'h':
case 'H':
usage();
return 0;
break;
case 'v':
case 'V':
bv_flag = 1;
break;
case '?':
if (isprint (optopt))
fprintf (stderr,
"Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
usage();
return 1;
break;
case ':':
fprintf(stderr, "Missing parameter.\n");
usage();
return 1;
break;
default:
usage();
return 1;
break;
}
}
pfilters = allocate_growable();
create_filters(pfilters, pincs);
free_growable(pincs);
pincs = NULL;
if ( pout_file ) {
pfsout = fopen(pout_file, "w");
if ( !pfsout )
err_quit("%s: %s", pout_file, strerror(errno));
} else {
pfsout = stdout;
}
/* the remaining arguments are either class file
* names or response files, ignore response file
* since they have already been included
*/
for ( i = optind; i < nall_argc; i++ ) {
char *parg = pall_argv[i];
if ( *parg != '@' ) {
process_class_file(parg, pfilters);
if ( pfsout != stdout ) {
if ( bv_flag )
printf("Processed %s ...\n", parg);
}
}
}
free_growable(pfilters);
pfilters = NULL;
free(pall_argv);
pall_argv = NULL;
free_growable(presp);
presp = NULL;
fclose(pfsout);
exit(0);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "hashtbl.hxx"
#include <string.h>
// -------------------------------------------------------------
// class HashItem
//
class HashItem
{
enum ETag { TAG_EMPTY, TAG_USED, TAG_DELETED };
void* m_pObject;
ETag m_Tag;
char* m_Key;
public:
HashItem() { m_Tag = TAG_EMPTY; m_Key = NULL; m_pObject = NULL; }
~HashItem() { delete [] m_Key; }
bool IsDeleted() const
{ return m_Tag == TAG_DELETED; }
bool IsEmpty() const
{ return m_Tag == TAG_DELETED || m_Tag == TAG_EMPTY; }
bool IsFree() const
{ return m_Tag == TAG_EMPTY; }
bool IsUsed() const
{ return m_Tag == TAG_USED; }
void Delete()
{ m_Tag = TAG_DELETED; delete [] m_Key; m_Key = new char[ 1 ]; m_Key[ 0 ] = 0; m_pObject = NULL; }
const char *GetKey() const
{ return m_Key; }
void* GetObject() const
{ return m_pObject; }
void SetObject(const char * Key, void *pObject)
{ m_Tag = TAG_USED; delete [] m_Key; m_Key = new char[ strlen( Key ) + 1 ]; strcpy( m_Key, Key ); m_pObject = pObject; }
};
#define MIN(a,b) (a)<(b)?(a):(b)
#define MAX(a,b) (a)>(b)?(a):(b)
// -------------------------------------------------------------
// class HashTable
//
/*static*/ double HashTable::m_defMaxLoadFactor = 0.5;
/*static*/ double HashTable::m_defDefGrowFactor = 2.0;
HashTable::HashTable(unsigned long lSize, bool bOwner, double dMaxLoadFactor, double dGrowFactor)
{
m_lSize = lSize;
m_bOwner = bOwner;
m_lElem = 0;
m_dMaxLoadFactor = MAX(0.5,MIN(1.0,dMaxLoadFactor)); // 0.5 ... 1.0
m_dGrowFactor = MAX(2.0,MIN(5.0,dGrowFactor)); // 1.3 ... 5.0
m_pData = new HashItem [lSize];
}
HashTable::~HashTable()
{
// Wenn die HashTable der Owner der Objecte ist,
// mssen die Destruktoren separat gerufen werden.
// Dies geschieht ber die virtuelle Methode OnDeleteObject()
//
// Problem: Virtuelle Funktionen sind im Destructor nicht virtuell!!
// Der Code mu deshalb ins Macro
// Speicher fr HashItems freigeben
delete [] m_pData;
}
void* HashTable::GetObjectAt(unsigned long lPos) const
// Gibt Objekt zurck, wenn es eines gibt, sonst NULL;
{
HashItem *pItem = &m_pData[lPos];
return pItem->IsUsed() ? pItem->GetObject() : NULL;
}
void HashTable::OnDeleteObject(void*)
{
}
unsigned long HashTable::Hash(const char *Key) const
{
// Hashfunktion von P.J. Weinberger
// aus dem "Drachenbuch" von Aho/Sethi/Ullman
unsigned long i,n;
unsigned long h = 0;
unsigned long g = 0;
for (i=0,n=strlen( Key ); i<n; i++)
{
h = (h<<4) + (unsigned long)(unsigned short)Key[i];
g = h & 0xf0000000;
if (g != 0)
{
h = h ^ (g >> 24);
h = h ^ g;
}
}
return h % m_lSize;
}
unsigned long HashTable::DHash(const char* Key, unsigned long lOldHash) const
{
unsigned long lHash = lOldHash;
unsigned long i,n;
for (i=0,n=strlen( Key ); i<n; i++)
{
lHash *= 256L;
lHash += (unsigned long)(unsigned short)Key[i];
lHash %= m_lSize;
}
return lHash;
}
unsigned long HashTable::Probe(unsigned long lPos) const
// gibt den Folgewert von lPos zurck
{
lPos++; if (lPos==m_lSize) lPos=0;
return lPos;
}
bool HashTable::IsFull() const
{
return m_lElem>=m_lSize;
}
bool HashTable::Insert(const char * Key, void* pObject)
// pre: Key ist nicht im Dictionary enthalten, sonst return FALSE
// Dictionary ist nicht voll, sonst return FALSE
// post: pObject ist unter Key im Dictionary; m_nElem wurde erhht
{
SmartGrow();
if (IsFull())
{
return false;
}
if (FindPos(Key) != NULL )
return false;
unsigned long lPos = Hash(Key);
HashItem *pItem = &m_pData[lPos];
// first hashing
//
if (pItem->IsEmpty())
{
pItem->SetObject(Key, pObject);
m_lElem++;
return true;
}
// double hashing
//
lPos = DHash(Key,lPos);
pItem = &m_pData[lPos];
if (pItem->IsEmpty())
{
pItem->SetObject(Key, pObject);
m_lElem++;
return true;
}
// linear probing
//
do
{
lPos = Probe(lPos);
pItem = &m_pData[lPos];
}
while(!pItem->IsEmpty());
pItem->SetObject(Key, pObject);
m_lElem++;
return true;
}
HashItem* HashTable::FindPos(const char * Key) const
// sucht den Key; gibt Refrenz auf den Eintrag (gefunden)
// oder NULL (nicht gefunden) zurck
//
// pre: -
// post: -
{
// first hashing
//
unsigned long lPos = Hash(Key);
HashItem *pItem = &m_pData[lPos];
if (pItem->IsUsed()
&& !(strcmp( pItem->GetKey(), Key )))
{
return pItem;
}
// double hashing
//
if (pItem->IsDeleted() || pItem->IsUsed())
{
lPos = DHash(Key,lPos);
pItem = &m_pData[lPos];
if (pItem->IsUsed()
&& (!strcmp( pItem->GetKey(), Key)))
{
return pItem;
}
// linear probing
//
if (pItem->IsDeleted() || pItem->IsUsed())
{
unsigned long n = 0;
bool bFound = false;
bool bEnd = false;
do
{
n++;
lPos = Probe(lPos);
pItem = &m_pData[lPos];
bFound = pItem->IsUsed()
&& !( strcmp( pItem->GetKey(), Key ));
bEnd = !(n<m_lSize || pItem->IsFree());
}
while(!bFound && !bEnd);
return bFound ? pItem : NULL;
}
}
// nicht gefunden
//
return NULL;
}
void* HashTable::Find(const char *Key) const
// Gibt Verweis des Objektes zurck, das unter Key abgespeichert ist,
// oder NULL wenn nicht vorhanden.
//
// pre: -
// post: -
{
HashItem *pItem = FindPos(Key);
if (pItem != NULL
&& ( !strcmp( pItem->GetKey(), Key )))
return pItem->GetObject();
else
return NULL;
}
void* HashTable::Delete( const char * Key)
// Lscht Objekt, das unter Key abgespeichert ist und gibt Verweis
// darauf zurck.
// Gibt NULL zurck, wenn Key nicht vorhanden ist.
//
// pre: -
// post: Objekt ist nicht mehr enthalten; m_lElem dekrementiert
// Wenn die HashTable der Owner ist, wurde das Object gelscht
{
HashItem *pItem = FindPos(Key);
if (pItem != NULL
&& ( !strcmp( pItem->GetKey(), Key )))
{
void* pObject = pItem->GetObject();
if (m_bOwner)
OnDeleteObject(pObject);
pItem->Delete();
m_lElem--;
return pObject;
}
else
{
return NULL;
}
}
double HashTable::CalcLoadFactor() const
// prozentuale Belegung der Hashtabelle berechnen
{
return double(m_lElem) / double(m_lSize);
}
void HashTable::SmartGrow()
// Achtung: da die Objekte umkopiert werden, darf die OnDeleteObject-Methode
// nicht gerufen werden
{
double dLoadFactor = CalcLoadFactor();
if (dLoadFactor <= m_dMaxLoadFactor)
return; // nothing to grow
unsigned long lOldSize = m_lSize; // alte Daten sichern
HashItem* pOldData = m_pData;
m_lSize = (unsigned long) (m_dGrowFactor * m_lSize); // neue Gre
m_pData = new HashItem[m_lSize]; // neue Daten holen
// kein Speicher:
// Zustand "Tabelle voll" wird in Insert abgefangen
//
if (m_pData == NULL)
{
m_lSize = lOldSize;
m_pData = pOldData;
return;
}
m_lElem = 0; // noch keine neuen Daten
// Umkopieren der Daten
//
for (unsigned long i=0; i<lOldSize; i++)
{
HashItem *pItem = &pOldData[i];
if (pItem->IsUsed())
Insert(pItem->GetKey(),pItem->GetObject());
}
delete [] pOldData;
}
// Iterator ---------------------------------------------------------
//
HashTableIterator::HashTableIterator(HashTable const& aTable)
: m_aTable(aTable)
{
m_lAt = 0;
}
void* HashTableIterator::GetFirst()
{
m_lAt = 0;
return FindValidObject(true /* forward */);
}
void* HashTableIterator::GetLast()
{
m_lAt = m_aTable.GetSize() -1;
return FindValidObject(false /* backward */);
}
void* HashTableIterator::GetNext()
{
if (m_lAt+1 >= m_aTable.GetSize())
return NULL;
m_lAt++;
return FindValidObject(true /* forward */);
}
void* HashTableIterator::GetPrev()
{
if (m_lAt)
{
--m_lAt;
return FindValidObject(false /* backward */);
}
return NULL;
}
void* HashTableIterator::FindValidObject(bool bForward)
// Sucht nach einem vorhandenen Objekt ab der aktuellen
// Position.
//
// pre: ab inkl. m_lAt soll die Suche beginnen
// post: if not found then
// if bForward == TRUE then
// m_lAt == m_aTable.GetSize() -1
// else
// m_lAt == 0
// else
// m_lAt ist die gefundene Position
{
void *pObject = m_aTable.GetObjectAt(m_lAt);
if (pObject != NULL)
return pObject;
while (pObject == NULL
&& (bForward ? ((m_lAt+1) < m_aTable.GetSize())
: m_lAt > 0))
{
if (bForward)
m_lAt++;
else
m_lAt--;
pObject = m_aTable.GetObjectAt(m_lAt);
}
return pObject;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef _HASHTBL_HXX
#define _HASHTBL_HXX
// ADT hash table
//
// Invariante:
// 1. m_lElem < m_lSize
// 2. die Elemente in m_Array wurden double-hashed erzeugt
//
class HashItem;
class HashTable
{
unsigned long m_lSize;
unsigned long m_lElem;
HashItem *m_pData;
double m_dMaxLoadFactor;
double m_dGrowFactor;
bool m_bOwner;
unsigned long Hash(const char *cKey) const;
unsigned long DHash(const char *cKey , unsigned long lHash) const;
unsigned long Probe(unsigned long lPos) const;
HashItem* FindPos(const char *cKey) const;
void SmartGrow();
double CalcLoadFactor() const;
protected:
friend class HashTableIterator;
virtual void OnDeleteObject(void* pObject);
void* GetObjectAt(unsigned long lPos) const;
// Default-Werte
public:
static double m_defMaxLoadFactor;
static double m_defDefGrowFactor;
public:
HashTable
(
unsigned long lSize,
bool bOwner,
double dMaxLoadFactor = HashTable::m_defMaxLoadFactor /* 0.8 */,
double dGrowFactor = HashTable::m_defDefGrowFactor /* 2.0 */
);
virtual ~HashTable();
bool IsFull() const;
unsigned long GetSize() const { return m_lSize; }
void* Find (const char *cKey ) const;
bool Insert (const char *cKey , void* pObject);
void* Delete (const char *cKey);
};
// ADT hash table iterator
//
// Invariante: 0 <= m_lAt < m_aTable.GetCount()
//
class HashTableIterator
{
unsigned long m_lAt;
HashTable const& m_aTable;
void operator =(HashTableIterator &); // not defined
void* FindValidObject(bool bForward);
protected:
void* GetFirst(); // Interation _ohne_ Sortierung
void* GetNext();
void* GetLast();
void* GetPrev();
public:
HashTableIterator(HashTable const&);
};
#endif // _HASHTBL_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <string.h>
#include <direct.h>
#include <stdio.h>
#include <stdlib.h>
#include "ldump.hxx"
#include "hashtbl.hxx"
#define MAXSYM 65536
#define MAXBASE 98304
#define MAX_MAN 4096
int bFilter = 0;
int bLdump3 = 0;
int bUseDirectives = 0;
int bVerbose = 0;
int bExportByName = 0;
class ExportSet : public HashTable
{
public:
ExportSet
(
unsigned long lSize,
double dMaxLoadFactor = HashTable::m_defMaxLoadFactor,
double dGrowFactor = HashTable::m_defDefGrowFactor
)
: HashTable(lSize,false,dMaxLoadFactor,dGrowFactor) {}
virtual ~ExportSet() {}
LibExport * Find (char * const& Key) const
{ return (LibExport *) HashTable::Find((char *) Key); }
bool Insert (char * const& Key, LibExport * Object)
{ return HashTable::Insert((char *) Key, (void*) Object); }
LibExport * Delete (char * const&Key)
{ return (LibExport *) HashTable::Delete ((char *) Key); }
};
LibDump::LibDump( char *cFileName, int bExportByName )
: cBName( NULL ),
cAPrefix( NULL ),
cLibName( NULL ),
cFilterName( NULL ),
cModName( NULL )
{
fprintf( stderr, "LIB-NT File Dumper v4.00 (C) 2000 Sun Microsystems, Inc.\n\n" );
fprintf( stderr, "%s ", cFileName );
bExportName = bExportByName;
unsigned long nSlots = 0xfffff;
pBaseTab = new ExportSet( nSlots );
pIndexTab = new ExportSet( nSlots );
pFilterLines = new char * [MAXFILT];
CheckLibrary(cFileName);
bBase = 0;
bAll = false;
nDefStart = 0;
nBaseLines = 0;
nFilterLines = 0;
bDef = true;
cAPrefix = new char[ 1 ];
cAPrefix[ 0 ] = 0;
if (!bExportName)
CheckDataBase();
}
bool LibDump::Dump()
{
FILE *pList;
char aBuf[MAX_MAN];
int nLen;
char aName[MAX_MAN];
pList = fopen( cLibName, "rb");
if (!pList)
DumpError(10);
// forget about offset when working on linker directives
if ( !bUseDirectives )
{
// calculating offset for name section
unsigned char TmpBuffer[4];
fread( TmpBuffer, 1, 4, pList);
// anzahl bigendian mal laenge + ueberspringen der naechsten laengenangabe
unsigned long nOffSet = (unsigned long) ( TmpBuffer[2] * 256 + TmpBuffer[3] ) * 4 + 4;
fseek( pList, (long) nOffSet, 0);
}
char aTmpBuf[4096];
// reading file containing symbols
while( !feof( pList ) )
{
int i = 0;
if ( !bUseDirectives )
{
// symbol komplett einlesen
for (;;)
{
int c = fgetc( pList );
if ( c == '\0' )
{
break;
}
if ( ((c >= 33) && (c <= 126)) && ( c!=40 && c!=41) )
aBuf[i] = static_cast< char >(c);
else
{
aBuf[0] = '\0';
break;
}
i++;
}
// Namen found
aBuf[i] = '\0';
}
else
{
fgets( aTmpBuf, 4096, pList );
char * pEnd = 0;
char *pFound = 0;
aBuf[0] = '\0';
pFound = strchr( aTmpBuf, 'E' );
while ( pFound )
{
if ( strncmp( "EXPORT:", pFound, 7) == 0 )
{
pFound += 7;
pEnd = strchr( pFound, ',');
if ( pEnd )
*pEnd = '\0';
strncpy( aBuf, pFound, strlen( pFound));
aBuf[ strlen( pFound) ] = '\0';
break;
}
else
{
pFound++;
pFound = strchr( pFound, 'E' );
}
}
}
if (aBuf[0] =='?')
{
nLen = (int) strlen(aBuf);
memset( aName, 0, sizeof( aName ) );
int nName = 0;
for( i = 0; i < nLen; i++ )
{
if ( (aBuf[i] != '\n') && (aBuf[i] != '\r') )
{
aName[nName] = aBuf[i];
nName++;
}
}
// und raus damit
PrintSym( aName, bExportByName );
}
else if ( bAll == true &&
strncmp(aBuf, "__real@", 7) != 0 &&
strncmp(aBuf, "__CT",4) != 0 &&
strncmp(aBuf, "__TI3?", 6) != 0 )
{
int nPreLen = (int) strlen( cAPrefix );
nLen = (int) strlen(aBuf);
memset( aName, 0, sizeof( aName ) );
int nName = 0;
for( i = 0; i < nLen; i++ )
{
if ( (aBuf[i] != '\n') && (aBuf[i] != '\r') )
{
aName[nName] = aBuf[i];
nName++;
}
}
// den ersten _ raus
nLen = (int) strlen(aName);
#ifndef _WIN64
if (aName[0] == '_')
strcpy( aBuf , &aName[1] );
#endif
strncpy ( aTmpBuf, aBuf, (size_t) nPreLen );
aTmpBuf[nPreLen] = '\0';
if ( !strcmp( aTmpBuf, cAPrefix ))
{
if ( bLdump3 ) {
int nChar = '@';
char *pNeu = strchr( aBuf, nChar );
size_t nPos = pNeu - aBuf + 1;
if ( nPos > 0 )
{
char aOldBuf[MAX_MAN];
strcpy( aOldBuf, aBuf );
char pChar[MAX_MAN];
strncpy( pChar, aBuf, nPos - 1 );
pChar[nPos-1] = '\0';
strcpy( aBuf, pChar );
strcat( aBuf, "=" );
strcat( aBuf, aOldBuf );
strcpy( pChar, "" );
}
}
// und raus damit
PrintSym( aBuf, true );
}
}
}
fclose(pList);
return true;
}
bool LibDump::ReadFilter( char * cFilterName )
{
FILE* pfFilter = 0;
char aBuf[MAX_MAN];
char* pStr;
int nLen;
pfFilter = fopen( cFilterName, "r" );
if ( !pfFilter )
{
::bFilter = 0;
DumpError( 500 );
}
while( fgets( aBuf, MAX_MAN, pfFilter ) != 0 )
{
nLen = (int) strlen(aBuf);
pStr = new char[(unsigned int) nLen];
if ( !pStr )
DumpError( 98 );
memcpy( pStr, aBuf, (unsigned int) nLen );
if ( *(pStr+nLen-1) == '\n' )
*(pStr+nLen-1) = '\0';
pFilterLines[nFilterLines] = pStr;
nFilterLines++;
if ( nFilterLines >= MAXFILT )
DumpError( 510 );
}
fclose( pfFilter );
return true;
}
bool LibDump::PrintSym(char *pName, bool bName )
{
LibExport *pData;
// Filter auswerten
if ( Filter( pName ) )
{
if ( strlen( pName ) > 3 )
{
if ( bDef )
{
if (!bBase)
if (bExportName) {
fprintf( stdout, "\t%s\n", pName );
} else {
fprintf( stdout, "\t%s\t\t@%lu\n", pName, nDefStart );
}
else
{
pData = pBaseTab->Find( pName );
if ( pData )
{
pData->bExport = true;
if ( bName )
pData->bByName = true;
else
pData->bByName = false;
if ( bVerbose )
fprintf(stderr,".");
}
else
{
// neuen Export eintragen
pData = new LibExport;
pData->cExportName = new char[ strlen( pName ) + 1 ];
strcpy( pData->cExportName, pName );
pData->nOrdinal = nBaseLines++;
pData->bExport = true;
if ( bName )
pData->bByName = true;
else
pData->bByName = false;
pBaseTab->Insert( pData->cExportName, pData );
char *cBuffer = new char[ 30 ];
sprintf( cBuffer, "%lu", pData->nOrdinal );
pIndexTab->Insert( cBuffer, pData );
delete [] cBuffer;
if ( bVerbose )
fprintf(stderr,"n");
}
}
}
else
printf( "%s\n", pName );
nDefStart++;
}
}
return true;
}
bool LibDump::IsFromAnonymousNamespace (char *pExportName) {
char* pattern1 = "@?A0x";
if (strstr(pExportName, pattern1)) {
return true;
};
return false;
};
bool LibDump::Filter(char *pExportName)
{
unsigned long i;
char pTest[256];
// filter out symbols from anonymous namespaces
if (IsFromAnonymousNamespace (pExportName))
return false;
// Kein Filter gesetzt
if ( ::bFilter == 0 )
return true;
for ( i=0; i<nFilterLines; i++ )
{
//Zum vergleichen mu das Plus abgeschnitteb werden
if(pFilterLines[i][0] != '+')
{
if ( strstr( pExportName, pFilterLines[i]))
return false;
}
else
{
strcpy(pTest,&pFilterLines[i][1]);
if ( strstr( pExportName, pTest))
return true;
}
}
return true;
}
bool LibDump::SetFilter(char * cFilterName)
{
ReadFilter( cFilterName );
return true;
}
bool LibDump::CheckLibrary(char * cName)
{
delete [] cLibName;
cLibName = new char[ strlen( cName ) + 1 ];
strcpy( cLibName, cName );
return true;
}
bool LibDump::ReadDataBase()
{
FILE* pfBase = 0;
char aBuf[MAX_MAN];
char* pStr;
char cBuffer[ 30 ];
int nLen;
LibExport *pData;
pfBase = fopen( cBName, "r" );
if ( !pfBase )
{
bBase = 0;
DumpError( 600 );
}
bool bRet = true;
while( fgets( aBuf, MAX_MAN, pfBase ) != 0 )
{
nLen = (int) strlen(aBuf);
pStr = new char[(unsigned int) nLen];
if ( !pStr )
DumpError( 98 );
memcpy( pStr, aBuf, (size_t) nLen );
if ( *(pStr+nLen-1) == '\n' )
*(pStr+nLen-1) = '\0';
pData = new LibExport;
pData->cExportName = pStr;
pData->nOrdinal = nBaseLines;
pData->bExport=false;
if (pBaseTab->Insert(pData->cExportName, pData ) == NULL)
bRet = false;
ltoa( (long) pData->nOrdinal, cBuffer, 10 );
if (pIndexTab->Insert( cBuffer, pData ) == NULL)
bRet = false;
nBaseLines++;
if ( nBaseLines >= MAXBASE )
DumpError( 610 );
}
fclose( pfBase );
return bRet;
}
class ExportSetIter : public HashTableIterator
{
public:
ExportSetIter(HashTable const& aTable)
: HashTableIterator(aTable) {}
LibExport * GetFirst()
{ return (LibExport *)HashTableIterator::GetFirst(); }
LibExport * GetNext()
{ return (LibExport *)HashTableIterator::GetNext(); }
LibExport * GetLast()
{ return (LibExport *)HashTableIterator::GetLast(); }
LibExport * GetPrev()
{ return (LibExport *)HashTableIterator::GetPrev(); }
private:
void operator =(ExportSetIter &); // not defined
};
bool LibDump::PrintDataBase()
{
if (bExportName)
return true;
FILE *pFp;
pFp = fopen (cBName,"w+");
if (!pFp)
fprintf( stderr, "Error opening DataBase File\n" );
LibExport *pData;
for ( unsigned long i=0; i < nBaseLines+10; i++ )
{
char * cBuffer = new char[ 30 ];
sprintf( cBuffer, "%lu", i );
pData = pIndexTab->Find( cBuffer );
delete [] cBuffer;
if ( pData )
fprintf(pFp,"%s\n",pData->cExportName);
}
fclose(pFp);
return true;
}
bool LibDump::PrintDefFile()
{
#ifdef FAST
ExportSetIter aIterator( *pBaseTab );
for ( LibExport *pData = aIterator.GetFirst(); pData != NULL;
pData = aIterator.GetNext() )
{
if ( pData->bExport )
{
if ( pData->bByName )
{
fprintf(stdout,"\t%s\n",
pData->sExportName.GetBuffer());
}
else
{
fprintf(stdout,"\t%s\t\t@%d NONAME\n",
pData->sExportName.GetBuffer(), pData->nOrdinal+nBegin);
}
}
}
#else
// sortiert nach Ordinals;
LibExport *pData;
for ( unsigned long i=0; i<nBaseLines+1; i++)
{
char * cBuffer = new char[ 30 ];
sprintf( cBuffer, "%lu", i );
pData = pIndexTab->Find( cBuffer );
delete [] cBuffer;
if ( pData )
if ( pData->bExport )
{
if ( pData->bByName )
{
if ( strlen( pData->cExportName ))
fprintf(stdout,"\t%s\n",
pData->cExportName);
}
else
{
if ( strlen( pData->cExportName ))
fprintf(stdout,"\t%s\t\t@%d NONAME\n",
pData->cExportName, pData->nOrdinal+nBegin);
}
}
}
#endif
return true;
}
bool LibDump::CheckDataBase()
{
// existiert eine Datenbasis ?
if (!bBase)
{
cBName = new char[ 2048 ];
char *pTmp = "defs\\";
FILE *fp;
_mkdir ("defs");
strcpy(cBName,pTmp);
strcat(cBName,getenv ("COMP_ENV"));
fp = fopen (cBName,"r");
if (fp)
{
bBase = true;
}
else
{
fp = fopen (cBName,"w+");
bBase = true;
}
fclose (fp);
}
// lese Datenbasis !
if (bBase)
{
ReadDataBase();
}
return true;
}
LibDump::~LibDump()
{
delete [] cBName;
delete [] cAPrefix;
delete [] cFilterName;
delete [] cModName;
}
void LibDump::SetCExport( char* pName )
{
delete [] cAPrefix;
cAPrefix = new char[ strlen( pName ) + 1 ];
strcpy( cAPrefix, pName );bAll = true;
}
//******************************************************************
//* Error() - Gibt Fehlermeldumg aus
//******************************************************************
void LibDump::DumpError( unsigned long n )
{
char *p;
switch (n)
{
case 1: p = "Input error in library file"; break;
case 2: p = "Position error in library file (no THEADR set)"; break;
case 3: p = "Overflow of symbol table"; break;
#ifdef WNT
case 10: p = "EXP file not found"; break;
case 11: p = "No valid EXP file"; break;
#else
case 10: p = "Library file not found"; break;
case 11: p = "No valid library file"; break;
#endif
case 98: p = "Out of memory"; break;
case 99: p = "LDUMP [-LD3] [-D] [-N] [-A] [-E nn] [-F name] Filename[.LIB]\n"
"-LD3 : Supports feature set of ldump3 (default: ldump/ldump2)\n"
"-A : all symbols (default: only C++)\n"
"-E nn : gerenration of export table beginning with number nn\n"
"-F name: Filter file\n"
"-D : file contains \"dumpbin\" directives\n"
"-N : export by name\n"
"-V : be verbose\n"; break;
case 500: p = "Unable to open filter file\n"; break;
case 510: p = "Overflow of filter table\n"; break;
case 600: p = "Unable to open base database file\n"; break;
case 610: p = "Overflow in base database table\n"; break;
default: p = "Unspecified error";
}
fprintf( stdout, "%s\n", p );
exit (1);
}
/*********************************************************************
Test Funktionen
*********************************************************************/
void usage()
{
LibDump::DumpError(99);
}
#define STATE_NON 0x0000
#define STATE_BEGIN 0x0001
#define STATE_FILTER 0x0002
#define STATE_CEXPORT 0x0003
int
#ifdef WNT
__cdecl
#endif
main( int argc, char **argv )
{
char *pLibName = NULL, *pFilterName = NULL, *pCExport= NULL;
unsigned short nBegin=1;
unsigned short nState = STATE_NON;
if ( argc == 1 ) {
usage();
}
for ( int i = 1; i < argc; i++ ) {
if (( !strcmp( argv[ i ], "-H" )) ||
( !strcmp( argv[ i ], "-h" )) ||
( !strcmp( argv[ i ], "-?" )))
{
usage();
}
else if (( !strcmp( argv[ i ], "-LD3" )) ||
( !strcmp( argv[ i ], "-Ld3" )) ||
( !strcmp( argv[ i ], "-ld3" )) ||
( !strcmp( argv[ i ], "-lD3" )))
{
if ( nState != STATE_NON ) {
usage();
}
bLdump3 = 1;
}
else if (( !strcmp( argv[ i ], "-E" )) || ( !strcmp( argv[ i ], "-e" ))) {
if ( nState != STATE_NON ) {
usage();
}
nState = STATE_BEGIN;
}
else if (( !strcmp( argv[ i ], "-F" )) || ( !strcmp( argv[ i ], "-f" ))) {
if ( nState != STATE_NON ) {
usage();
}
nState = STATE_FILTER;
}
else if (( !strcmp( argv[ i ], "-A" )) || ( !strcmp( argv[ i ], "-a" ))) {
if ( nState != STATE_NON ) {
usage();
}
nState = STATE_CEXPORT;
pCExport = new char[ 1 ];
pCExport[ 0 ] = 0;
}
else if (( !strcmp( argv[ i ], "-D" )) || ( !strcmp( argv[ i ], "-d" ))) {
if ( nState != STATE_NON ) {
usage();
}
bUseDirectives = 1;
}
else if (( !strcmp( argv[ i ], "-N" )) || ( !strcmp( argv[ i ], "-n" ))) {
if ( nState != STATE_NON ) {
usage();
}
bExportByName = 1;
}
else if (( !strcmp( argv[ i ], "-V" )) || ( !strcmp( argv[ i ], "-v" ))) {
if ( nState != STATE_NON ) {
usage();
}
bVerbose = 1;
}
else {
switch ( nState ) {
case STATE_BEGIN:
nBegin = static_cast< unsigned short >(atoi( argv[ i ] ));
nState = STATE_NON;
break;
case STATE_FILTER:
pFilterName = new char[ strlen( argv[ i ] ) + 1 ];
strcpy( pFilterName, argv[ i ] );
bFilter = 1;
nState = STATE_NON;
break;
case STATE_CEXPORT:
delete [] pCExport;
pCExport = new char[ strlen( argv[ i ] ) + 1 ];
strcpy( pCExport, argv[ i ] );
nState = STATE_NON;
break;
default:
pLibName = new char[ strlen( argv[ i ] ) + 1 ];
strcpy( pLibName, argv[ i ] );
break;
}
}
}
if ( !pLibName ) {
usage();
}
LibDump *pDump = new LibDump( pLibName, bExportByName );
pDump->SetBeginExport(nBegin);
if ( bFilter != 0 )
pDump->SetFilter( pFilterName );
if ( pCExport )
pDump->SetCExport( pCExport );
else {
char *pEmpty = "";
pDump->SetCExport( pEmpty );
}
pDump->Dump();
pDump->PrintDefFile();
pDump->PrintDataBase();
delete pDump;
delete [] pLibName;
return 0;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include "hashtbl.hxx"
#define MAXFILT 200
struct LibExport
{
char *cExportName; // zu exportierende Fkt.
unsigned long nOrdinal; // Nummer der zu export. Fkt.
bool bByName; // NONAME anhaengen
bool bExport; // exportieren oder nicht ?
};
class ExportSet;
class LibDump
{
ExportSet *pBaseTab; // Zugriff auf gemangelte Namen
ExportSet *pIndexTab; // Zugriff auf die Ordinals
char *cBName; // Name der Datenbasis
char *cAPrefix; // Prefix fuer C-Fkts.
char *cLibName; // Name der zu untersuchenden Lib
char *cFilterName; // Name der Filterdatei
char *cModName; // Modulname
unsigned short nBegin; // Nummer des ersten Exports
unsigned long nBaseLines; // Line in Datenbasis
unsigned long nFilterLines; // Line in FilterTabelle
char **pFilterLines; // Filtertabelle
unsigned long nDefStart;
bool bBase; // Existenz der DatenBasis;
bool bAll; // Alle Fkts exportieren
bool bDef; // DefFile schreiben ( bei -E )
int bExportName; // 0 - export by ordinal; 1 - export by name
bool CheckDataBase();
bool CheckLibrary(char * cName);
bool ReadDataBase();
bool ReadFilter(char *);
bool PrintSym(char *, bool bName = true );
public:
LibDump( char *cFileName, int bExportByName );
~LibDump();
bool Dump();
bool SetFilter(char *cFilterName);
void SetBeginExport(unsigned short nVal){nBegin = nVal;}
void SetCExport( char* pName );
bool Filter(char *pName);
bool IsFromAnonymousNamespace(char *pName);
bool PrintDefFile();
bool PrintDataBase();
static void DumpError(unsigned long nError);
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment