/*************************************************************************** * Copyright (C) 2007 Nicolas Hadacek * * * * 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 "main.h" #include "common/global/pfile.h" #include "common/cli/cli_log.h" #include "devices/list/device_list.h" #include "devices/base/device_group.h" #include "common/global/about.h" #include "coff/base/text_coff.h" #include "coff/base/coff_archive.h" //----------------------------------------------------------------------------- const KCmdLineOptions OPTIONS[] = { KCmdLineLastOption }; const CLI::CommandData CLI::NORMAL_COMMAND_DATA[] = { { "info", NeedSource, I18N_NOOP("Return general informations.") }, { "variables", NeedSource, I18N_NOOP("Return informations about variables (for object).") }, { "symbols", NeedSource, I18N_NOOP("Return informations about symbols.") }, { "sections", NeedSource, I18N_NOOP("Return informations about sections (for object).") }, { "lines", NeedSource, I18N_NOOP("Return informations about code lines (for object).") }, { "files", NeedSource, I18N_NOOP("Return informations about files.") }, { 0, NoCommandProperty, 0 } }; const CLI::CommandData CLI::INTERACTIVE_COMMAND_DATA[] = { { 0, NoCommandProperty, 0 } }; const CLI::PropertyData CLI::PROPERTY_DATA[] = { { "device", "device ", "d", I18N_NOOP("Target device."), "device-list", I18N_NOOP("Return the list of supported devices.") }, { 0, 0, 0, 0, 0, 0 } }; const KCmdLineOptions CLI::OPTIONS[] = { KCmdLineLastOption }; //----------------------------------------------------------------------------- CLI::Main::Main() : MainBase(HasForce), _device(0) {} CLI::Main::~Main() {} CLI::ExitCode CLI::Main::prepareCommand(const QString &command) { const CommandData *data = findCommandData(command); CommandProperties properties = static_cast(data->properties); int nbArgs = 0; if ( properties & NeedSource ) nbArgs++; if ( properties & NeedDestination ) nbArgs++; if ( _args->count()count()>nbArgs ) return errorExit(i18n("Too many arguments."), ARG_ERROR); uint argIndex = 0; if ( properties & NeedSource ) { _source = PURL::Url(_args->url(argIndex)); argIndex++; PURL::File file(_source, *_view); if ( !file.openForRead() ) return FILE_ERROR; } if ( properties & NeedDestination ) { _dest = PURL::Url(_args->url(argIndex)); argIndex++; if ( !_force && _dest.exists() ) return errorExit(i18n("Destination file already exists."), FILE_ERROR); } if ( _device==0 && (properties & NeedDevice) ) return errorExit(i18n("Device not specified."), ARG_ERROR); return OK; } QString CLI::Main::prettyAuxSymbol(const Coff::AuxSymbol &aux) { QString s = (aux.type()==Coff::AuxSymbolType::Nb_Types ? "?" : aux.type().label()); switch (aux.type().type()) { case Coff::AuxSymbolType::Direct: break; case Coff::AuxSymbolType::File: s += "=" + static_cast(aux).filename(); break; case Coff::AuxSymbolType::Identifier: s += "=" + static_cast(aux).string(); break; case Coff::AuxSymbolType::Section: break; case Coff::AuxSymbolType::Nb_Types: break; } return s; } QString CLI::Main::prettySymbol(const Coff::Symbol &sym) { QStringList saux; for (uint i=0; igroup().name()=="pic" ); const Pic::Data *pdata = static_cast(coff.device()); uint nbCharsAddress = (pdata ? pdata->nbCharsAddress() : 8); if ( command=="info" ) { keys = coff.information(); keys.setTitle(QString::null); return OK; } if ( command=="variables" ) { keys.setTitle(i18n("Variables:")); QMap::const_iterator it; for (it=coff.variables().begin(); it!=coff.variables().end(); ++it) keys.append(it.key(), toHexLabelAbs(it.data())); return OK; } if ( command=="symbols" ) { keys.setTitle(i18n("Symbols:")); for (uint i=0; iisAuxSymbol() ) continue; const Coff::Symbol &sym = static_cast(*coff.symbol(i)); keys.append(sym.name(), prettySymbol(sym)); } return OK; } if ( command=="sections" ) { keys.setTitle(i18n("Sections:")); for (uint i=0; iname(), i18n("type=\"%1\" address=%2 size=%3 flags=%4") .arg(s->type()==Coff::SectionType::Nb_Types ? "?" : s->type().label()) .arg(toHexLabel(s->address(), nbCharsAddress)).arg(toHexLabel(s->size(), nbCharsAddress)).arg(toHexLabel(s->flags(), 8))); } return OK; } if ( command=="lines" ) { keys.setTitle(i18n("Source Lines:")); keys.append(i18n(" Filename:Line"), i18n("Address")); for (uint i=0; ilines().count()); k++) { if (first) { first = false; keys.append(i18n("section \"%1\":").arg(s->name()), QString::null); } const Coff::CodeLine *cl = s->lines()[k]; QString key = cl->filename() + ":" + QString::number(cl->line()); if ( !cl->address().isValid() ) { const Coff::Symbol &sym = *cl->symbol(); keys.append(key, i18n("symbol \"%1\"").arg(sym.name()) + prettySymbol(sym)); } else keys.append(key, toHexLabel(cl->address(), nbCharsAddress)); } } return OK; } if ( command=="files" ) { keys.setTitle(i18n("Files:")); QStringList::const_iterator it; for (it=coff.filenames().begin(); it!=coff.filenames().end(); ++it) keys.append(*it, QString::null); return OK; } return errorExit(i18n("Command not available for COFF of type Object."), ARG_ERROR); } CLI::ExitCode CLI::Main::executeCommand(const QString &command) { CoffType type = Coff::identify(_source, *this); if ( type==CoffType::Nb_Types ) return ARG_ERROR; Log::KeyList keys; if ( command=="info" ) keys.append(i18n("COFF type:"), type.label()); ExitCode code = ARG_ERROR; switch (type.type()) { case CoffType::Archive: code = executeCommandArchive(command, keys); break; case CoffType::Object: code = executeCommandObject(command, keys); break; case CoffType::Nb_Types: Q_ASSERT(false); break; } if ( code==OK ) keys.display(*_view); return code; } CLI::ExitCode CLI::Main::prepareRun(bool &interactive) { interactive = false; return OK; } CLI::ExitCode CLI::Main::executeSetCommand(const QString &property, const QString &value) { if ( property=="device" || property=="processor" ) { if ( value.isEmpty() ) { _device = 0; return OK; } QString s = value.upper(); _device = Device::lister().data(s); if ( _device==0 ) return errorExit(i18n("Unknown device \"%1\".").arg(s), ARG_ERROR); return OK; } return errorExit(i18n("Unknown property \"%1\".").arg(property), ARG_ERROR); } QString CLI::Main::executeGetCommand(const QString &property) { if ( property=="device" || property=="processor" ) { if ( _device==0 ) return i18n(""); return _device->name(); } log(Log::LineType::SoftError, i18n("Unknown property \"%1\".").arg(property)); return QString::null; } CLI::ExitCode CLI::Main::list(const QString &command) { if ( MainBase::list(command)==OK ) return OK; if ( command=="device-list" ) return deviceList(); Q_ASSERT(false); return OK; } CLI::ExitCode CLI::Main::deviceList() { QValueVector devices; log(Log::LineType::Normal, i18n("Supported devices:")); devices = Device::lister().supportedDevices(); qHeapSort(devices); QString s; for (uint i=0; i