2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: MessageReporter.C /main/1 1996/07/29 16:57:32 cde-hp $ */
24 // Copyright (c) 1994, 1995 James Clark
25 // See the file COPYING for copying permission.
28 #pragma implementation
32 #include "MessageReporter.h"
33 #include "ExtendEntityManager.h"
34 #include "StorageManager.h"
37 #include "MessageArg.h"
38 #include "ErrnoMessageArg.h"
39 #include "SearchResultMessageArg.h"
40 #include "MessageReporterMessages.h"
45 #ifdef DECLARE_STRERROR
52 namespace SP_NAMESPACE {
55 const OutputCharStream::Newline nl = OutputCharStream::newline;
57 MessageReporter::MessageReporter(OutputCharStream *os)
58 : os_(os), options_(0)
62 MessageReporter::~MessageReporter()
67 void MessageReporter::setMessageStream(OutputCharStream *os)
75 void MessageReporter::addOption(Option option)
80 void MessageReporter::dispatchMessage(Message &message)
82 dispatchMessage((const Message &) message);
85 void MessageReporter::dispatchMessage(const Message &message)
88 const ExternalInfo *externalInfo = locationHeader(message.loc, off);
89 if (programName_.size())
90 os() << programName_ << ':';
92 printLocation(externalInfo, off);
95 if (options_ & messageNumbers)
96 os() << (unsigned long)message.type->module() << "."
97 << (unsigned long)message.type->number() << ":";
98 switch (message.type->severity()) {
99 case MessageType::info:
100 appendFragment(MessageReporterMessages::infoTag);
102 case MessageType::warning:
103 appendFragment(MessageReporterMessages::warningTag);
105 case MessageType::quantityError:
106 appendFragment(MessageReporterMessages::quantityErrorTag);
108 case MessageType::idrefError:
109 appendFragment(MessageReporterMessages::idrefErrorTag);
111 case MessageType::error:
112 appendFragment(MessageReporterMessages::errorTag);
118 formatMessage(*message.type, message.args);
120 if (!message.auxLoc.origin().isNull()) {
122 const ExternalInfo *externalInfo = locationHeader(message.auxLoc, off);
123 if (programName_.size())
124 os() << programName_ << ':';
126 printLocation(externalInfo, off);
129 formatMessage(message.type->auxFragment(), message.args);
132 if ((options_ & openElements) && message.openElementInfo.size() > 0) {
133 if (programName_.size())
134 os() << programName_ << ':';
136 printLocation(externalInfo, off);
139 appendFragment(MessageReporterMessages::openElements);
141 unsigned nOpenElements = message.openElementInfo.size();
142 for (unsigned i = 0;; i++) {
144 && (i == nOpenElements || message.openElementInfo[i].included)) {
145 // describe last match in previous open element
146 const OpenElementInfo &prevInfo = message.openElementInfo[i - 1];
147 if (prevInfo.matchType.size() != 0) {
148 os() << " (" << prevInfo.matchType;
149 if (prevInfo.matchIndex != 0)
150 os() << '[' << (unsigned long)prevInfo.matchIndex << ']';
154 if (i == nOpenElements)
156 const OpenElementInfo &e = message.openElementInfo[i];
158 if (i > 0 && !e.included) {
159 unsigned long n = message.openElementInfo[i - 1].matchIndex;
161 os() << '[' << n << ']';
169 void MessageReporter::formatMessage(const MessageFragment &frag,
170 const Vector<CopyOwner<MessageArg> > &args)
173 if (!getMessageText(frag, text)) {
174 appendFragment(MessageReporterMessages::invalidMessage);
178 while (i < text.size()) {
179 if (text[i] == '%') {
181 if (i >= text.size())
183 if (text[i] >= '1' && text[i] <= '9') {
184 if (unsigned(text[i] - '1') < args.size())
185 args[text[i] - '1']->append(*this);
198 const ExternalInfo *MessageReporter::locationHeader(const Location &loc,
201 const Origin *origin = loc.origin().pointer();
202 Index index = loc.index();
203 if (!(options_ & openEntities)) {
205 const InputSourceOrigin *inputSourceOrigin = origin->asInputSourceOrigin();
206 if (inputSourceOrigin) {
207 const ExternalInfo *externalInfo = inputSourceOrigin->externalInfo();
209 off = inputSourceOrigin->startOffset(index);
213 const Location &loc = origin->parent();
214 index = loc.index() + origin->refLength();
215 origin = loc.origin().pointer();
219 Boolean doneHeader = 0;
221 const InputSourceOrigin *inputSourceOrigin = origin->asInputSourceOrigin();
222 if (inputSourceOrigin) {
225 Location parentLoc = inputSourceOrigin->parent();
226 parentLoc += inputSourceOrigin->refLength();
227 const ExternalInfo *parentInfo = locationHeader(parentLoc, parentOff);
230 if (getMessageText(inputSourceOrigin->entityName()
231 ? MessageReporterMessages::inNamedEntity
232 : MessageReporterMessages::inUnnamedEntity,
234 for (size_t i = 0; i < text.size(); i++) {
235 if (text[i] == '%') {
236 if (i + 1 < text.size()) {
239 os() << *inputSourceOrigin->entityName();
240 else if (text[i] == '2')
241 printLocation(parentInfo, parentOff);
242 else if (text[i] >= '3' && text[i] <= '9')
256 off = inputSourceOrigin->startOffset(index);
257 const ExternalInfo *externalInfo = inputSourceOrigin->externalInfo();
261 if (!inputSourceOrigin->defLocation(off, loc))
264 origin = loc.origin().pointer();
267 const Location &loc = origin->parent();
268 index = loc.index() + origin->refLength();
269 origin = loc.origin().pointer();
276 void MessageReporter::printLocation(const ExternalInfo *externalInfo,
280 appendFragment(MessageReporterMessages::invalidLocation);
283 StorageObjectLocation soLoc;
284 if (!ExtendEntityManager::externalize(externalInfo, off, soLoc)) {
285 appendFragment(MessageReporterMessages::invalidLocation);
288 if (strcmp(soLoc.storageObjectSpec->storageManager->type(), "OSFILE") != 0)
289 os() << '<' << soLoc.storageObjectSpec->storageManager->type() << '>';
290 os() << soLoc.storageObjectSpec->id;
291 if (soLoc.lineNumber == (unsigned long)-1) {
293 appendFragment(MessageReporterMessages::offset);
294 os() << soLoc.storageObjectOffset;
297 os() << ':' << soLoc.lineNumber;
298 if (soLoc.columnNumber != 0 && soLoc.columnNumber != (unsigned long)-1)
299 os() << ':' << soLoc.columnNumber - 1;
302 if (soLoc.byteIndex != (unsigned long)-1)
303 os() << ':' << soLoc.byteIndex;
307 void MessageReporter::appendNumber(unsigned long n)
312 void MessageReporter::appendOrdinal(unsigned long n)
317 appendFragment(MessageReporterMessages::ordinal1);
320 appendFragment(MessageReporterMessages::ordinal2);
323 appendFragment(MessageReporterMessages::ordinal3);
326 appendFragment(MessageReporterMessages::ordinaln);
331 void MessageReporter::appendChars(const Char *p, size_t n)
333 os().put('"').write(p, n).put('"');
336 void MessageReporter::appendOther(const OtherMessageArg *p)
338 const ErrnoMessageArg *ea = DYNAMIC_CAST_CONST_PTR(ErrnoMessageArg, p);
341 os() << strerror(ea->errnum());
345 const SearchResultMessageArg *sr
346 = DYNAMIC_CAST_CONST_PTR(SearchResultMessageArg, p);
348 for (size_t i = 0; i < sr->nTried(); i++) {
351 const StringC &f = sr->filename(i);
352 appendChars(f.data(), f.size());
353 switch (sr->errnum(i)) {
356 os() << strerror(sr->errnum(i));
366 appendFragment(MessageReporterMessages::invalidArgumentType);
369 void MessageReporter::appendFragment(const MessageFragment &frag)
372 if (getMessageText(frag, text))
376 Boolean MessageReporter::getMessageText(const MessageFragment &frag,
379 const char *p = frag.text();
384 str += Char((unsigned char)*p);