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.
piklab/src/coff/base/coff_archive.cpp

130 lines
4.2 KiB

/***************************************************************************
* Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "coff_archive.h"
//----------------------------------------------------------------------------
Coff::Member::Member(const TQByteArray &data, uint &offset, Log::Base &log)
{
// parse header
TQString s;
if ( !getString(data, offset, 256, log, s) ) return;
int i = s.find('/');
if ( i==-1 ) {
log.log(Log::LineType::Error, i18n("Member name not terminated by '/' (\"%1\").").tqarg(s));
return;
}
_name = s.mid(0, i);
if ( !getString(data, offset, 12, log, s) ) return; // mtime
if ( !getString(data, offset, 10, log, s) ) return;
i = s.find('l');
if ( i==-1 ) {
log.log(Log::LineType::Error, i18n("File size not terminated by 'l' (\"%1\").").tqarg(s));
return;
}
bool ok;
_nbBytes = s.mid(0, i).toUInt(&ok);
if ( !ok ) {
log.log(Log::LineType::Error, i18n("Wrong format for file size \"%1\".").tqarg(s));
return;
}
TQ_UINT32 v;
if ( !getULong(data, offset, 2, log, v) ) return;
log.log(Log::DebugLevel::Extra, i18n("Magic number: %1").tqarg(toHexLabel(v, 4)));
// if ( v!=0x600A ) {
// log.log(Log::LineType::Error, i18n("Wrong magic for Microchip archive (\"%1\").").tqarg(toHexLabel(v, 4)));
// return;
// }
offset += _nbBytes;
}
//----------------------------------------------------------------------------
Coff::Archive::Archive(const PURL::Url &url)
: Base(url)
{}
bool Coff::Archive::parse(Log::Base &log)
{
TQByteArray data;
uint offset = 0, symbolEnd = 0;
Member *symbol = 0;
if ( !initParse(CoffType::Archive, data, offset, log) ) return false;
for (;;) {
if ( offset==uint(data.count()) ) break; // end of archive
uint start = offset;
Member *member = new Member(data, offset, log);
if ( log.hasError() ) return false;
if ( member->name().isEmpty() ) {
symbolEnd = offset;
symbol = member;
} else {
_members[member->name()] = member;
_offsets[start] = member;
}
}
if (symbol) {
if ( !readSymbols(data, symbolEnd - symbol->nbBytes(), log) ) return false;
delete symbol;
}
return true;
}
Coff::Archive::~Archive()
{
TQMap<TQString, Member *>::const_iterator it;
for (it=_members.begin(); it!=_members.end(); ++it) delete it.data();
}
bool Coff::Archive::readSymbols(const TQByteArray &data, uint offset, Log::Base &log)
{
TQ_UINT32 nb;
if ( !getULong(data, offset, 4, log, nb) ) return false;
TQValueVector<Member *> members(nb);
for (uint i=0; i<nb; i++) {
TQ_UINT32 start;
if ( !getULong(data, offset, 4, log, start) ) return false;
if ( !_offsets.contains(start) ) {
log.log(Log::LineType::Error, i18n("Unknown file member offset: %1").tqarg(toHexLabel(start, 8)));
return false;
}
members[i] = _offsets[start];
}
for (uint i=0; i<nb; i++) {
TQString name(data.data() + offset);
offset += name.length() + 1;
_symbols[name] = members[i];
}
return true;
}
Log::KeyList Coff::Archive::information() const
{
Log::KeyList keys(i18n("Information:"));
keys.append(i18n("No. of file members:"), TQString::number(members().count()));
keys.append(i18n("No. of symbols:"), TQString::number(symbols().count()));
return keys;
}
Log::KeyList Coff::Archive::membersInformation() const
{
Log::KeyList keys(i18n("File Members:"));
TQMap<TQString, Member *>::const_iterator it;
for (it=members().begin(); it!=members().end(); ++it)
keys.append(it.key(), i18n("size: %1 bytes").tqarg(it.data()->nbBytes()));
return keys;
}
Log::KeyList Coff::Archive::symbolsInformation() const
{
Log::KeyList keys(i18n("Symbols:"));
TQMap<TQString, Member *>::const_iterator it;
for (it=symbols().begin(); it!=symbols().end(); ++it)
keys.append(it.key(), it.data()->name());
return keys;
}