melder_fatal.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /* melder_fatal.cpp
  2. *
  3. * Copyright (C) 1992-2018 Paul Boersma
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "melder.h"
  19. #include "../sys/MelderThread.h"
  20. MelderThread_MUTEX (theMelder_fatal_mutex);
  21. void Melder_message_init () {
  22. static bool inited = false;
  23. if (! inited) { MelderThread_MUTEX_INIT (theMelder_fatal_mutex); inited = true; }
  24. }
  25. static void defaultFatal (conststring32 message) {
  26. MelderConsole::write (U"Fatal error: ", true);
  27. MelderConsole::write (message, true);
  28. MelderConsole::write (U"\n", true);
  29. }
  30. static void (*theFatalProc) (conststring32 message) = & defaultFatal;
  31. constexpr int Melder_FATAL_BUFFER_SIZE { 2000 };
  32. static char32 theFatalBuffer [Melder_FATAL_BUFFER_SIZE];
  33. static const conststring32 theCrashMessage { U"Praat will crash. Notify the author (paul.boersma@uva.nl) with the following information:\n" };
  34. void Melder_fatal (const MelderArg& arg1,
  35. const MelderArg& arg2, const MelderArg& arg3, const MelderArg& arg4,
  36. const MelderArg& arg5, const MelderArg& arg6, const MelderArg& arg7,
  37. const MelderArg& arg8, const MelderArg& arg9, const MelderArg& arg10)
  38. {
  39. MelderThread_LOCK (theMelder_fatal_mutex);
  40. conststring32 s1 = arg1. _arg ? arg1. _arg : U""; int64 length1 = str32len (s1);
  41. conststring32 s2 = arg2. _arg ? arg2. _arg : U""; int64 length2 = str32len (s2);
  42. conststring32 s3 = arg3. _arg ? arg3. _arg : U""; int64 length3 = str32len (s3);
  43. conststring32 s4 = arg4. _arg ? arg4. _arg : U""; int64 length4 = str32len (s4);
  44. conststring32 s5 = arg5. _arg ? arg5. _arg : U""; int64 length5 = str32len (s5);
  45. conststring32 s6 = arg6. _arg ? arg6. _arg : U""; int64 length6 = str32len (s6);
  46. conststring32 s7 = arg7. _arg ? arg7. _arg : U""; int64 length7 = str32len (s7);
  47. conststring32 s8 = arg8. _arg ? arg8. _arg : U""; int64 length8 = str32len (s8);
  48. conststring32 s9 = arg9. _arg ? arg9. _arg : U""; int64 length9 = str32len (s9);
  49. conststring32 s10 = arg10._arg ? arg10._arg : U""; int64 length10 = str32len (s10);
  50. str32cpy (theFatalBuffer, theCrashMessage);
  51. int64 length = str32len (theFatalBuffer);
  52. if (length + length1 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s1); length += length1; }
  53. if (length + length2 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s2); length += length2; }
  54. if (length + length3 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s3); length += length3; }
  55. if (length + length4 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s4); length += length4; }
  56. if (length + length5 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s5); length += length5; }
  57. if (length + length6 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s6); length += length6; }
  58. if (length + length7 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s7); length += length7; }
  59. if (length + length8 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s8); length += length8; }
  60. if (length + length9 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s9); length += length9; }
  61. if (length + length10 < Melder_FATAL_BUFFER_SIZE) { str32cpy (theFatalBuffer + length, s10); length += length10; }
  62. trace (U"FATAL: ", theFatalBuffer);
  63. (*theFatalProc) (theFatalBuffer);
  64. abort ();
  65. }
  66. void Melder_assert_ (const char *fileName, int lineNumber, const char *condition) {
  67. /*
  68. * This function tries to make sure that it allocates no heap memory.
  69. * Hence, character conversion is done inline rather than with Melder_peek8to32(),
  70. * and Melder_integer() is also avoided.
  71. */
  72. MelderThread_LOCK (theMelder_fatal_mutex);
  73. static char32 fileNameBuffer [1000], conditionBuffer [1000], lineNumberBuffer [40];
  74. Melder_8to32_inplace (fileName, fileNameBuffer, kMelder_textInputEncoding::UTF8);
  75. Melder_8to32_inplace (condition, conditionBuffer, kMelder_textInputEncoding::UTF8);
  76. static char lineNumberBuffer8 [40];
  77. sprintf (lineNumberBuffer8, "%d", lineNumber);
  78. Melder_8to32_inplace (lineNumberBuffer8, lineNumberBuffer, kMelder_textInputEncoding::UTF8);
  79. str32cpy (theFatalBuffer, theCrashMessage);
  80. str32cpy (theFatalBuffer + str32len (theFatalBuffer), U"Assertion failed in file \"");
  81. str32cpy (theFatalBuffer + str32len (theFatalBuffer), fileNameBuffer);
  82. str32cpy (theFatalBuffer + str32len (theFatalBuffer), U"\" at line ");
  83. str32cpy (theFatalBuffer + str32len (theFatalBuffer), lineNumberBuffer);
  84. str32cpy (theFatalBuffer + str32len (theFatalBuffer), U":\n ");
  85. str32cpy (theFatalBuffer + str32len (theFatalBuffer), conditionBuffer);
  86. str32cpy (theFatalBuffer + str32len (theFatalBuffer), U"\n");
  87. trace (U"FATAL: ", theFatalBuffer);
  88. (*theFatalProc) (theFatalBuffer); // ...but this call will use heap memory...
  89. abort ();
  90. }
  91. void Melder_setFatalProc (void (*fatal) (conststring32))
  92. { theFatalProc = fatal ? fatal : & defaultFatal; }
  93. /* End of file melder_fatal.cpp */