1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/programs/nsgmls/MessageReporter.C
2018-04-28 12:30:20 -06:00

390 lines
9.9 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: MessageReporter.C /main/1 1996/07/29 16:57:32 cde-hp $ */
// Copyright (c) 1994, 1995 James Clark
// See the file COPYING for copying permission.
#ifdef __GNUG__
#pragma implementation
#endif
#include "splib.h"
#include "MessageReporter.h"
#include "ExtendEntityManager.h"
#include "StorageManager.h"
#include "macros.h"
#include "rtti.h"
#include "MessageArg.h"
#include "ErrnoMessageArg.h"
#include "SearchResultMessageArg.h"
#include "MessageReporterMessages.h"
#include <string.h>
#include <errno.h>
#ifdef DECLARE_STRERROR
extern "C" {
char *strerror(int);
}
#endif
#ifdef SP_NAMESPACE
namespace SP_NAMESPACE {
#endif
const OutputCharStream::Newline nl = OutputCharStream::newline;
MessageReporter::MessageReporter(OutputCharStream *os)
: os_(os), options_(0)
{
}
MessageReporter::~MessageReporter()
{
delete os_;
}
void MessageReporter::setMessageStream(OutputCharStream *os)
{
if (os != os_) {
delete os_;
os_ = os;
}
}
void MessageReporter::addOption(Option option)
{
options_ |= option;
}
void MessageReporter::dispatchMessage(Message &message)
{
dispatchMessage((const Message &) message);
}
void MessageReporter::dispatchMessage(const Message &message)
{
Offset off;
const ExternalInfo *externalInfo = locationHeader(message.loc, off);
if (programName_.size())
os() << programName_ << ':';
if (externalInfo) {
printLocation(externalInfo, off);
os() << ':';
}
if (options_ & messageNumbers)
os() << (unsigned long)message.type->module() << "."
<< (unsigned long)message.type->number() << ":";
switch (message.type->severity()) {
case MessageType::info:
appendFragment(MessageReporterMessages::infoTag);
break;
case MessageType::warning:
appendFragment(MessageReporterMessages::warningTag);
break;
case MessageType::quantityError:
appendFragment(MessageReporterMessages::quantityErrorTag);
break;
case MessageType::idrefError:
appendFragment(MessageReporterMessages::idrefErrorTag);
break;
case MessageType::error:
appendFragment(MessageReporterMessages::errorTag);
break;
default:
CANNOT_HAPPEN();
}
os() << ": ";
formatMessage(*message.type, message.args);
os() << nl;
if (!message.auxLoc.origin().isNull()) {
Offset off;
const ExternalInfo *externalInfo = locationHeader(message.auxLoc, off);
if (programName_.size())
os() << programName_ << ':';
if (externalInfo) {
printLocation(externalInfo, off);
os() << ": ";
}
formatMessage(message.type->auxFragment(), message.args);
os() << nl;
}
if ((options_ & openElements) && message.openElementInfo.size() > 0) {
if (programName_.size())
os() << programName_ << ':';
if (externalInfo) {
printLocation(externalInfo, off);
os() << ": ";
}
appendFragment(MessageReporterMessages::openElements);
os() << ':';
unsigned nOpenElements = message.openElementInfo.size();
for (unsigned i = 0;; i++) {
if (i > 0
&& (i == nOpenElements || message.openElementInfo[i].included)) {
// describe last match in previous open element
const OpenElementInfo &prevInfo = message.openElementInfo[i - 1];
if (prevInfo.matchType.size() != 0) {
os() << " (" << prevInfo.matchType;
if (prevInfo.matchIndex != 0)
os() << '[' << (unsigned long)prevInfo.matchIndex << ']';
os() << ')';
}
}
if (i == nOpenElements)
break;
const OpenElementInfo &e = message.openElementInfo[i];
os() << ' ' << e.gi;
if (i > 0 && !e.included) {
unsigned long n = message.openElementInfo[i - 1].matchIndex;
if (n != 0)
os() << '[' << n << ']';
}
}
os() << nl;
}
os().flush();
}
void MessageReporter::formatMessage(const MessageFragment &frag,
const Vector<CopyOwner<MessageArg> > &args)
{
StringC text;
if (!getMessageText(frag, text)) {
appendFragment(MessageReporterMessages::invalidMessage);
return;
}
size_t i = 0;
while (i < text.size()) {
if (text[i] == '%') {
i++;
if (i >= text.size())
break;
if (text[i] >= '1' && text[i] <= '9') {
if (unsigned(text[i] - '1') < args.size())
args[text[i] - '1']->append(*this);
}
else
os().put(text[i]);
i++;
}
else {
os().put(text[i]);
i++;
}
}
}
const ExternalInfo *MessageReporter::locationHeader(const Location &loc,
Offset &off)
{
const Origin *origin = loc.origin().pointer();
Index index = loc.index();
if (!(options_ & openEntities)) {
while (origin) {
const InputSourceOrigin *inputSourceOrigin = origin->asInputSourceOrigin();
if (inputSourceOrigin) {
const ExternalInfo *externalInfo = inputSourceOrigin->externalInfo();
if (externalInfo) {
off = inputSourceOrigin->startOffset(index);
return externalInfo;
}
}
const Location &loc = origin->parent();
index = loc.index() + origin->refLength();
origin = loc.origin().pointer();
}
}
else {
Boolean doneHeader = 0;
while (origin) {
const InputSourceOrigin *inputSourceOrigin = origin->asInputSourceOrigin();
if (inputSourceOrigin) {
if (!doneHeader) {
Offset parentOff;
Location parentLoc = inputSourceOrigin->parent();
parentLoc += inputSourceOrigin->refLength();
const ExternalInfo *parentInfo = locationHeader(parentLoc, parentOff);
if (parentInfo) {
StringC text;
if (getMessageText(inputSourceOrigin->entityName()
? MessageReporterMessages::inNamedEntity
: MessageReporterMessages::inUnnamedEntity,
text)) {
for (size_t i = 0; i < text.size(); i++) {
if (text[i] == '%') {
if (i + 1 < text.size()) {
i++;
if (text[i] == '1')
os() << *inputSourceOrigin->entityName();
else if (text[i] == '2')
printLocation(parentInfo, parentOff);
else if (text[i] >= '3' && text[i] <= '9')
;
else
os().put(text[i]);
}
}
else
os().put(text[i]);
}
os() << nl;
}
}
doneHeader = 1;
}
off = inputSourceOrigin->startOffset(index);
const ExternalInfo *externalInfo = inputSourceOrigin->externalInfo();
if (externalInfo)
return externalInfo;
Location loc;
if (!inputSourceOrigin->defLocation(off, loc))
break;
index = loc.index();
origin = loc.origin().pointer();
}
else {
const Location &loc = origin->parent();
index = loc.index() + origin->refLength();
origin = loc.origin().pointer();
}
}
}
return 0;
}
void MessageReporter::printLocation(const ExternalInfo *externalInfo,
Offset off)
{
if (!externalInfo) {
appendFragment(MessageReporterMessages::invalidLocation);
return;
}
StorageObjectLocation soLoc;
if (!ExtendEntityManager::externalize(externalInfo, off, soLoc)) {
appendFragment(MessageReporterMessages::invalidLocation);
return;
}
if (strcmp(soLoc.storageObjectSpec->storageManager->type(), "OSFILE") != 0)
os() << '<' << soLoc.storageObjectSpec->storageManager->type() << '>';
os() << soLoc.storageObjectSpec->id;
if (soLoc.lineNumber == (unsigned long)-1) {
os() << ": ";
appendFragment(MessageReporterMessages::offset);
os() << soLoc.storageObjectOffset;
}
else {
os() << ':' << soLoc.lineNumber;
if (soLoc.columnNumber != 0 && soLoc.columnNumber != (unsigned long)-1)
os() << ':' << soLoc.columnNumber - 1;
}
#if 0
if (soLoc.byteIndex != (unsigned long)-1)
os() << ':' << soLoc.byteIndex;
#endif
}
void MessageReporter::appendNumber(unsigned long n)
{
os() << n;
}
void MessageReporter::appendOrdinal(unsigned long n)
{
os() << n;
switch (n % 10) {
case 1:
appendFragment(MessageReporterMessages::ordinal1);
break;
case 2:
appendFragment(MessageReporterMessages::ordinal2);
break;
case 3:
appendFragment(MessageReporterMessages::ordinal3);
break;
default:
appendFragment(MessageReporterMessages::ordinaln);
break;
}
}
void MessageReporter::appendChars(const Char *p, size_t n)
{
os().put('"').write(p, n).put('"');
}
void MessageReporter::appendOther(const OtherMessageArg *p)
{
const ErrnoMessageArg *ea = DYNAMIC_CAST_CONST_PTR(ErrnoMessageArg, p);
if (ea) {
os() << strerror(ea->errnum());
return;
}
const SearchResultMessageArg *sr
= DYNAMIC_CAST_CONST_PTR(SearchResultMessageArg, p);
if (sr) {
for (size_t i = 0; i < sr->nTried(); i++) {
if (i > 0)
os() << ", ";
const StringC &f = sr->filename(i);
appendChars(f.data(), f.size());
switch (sr->errnum(i)) {
default:
os() << " (";
os() << strerror(sr->errnum(i));
os() << ")";
#ifdef ENOENT
case ENOENT:
#endif
break;
}
}
return;
}
appendFragment(MessageReporterMessages::invalidArgumentType);
}
void MessageReporter::appendFragment(const MessageFragment &frag)
{
StringC text;
if (getMessageText(frag, text))
os() << text;
}
Boolean MessageReporter::getMessageText(const MessageFragment &frag,
StringC &str)
{
const char *p = frag.text();
if (!p)
return 0;
str.resize(0);
for (; *p; p++)
str += Char((unsigned char)*p);
return 1;
}
#ifdef SP_NAMESPACE
}
#endif