hqlerror.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "jlog.hpp"
  14. #include "hqlerror.hpp"
  15. #include "hqlerrors.hpp"
  16. //---------------------------------------------------------------------------------------------------------------------
  17. ErrorSeverity getSeverity(IAtom * name)
  18. {
  19. if (name == failAtom)
  20. return SeverityFatal;
  21. if (name == errorAtom)
  22. return SeverityError;
  23. if (name == warningAtom)
  24. return SeverityWarning;
  25. if (name == ignoreAtom)
  26. return SeverityIgnore;
  27. if (name == logAtom)
  28. return SeverityInformation;
  29. return SeverityUnknown;
  30. }
  31. WarnErrorCategory getCategory(const char * category)
  32. {
  33. if (strieq(category, "all"))
  34. return CategoryAll;
  35. if (strieq(category, "cast"))
  36. return CategoryCast;
  37. if (strieq(category, "confuse"))
  38. return CategoryConfuse;
  39. if (strieq(category, "deprecated"))
  40. return CategoryDeprecated;
  41. if (strieq(category, "efficiency"))
  42. return CategoryEfficiency;
  43. if (strieq(category, "fold"))
  44. return CategoryFolding;
  45. if (strieq(category, "future"))
  46. return CategoryFuture;
  47. if (strieq(category, "ignored"))
  48. return CategoryIgnored;
  49. if (strieq(category, "index"))
  50. return CategoryIndex;
  51. if (strieq(category, "info"))
  52. return CategoryInformation;
  53. if (strieq(category, "mistake"))
  54. return CategoryMistake;
  55. if (strieq(category, "limit"))
  56. return CategoryLimit;
  57. if (strieq(category, "syntax"))
  58. return CategorySyntax;
  59. if (strieq(category, "unusual"))
  60. return CategoryUnusual;
  61. if (strieq(category, "unexpected"))
  62. return CategoryUnexpected;
  63. if (strieq(category, "cpp"))
  64. return CategoryCpp;
  65. if (strieq(category, "security"))
  66. return CategorySecurity;
  67. if (strieq(category, "dfs"))
  68. return CategoryDFS;
  69. if (strieq(category, "embed"))
  70. return CategoryEmbed;
  71. return CategoryUnknown;
  72. }
  73. ErrorSeverity getCheckSeverity(IAtom * name)
  74. {
  75. ErrorSeverity severity = getSeverity(name);
  76. assertex(severity != SeverityUnknown);
  77. return severity;
  78. }
  79. //---------------------------------------------------------------------------------------------------------------------
  80. void ErrorReceiverSink::report(IError* error)
  81. {
  82. switch (error->getSeverity())
  83. {
  84. case SeverityWarning:
  85. warns++;
  86. break;
  87. case SeverityError:
  88. case SeverityFatal:
  89. errs++;
  90. break;
  91. }
  92. }
  93. //---------------------------------------------------------------------------------------------------------------------
  94. void MultiErrorReceiver::report(IError* error)
  95. {
  96. ErrorReceiverSink::report(error);
  97. msgs.append(*LINK(error));
  98. StringBuffer msg;
  99. DBGLOG("reportError(%d:%d) : %s", error->getLine(), error->getColumn(), error->errorMessage(msg).str());
  100. }
  101. StringBuffer& MultiErrorReceiver::toString(StringBuffer& buf)
  102. {
  103. ForEachItemIn(i, msgs)
  104. {
  105. IError* error=item(i);
  106. error->toString(buf);
  107. buf.append('\n');
  108. }
  109. return buf;
  110. }
  111. IError *MultiErrorReceiver::firstError()
  112. {
  113. ForEachItemIn(i, msgs)
  114. {
  115. IError* error = item(i);
  116. if (isError(error->getSeverity()))
  117. return error;
  118. }
  119. return NULL;
  120. }
  121. extern HQL_API void reportErrors(IErrorReceiver & receiver, IErrorArray & errors)
  122. {
  123. ForEachItemIn(i, errors)
  124. receiver.report(&errors.item(i));
  125. }
  126. //---------------------------------------------------------------------------------------------------------------------
  127. class HQL_API FileErrorReceiver : public ErrorReceiverSink
  128. {
  129. public:
  130. FileErrorReceiver(FILE *_f)
  131. {
  132. f = _f;
  133. }
  134. protected:
  135. FILE *f;
  136. };
  137. class HQL_API StandardFileErrorReceiver : public FileErrorReceiver
  138. {
  139. public:
  140. StandardFileErrorReceiver(FILE *_f) : FileErrorReceiver(_f) {}
  141. virtual void report(IError* error) override
  142. {
  143. ErrorReceiverSink::report(error);
  144. ErrorSeverity severity = error->getSeverity();
  145. const char * severityText;
  146. switch (severity)
  147. {
  148. case SeverityIgnore:
  149. return;
  150. case SeverityInformation:
  151. severityText = "info";
  152. break;
  153. case SeverityWarning:
  154. severityText = "warning";
  155. break;
  156. case SeverityError:
  157. case SeverityFatal:
  158. severityText = "error";
  159. break;
  160. default:
  161. throwUnexpected();
  162. }
  163. unsigned code = error->errorCode();
  164. const char * filename = error->getFilename();
  165. unsigned line = error->getLine();
  166. unsigned column = error->getColumn();
  167. StringBuffer msg;
  168. error->errorMessage(msg);
  169. if (!filename) filename = isError(severity) ? "" : unknownAtom->queryStr();
  170. fprintf(f, "%s(%d,%d): %s C%04d: %s\n", filename, line, column, severityText, code, msg.str());
  171. }
  172. };
  173. class HQL_API XmlFileErrorReceiver : public FileErrorReceiver
  174. {
  175. public:
  176. XmlFileErrorReceiver(FILE *_f) : FileErrorReceiver(_f) {}
  177. virtual void report(IError* error) override
  178. {
  179. ErrorReceiverSink::report(error);
  180. OwnedPTree tree = error->toTree();
  181. StringBuffer msg;
  182. toXML(tree, msg, 0, XML_Embed);
  183. fprintf(f, "%s\n", msg.str());
  184. }
  185. };
  186. extern HQL_API IErrorReceiver *createFileErrorReceiver(FILE *f)
  187. {
  188. return new StandardFileErrorReceiver(f);
  189. }
  190. extern HQL_API IErrorReceiver *createXmlFileErrorReceiver(FILE *f)
  191. {
  192. return new XmlFileErrorReceiver(f);
  193. }
  194. //---------------------------------------------------------------------------------------------------------------------
  195. class HQL_API ThrowingErrorReceiver : public ErrorReceiverSink
  196. {
  197. virtual void report(IError* error);
  198. };
  199. void ThrowingErrorReceiver::report(IError* error)
  200. {
  201. throw LINK(error);
  202. }
  203. IErrorReceiver * createThrowingErrorReceiver()
  204. {
  205. return new ThrowingErrorReceiver;
  206. }
  207. //---------------------------------------------------------------------------------------------------------------------
  208. IErrorReceiver * createNullErrorReceiver()
  209. {
  210. return new NullErrorReceiver;
  211. }
  212. //---------------------------------------------------------------------------------------------------------------------
  213. void reportErrorVa(IErrorReceiver * errors, int errNo, const ECLlocation & loc, const char* format, va_list args)
  214. {
  215. StringBuffer msg;
  216. msg.valist_appendf(format, args);
  217. if (errors)
  218. errors->reportError(errNo, msg.str(), str(loc.sourcePath), loc.lineno, loc.column, loc.position);
  219. else
  220. throw createError(errNo, msg.str(), str(loc.sourcePath), loc.lineno, loc.column, loc.position);
  221. }
  222. void reportError(IErrorReceiver * errors, int errNo, const ECLlocation & loc, const char * format, ...)
  223. {
  224. va_list args;
  225. va_start(args, format);
  226. reportErrorVa(errors, errNo, loc, format, args);
  227. va_end(args);
  228. }
  229. class ErrorInserter : public IndirectErrorReceiver
  230. {
  231. public:
  232. ErrorInserter(IErrorReceiver & _prev, IError * _error) : IndirectErrorReceiver(_prev), error(_error) {}
  233. virtual void report(IError* error)
  234. {
  235. if (isError(error->getSeverity()))
  236. flush();
  237. IndirectErrorReceiver::report(error);
  238. }
  239. protected:
  240. void flush()
  241. {
  242. if (error)
  243. {
  244. IndirectErrorReceiver::report(error);
  245. error.clear();
  246. }
  247. }
  248. protected:
  249. Linked<IError> error;
  250. };
  251. //---------------------------------------------------------------------------------------------------------------------
  252. class AbortingErrorReceiver : public IndirectErrorReceiver
  253. {
  254. public:
  255. AbortingErrorReceiver(IErrorReceiver & _prev) : IndirectErrorReceiver(_prev) {}
  256. virtual void report(IError* error)
  257. {
  258. Owned<IError> mappedError = prevErrorProcessor->mapError(error);
  259. prevErrorProcessor->report(mappedError);
  260. if (isError(mappedError->getSeverity()))
  261. throw MakeStringExceptionDirect(HQLERR_ErrorAlreadyReported, "");
  262. }
  263. };
  264. IErrorReceiver * createAbortingErrorReceiver(IErrorReceiver & prev)
  265. {
  266. return new AbortingErrorReceiver(prev);
  267. }
  268. //---------------------------------------------------------------------------------------------------------------------
  269. class DedupingErrorReceiver : public IndirectErrorReceiver
  270. {
  271. public:
  272. DedupingErrorReceiver(IErrorReceiver & _prev) : IndirectErrorReceiver(_prev) {}
  273. virtual void report(IError* error)
  274. {
  275. if (errors.contains(*error))
  276. return;
  277. errors.append(*LINK(error));
  278. IndirectErrorReceiver::report(error);
  279. }
  280. private:
  281. IArray errors;
  282. };
  283. IErrorReceiver * createDedupingErrorReceiver(IErrorReceiver & prev)
  284. {
  285. return new DedupingErrorReceiver(prev);
  286. }
  287. //---------------------------------------------------------------------------------------------------------------------
  288. void checkEclVersionCompatible(Shared<IErrorReceiver> & errors, const char * eclVersion)
  289. {
  290. if (eclVersion)
  291. {
  292. unsigned major, minor, subminor;
  293. if (extractVersion(major, minor, subminor, eclVersion))
  294. {
  295. if (major != LANGUAGE_VERSION_MAJOR)
  296. {
  297. VStringBuffer msg("Mismatch in major version number (%s v %s)", eclVersion, LANGUAGE_VERSION);
  298. errors->reportWarning(CategoryUnexpected, HQLERR_VersionMismatch, msg.str(), NULL, 0, 0, 0);
  299. }
  300. else if (minor != LANGUAGE_VERSION_MINOR)
  301. {
  302. VStringBuffer msg("Mismatch in minor version number (%s v %s)", eclVersion, LANGUAGE_VERSION);
  303. Owned<IError> warning = createError(CategoryUnexpected, SeverityInformation, HQLERR_VersionMismatch, msg.str(), NULL, 0, 0);
  304. errors.setown(new ErrorInserter(*errors, warning));
  305. }
  306. else if (subminor != LANGUAGE_VERSION_SUB)
  307. {
  308. //This adds the warning if any other warnings occur.
  309. VStringBuffer msg("Mismatch in subminor version number (%s v %s)", eclVersion, LANGUAGE_VERSION);
  310. Owned<IError> warning = createError(CategoryUnexpected, SeverityInformation, HQLERR_VersionMismatch, msg.str(), NULL, 0, 0);
  311. errors.setown(new ErrorInserter(*errors, warning));
  312. }
  313. }
  314. }
  315. }