/branches/jade_1_2_1/lib/MessageReporter.cxx

# · C++ · 239 lines · 220 code · 16 blank · 3 comment · 56 complexity · 900a5c34b88a6782e08030f5a4009daf MD5 · raw file

  1. // Copyright (c) 1994, 1995 James Clark
  2. // See the file COPYING for copying permission.
  3. #ifdef __GNUG__
  4. #pragma implementation
  5. #endif
  6. #include "splib.h"
  7. #include "MessageReporter.h"
  8. #include "MessageReporterMessages.h"
  9. #include "ExtendEntityManager.h"
  10. #include "StorageManager.h"
  11. #include "macros.h"
  12. #include <string.h>
  13. #ifdef SP_NAMESPACE
  14. namespace SP_NAMESPACE {
  15. #endif
  16. const OutputCharStream::Newline nl = OutputCharStream::newline;
  17. MessageReporter::MessageReporter(OutputCharStream *os)
  18. : os_(os), options_(0)
  19. {
  20. }
  21. MessageReporter::~MessageReporter()
  22. {
  23. delete os_;
  24. }
  25. void MessageReporter::setMessageStream(OutputCharStream *os)
  26. {
  27. if (os != os_) {
  28. delete os_;
  29. os_ = os;
  30. }
  31. }
  32. void MessageReporter::addOption(Option option)
  33. {
  34. options_ |= option;
  35. }
  36. void MessageReporter::dispatchMessage(const Message &message)
  37. {
  38. Offset off;
  39. const ExternalInfo *externalInfo = locationHeader(message.loc, off);
  40. if (programName_.size())
  41. os() << programName_ << ':';
  42. if (externalInfo) {
  43. printLocation(externalInfo, off);
  44. os() << ':';
  45. }
  46. if (options_ & messageNumbers)
  47. os() << (unsigned long)message.type->module() << "."
  48. << (unsigned long)message.type->number() << ":";
  49. switch (message.type->severity()) {
  50. case MessageType::info:
  51. formatFragment(MessageReporterMessages::infoTag, os());
  52. break;
  53. case MessageType::warning:
  54. formatFragment(MessageReporterMessages::warningTag, os());
  55. break;
  56. case MessageType::quantityError:
  57. formatFragment(MessageReporterMessages::quantityErrorTag, os());
  58. break;
  59. case MessageType::idrefError:
  60. formatFragment(MessageReporterMessages::idrefErrorTag, os());
  61. break;
  62. case MessageType::error:
  63. formatFragment(MessageReporterMessages::errorTag, os());
  64. break;
  65. default:
  66. CANNOT_HAPPEN();
  67. }
  68. os() << ": ";
  69. formatMessage(*message.type, message.args, os());
  70. os() << nl;
  71. if (!message.auxLoc.origin().isNull()) {
  72. Offset off;
  73. const ExternalInfo *externalInfo = locationHeader(message.auxLoc, off);
  74. if (programName_.size())
  75. os() << programName_ << ':';
  76. if (externalInfo) {
  77. printLocation(externalInfo, off);
  78. os() << ": ";
  79. }
  80. formatMessage(message.type->auxFragment(), message.args, os());
  81. os() << nl;
  82. }
  83. if ((options_ & openElements) && message.openElementInfo.size() > 0) {
  84. if (programName_.size())
  85. os() << programName_ << ':';
  86. if (externalInfo) {
  87. printLocation(externalInfo, off);
  88. os() << ": ";
  89. }
  90. formatFragment(MessageReporterMessages::openElements, os());
  91. os() << ':';
  92. formatOpenElements(message.openElementInfo, os());
  93. os() << nl;
  94. }
  95. os().flush();
  96. }
  97. // Note this is written so as not to change any reference counts.
  98. const ExternalInfo *MessageReporter::locationHeader(const Location &loc,
  99. Offset &off)
  100. {
  101. return locationHeader(loc.origin().pointer(), loc.index(), off);
  102. }
  103. const ExternalInfo *MessageReporter::locationHeader(const Origin *origin,
  104. Index index,
  105. Offset &off)
  106. {
  107. if (!(options_ & openEntities)) {
  108. while (origin) {
  109. const ExternalInfo *externalInfo = origin->externalInfo();
  110. if (externalInfo) {
  111. off = origin->startOffset(index);
  112. return externalInfo;
  113. }
  114. const Location &loc = origin->parent();
  115. if (loc.origin().isNull()) {
  116. if (!origin->defLocation(origin->startOffset(index), origin, index))
  117. break;
  118. }
  119. else {
  120. index = loc.index() + origin->refLength();
  121. origin = loc.origin().pointer();
  122. }
  123. }
  124. }
  125. else {
  126. Boolean doneHeader = 0;
  127. while (origin) {
  128. if (origin->entityName() || origin->parent().origin().isNull()) {
  129. if (!doneHeader) {
  130. Offset parentOff;
  131. const Location &parentLoc = origin->parent();
  132. const ExternalInfo *parentInfo
  133. = locationHeader(parentLoc.origin().pointer(),
  134. parentLoc.index() + origin->refLength(),
  135. parentOff);
  136. if (parentInfo) {
  137. StringC text;
  138. if (getMessageText(origin->entityName()
  139. ? MessageReporterMessages::inNamedEntity
  140. : MessageReporterMessages::inUnnamedEntity,
  141. text)) {
  142. for (size_t i = 0; i < text.size(); i++) {
  143. if (text[i] == '%') {
  144. if (i + 1 < text.size()) {
  145. i++;
  146. if (text[i] == '1')
  147. os() << *origin->entityName();
  148. else if (text[i] == '2')
  149. printLocation(parentInfo, parentOff);
  150. else if (text[i] >= '3' && text[i] <= '9')
  151. ;
  152. else
  153. os().put(text[i]);
  154. }
  155. }
  156. else
  157. os().put(text[i]);
  158. }
  159. os() << nl;
  160. }
  161. }
  162. doneHeader = 1;
  163. }
  164. off = origin->startOffset(index);
  165. const ExternalInfo *externalInfo = origin->externalInfo();
  166. if (externalInfo)
  167. return externalInfo;
  168. if (!origin->defLocation(off, origin, index))
  169. break;
  170. }
  171. else {
  172. const Location &loc = origin->parent();
  173. index = loc.index() + origin->refLength();
  174. origin = loc.origin().pointer();
  175. }
  176. }
  177. }
  178. return 0;
  179. }
  180. void MessageReporter::printLocation(const ExternalInfo *externalInfo,
  181. Offset off)
  182. {
  183. if (!externalInfo) {
  184. formatFragment(MessageReporterMessages::invalidLocation, os());
  185. return;
  186. }
  187. StorageObjectLocation soLoc;
  188. if (!ExtendEntityManager::externalize(externalInfo, off, soLoc)) {
  189. formatFragment(MessageReporterMessages::invalidLocation, os());
  190. return;
  191. }
  192. if (strcmp(soLoc.storageObjectSpec->storageManager->type(), "OSFILE") != 0)
  193. os() << '<' << soLoc.storageObjectSpec->storageManager->type() << '>';
  194. os() << soLoc.actualStorageId;
  195. if (soLoc.lineNumber == (unsigned long)-1) {
  196. os() << ": ";
  197. formatFragment(MessageReporterMessages::offset, os());
  198. os() << soLoc.storageObjectOffset;
  199. }
  200. else {
  201. os() << ':' << soLoc.lineNumber;
  202. if (soLoc.columnNumber != 0 && soLoc.columnNumber != (unsigned long)-1)
  203. os() << ':' << soLoc.columnNumber - 1;
  204. }
  205. #if 0
  206. if (soLoc.byteIndex != (unsigned long)-1)
  207. os() << ':' << soLoc.byteIndex;
  208. #endif
  209. }
  210. Boolean MessageReporter::getMessageText(const MessageFragment &frag,
  211. StringC &str)
  212. {
  213. const char *p = frag.text();
  214. if (!p)
  215. return 0;
  216. str.resize(0);
  217. for (; *p; p++)
  218. str += Char((unsigned char)*p);
  219. return 1;
  220. }
  221. #ifdef SP_NAMESPACE
  222. }
  223. #endif