slerr.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /* error handling common to all routines. */
  2. /*
  3. Copyright (C) 2004, 2005, 2006 John E. Davis
  4. This file is part of the S-Lang Library.
  5. The S-Lang Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the
  8. License, or (at your option) any later version.
  9. The S-Lang Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this library; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. USA.
  17. */
  18. #include "slinclud.h"
  19. #include "slang.h"
  20. #include "_slang.h"
  21. void (*_pSLinterpreter_Error_Hook) (int);
  22. void (*SLang_VMessage_Hook) (char *, va_list);
  23. void (*SLang_Error_Hook)(char *);
  24. void (*SLang_Exit_Error_Hook)(char *, va_list);
  25. void (*SLang_Dump_Routine)(char *);
  26. volatile int _pSLang_Error = 0;
  27. volatile int SLKeyBoard_Quit = 0;
  28. typedef struct _Exception_Type Exception_Type;
  29. struct _Exception_Type
  30. {
  31. int error_code;
  32. char *name;
  33. char *description;
  34. Exception_Type *subclasses;
  35. Exception_Type *next;
  36. Exception_Type *parent;
  37. };
  38. static Exception_Type *Exception_Root;
  39. static Exception_Type Exception_Root_Buf =
  40. {
  41. -1, "AnyError", "All Errors", NULL, NULL, NULL
  42. };
  43. /* Built-in error codes */
  44. /* These values should correspond to the values produced by _pSLerr_init.
  45. * Some apps may not use the interpreter, and as such _pSLerr_init will not
  46. * get called.
  47. */
  48. int SL_Any_Error = -1;
  49. int SL_Unknown_Error = 6;
  50. int SL_Internal_Error = 5;
  51. int SL_OS_Error = 1;
  52. int SL_Malloc_Error = 2;
  53. int SL_Import_Error = 7;
  54. int SL_RunTime_Error = 3;
  55. int SL_InvalidParm_Error = 4;
  56. int SL_TypeMismatch_Error = 8;
  57. int SL_UserBreak_Error = 9;
  58. int SL_Stack_Error = 10;
  59. int SL_StackOverflow_Error = 12;
  60. int SL_StackUnderflow_Error = 11;
  61. int SL_ReadOnly_Error = 13;
  62. int SL_VariableUninitialized_Error = 14;
  63. int SL_NumArgs_Error = 15;
  64. int SL_Index_Error = 16;
  65. int SL_Usage_Error = 17;
  66. int SL_Application_Error = 18;
  67. int SL_NotImplemented_Error = 19;
  68. int SL_LimitExceeded_Error = 20;
  69. int SL_Forbidden_Error = 21;
  70. int SL_Math_Error = 22;
  71. int SL_DivideByZero_Error = 23;
  72. int SL_ArithOverflow_Error = 24;
  73. int SL_ArithUnderflow_Error = 25;
  74. int SL_Domain_Error = 26;
  75. int SL_IO_Error = 27;
  76. int SL_Write_Error = 28;
  77. int SL_Read_Error = 29;
  78. int SL_Open_Error = 30;
  79. int SL_Data_Error = 31;
  80. int SL_Unicode_Error = 32;
  81. int SL_InvalidUTF8_Error = 33;
  82. int SL_Namespace_Error = 34;
  83. int SL_Parse_Error = 35;
  84. int SL_Syntax_Error = 36;
  85. int SL_DuplicateDefinition_Error = 37;
  86. int SL_UndefinedName_Error = 38;
  87. typedef struct
  88. {
  89. int *errcode_ptr;
  90. char *name;
  91. char *description;
  92. int *base_class_ptr;
  93. }
  94. BuiltIn_Exception_Table_Type;
  95. static SLCONST BuiltIn_Exception_Table_Type BuiltIn_Exception_Table[] =
  96. {
  97. /* Define MallocError and InvalidParmError ASAP */
  98. {&SL_OS_Error, "OSError", "OS Error", &SL_Any_Error},
  99. {&SL_Malloc_Error, "MallocError", "Not enough memory", &SL_OS_Error},
  100. {&SL_RunTime_Error, "RunTimeError", "Run-Time Error", &SL_Any_Error},
  101. {&SL_InvalidParm_Error, "InvalidParmError", "Invalid Parameter", &SL_RunTime_Error},
  102. {&SL_Internal_Error, "InternalError", "Internal Error", &SL_Any_Error},
  103. {&SL_Unknown_Error, "UnknownError", "Unknown Error", &SL_Any_Error},
  104. /* Rest of OSErrors */
  105. {&SL_Import_Error, "ImportError", "Import Error", &SL_OS_Error},
  106. /* Rest of RunTimeErrors */
  107. {&SL_TypeMismatch_Error, "TypeMismatchError", "Type Mismatch", &SL_RunTime_Error},
  108. {&SL_UserBreak_Error, "UserBreakError", "User Break", &SL_RunTime_Error},
  109. {&SL_Stack_Error, "StackError", "Stack Error", &SL_RunTime_Error},
  110. {&SL_StackUnderflow_Error, "StackUnderflowError", "Stack Underflow Error", &SL_Stack_Error},
  111. {&SL_StackOverflow_Error, "StackOverflowError", "Stack Overflow Error", &SL_Stack_Error},
  112. {&SL_ReadOnly_Error, "ReadOnlyError", "Read-Only Error", &SL_RunTime_Error},
  113. {&SL_VariableUninitialized_Error, "VariableUninitializedError", "Variable Uninitialized Error", &SL_RunTime_Error},
  114. {&SL_NumArgs_Error, "NumArgsError", "Invalid Number of Arguments", &SL_RunTime_Error},
  115. {&SL_Index_Error, "IndexError", "Invalid Index", &SL_RunTime_Error},
  116. {&SL_Usage_Error, "UsageError", "Illegal Usage", &SL_RunTime_Error},
  117. {&SL_Application_Error, "ApplicationError", "Application Error", &SL_RunTime_Error},
  118. {&SL_NotImplemented_Error, "NotImplementedError", "Not Implemented", &SL_RunTime_Error},
  119. {&SL_LimitExceeded_Error, "LimitExceededError", "Limit Exceeded", &SL_RunTime_Error},
  120. {&SL_Forbidden_Error, "ForbiddenError", "Operation Forbidden", &SL_RunTime_Error},
  121. {&SL_Math_Error, "MathError", "Math Error", &SL_RunTime_Error},
  122. {&SL_DivideByZero_Error, "DivideByZeroError", "Divide by Zero", &SL_Math_Error},
  123. {&SL_ArithOverflow_Error, "ArithOverflowError", "Arithmetic Overflow", &SL_Math_Error},
  124. {&SL_ArithUnderflow_Error, "ArithUnderflowError", "Arithmetic Underflow", &SL_Math_Error},
  125. {&SL_Domain_Error, "DomainError", "Domain Error", &SL_Math_Error},
  126. {&SL_IO_Error, "IOError", "I/O Error", &SL_RunTime_Error},
  127. {&SL_Write_Error, "WriteError", "Write failed", &SL_IO_Error},
  128. {&SL_Read_Error, "ReadError", "Read failed", &SL_IO_Error},
  129. {&SL_Open_Error, "OpenError", "Open failed", &SL_IO_Error},
  130. {&SL_Data_Error, "DataError", "Data Error", &SL_RunTime_Error},
  131. {&SL_Unicode_Error, "UnicodeError", "Unicode Error", &SL_RunTime_Error},
  132. {&SL_InvalidUTF8_Error, "UTF8Error", "Invalid UTF8", &SL_Unicode_Error},
  133. {&SL_Namespace_Error, "NamespaceError", "Namespace Error", &SL_RunTime_Error},
  134. /* Parse Errors */
  135. {&SL_Parse_Error, "ParseError", "Parse Error", &SL_Any_Error},
  136. {&SL_Syntax_Error, "SyntaxError", "Syntax Error", &SL_Parse_Error},
  137. {&SL_DuplicateDefinition_Error, "DuplicateDefinitionError", "Duplicate Definition", &SL_Parse_Error},
  138. {&SL_UndefinedName_Error, "UndefinedNameError", "Undefined Name", &SL_Parse_Error},
  139. {NULL, NULL, NULL, NULL}
  140. };
  141. static Exception_Type *find_exception (Exception_Type *root, int error_code)
  142. {
  143. Exception_Type *e;
  144. while (root != NULL)
  145. {
  146. if (error_code == root->error_code)
  147. return root;
  148. if (root->subclasses != NULL)
  149. {
  150. e = find_exception (root->subclasses, error_code);
  151. if (e != NULL)
  152. return e;
  153. }
  154. root = root->next;
  155. }
  156. return root;
  157. }
  158. static int is_exception_ancestor (int a, int b)
  159. {
  160. Exception_Type *e;
  161. if (a == b)
  162. return 1;
  163. if (NULL == (e = find_exception (Exception_Root, a)))
  164. return 0;
  165. while (e->parent != NULL)
  166. {
  167. e = e->parent;
  168. if (e->error_code == b)
  169. return 1;
  170. }
  171. return 0;
  172. }
  173. int SLerr_exception_eqs (int a, int b)
  174. {
  175. if (is_exception_ancestor (a, b))
  176. return 1;
  177. return 0;
  178. }
  179. static void free_this_exception (Exception_Type *e)
  180. {
  181. if (e == NULL)
  182. return;
  183. if (e->name != NULL)
  184. SLang_free_slstring (e->name);
  185. if (e->description != NULL)
  186. SLang_free_slstring (e->description);
  187. SLfree ((char *)e);
  188. }
  189. static int Next_Exception_Code;
  190. /* The whole point of this nonsense involving the _pSLerr_New_Exception_Hook
  191. * is to provide a mechanism to avoid linking in the interpreter for apps
  192. * that just want the other facilities.
  193. */
  194. int (*_pSLerr_New_Exception_Hook)(char *name, char *desc, int error_code);
  195. int _pSLerr_init_interp_exceptions (void)
  196. {
  197. SLCONST BuiltIn_Exception_Table_Type *b;
  198. Exception_Type *e;
  199. if (_pSLerr_New_Exception_Hook == NULL)
  200. return 0;
  201. e = &Exception_Root_Buf;
  202. if (-1 == (*_pSLerr_New_Exception_Hook)(e->name, e->description, e->error_code))
  203. return -1;
  204. b = BuiltIn_Exception_Table;
  205. while (b->errcode_ptr != NULL)
  206. {
  207. if (-1 == (*_pSLerr_New_Exception_Hook)(b->name, b->description, *b->errcode_ptr))
  208. return -1;
  209. b++;
  210. }
  211. return 0;
  212. }
  213. int SLerr_new_exception (int baseclass, char *name, char *descript)
  214. {
  215. Exception_Type *base;
  216. Exception_Type *e;
  217. if (-1 == _pSLerr_init ())
  218. return -1;
  219. base = find_exception (Exception_Root, baseclass);
  220. if (base == NULL)
  221. {
  222. SLang_verror (SL_InvalidParm_Error,
  223. "Base class for new exception not found");
  224. return -1;
  225. }
  226. e = (Exception_Type *) SLcalloc (1, sizeof (Exception_Type));
  227. if (e == NULL)
  228. return -1;
  229. if ((NULL == (e->name = SLang_create_slstring (name)))
  230. || (NULL == (e->description = SLang_create_slstring (descript))))
  231. {
  232. free_this_exception (e);
  233. return -1;
  234. }
  235. e->error_code = Next_Exception_Code;
  236. if ((_pSLerr_New_Exception_Hook != NULL)
  237. && (-1 == (*_pSLerr_New_Exception_Hook) (e->name, e->description, e->error_code)))
  238. {
  239. free_this_exception (e);
  240. return -1;
  241. }
  242. e->parent = base;
  243. e->next = base->subclasses;
  244. base->subclasses = e;
  245. Next_Exception_Code++;
  246. return e->error_code;
  247. }
  248. static int init_exceptions (void)
  249. {
  250. SLCONST BuiltIn_Exception_Table_Type *b;
  251. if (Exception_Root != NULL)
  252. return 0;
  253. Exception_Root = &Exception_Root_Buf;
  254. Next_Exception_Code = 1;
  255. b = BuiltIn_Exception_Table;
  256. while (b->errcode_ptr != NULL)
  257. {
  258. int err_code;
  259. err_code = SLerr_new_exception (*b->base_class_ptr, b->name, b->description);
  260. if (err_code == -1)
  261. return -1;
  262. *b->errcode_ptr = err_code;
  263. b++;
  264. }
  265. return 0;
  266. }
  267. static void free_exceptions (Exception_Type *root)
  268. {
  269. while (root != NULL)
  270. {
  271. Exception_Type *next;
  272. if (root->subclasses != NULL)
  273. free_exceptions (root->subclasses);
  274. next = root->next;
  275. free_this_exception (root);
  276. root = next;
  277. }
  278. }
  279. static void deinit_exceptions (void)
  280. {
  281. Exception_Type *root = Exception_Root;
  282. if (root != NULL)
  283. free_exceptions (root->subclasses);
  284. Exception_Root = NULL;
  285. Next_Exception_Code = 0;
  286. }
  287. char *SLerr_strerror (int err_code)
  288. {
  289. Exception_Type *e;
  290. if (err_code == 0)
  291. err_code = _pSLang_Error;
  292. if (-1 == _pSLerr_init ())
  293. return "Unable to initialize SLerr module";
  294. if (NULL == (e = find_exception (Exception_Root, err_code)))
  295. return "Invalid/Unknown Error Code";
  296. return e->description;
  297. }
  298. /* Error Queue Functions
  299. * SLang_verror (int errcode, fmt, args)
  300. * Add an error message to the queue.
  301. * SLerr_delete_queue ()
  302. * Removes messages from the error queue
  303. * SLerr_print_queue ()
  304. * Prints all messages from the queue, deletes the queue
  305. */
  306. typedef struct _Error_Message_Type
  307. {
  308. char *msg; /* SLstring, may be NULL */
  309. int msg_type;
  310. #define _SLERR_MSG_ERROR 1
  311. #define _SLERR_MSG_WARNING 2
  312. #define _SLERR_MSG_TRACEBACK 4
  313. struct _Error_Message_Type *next;
  314. }
  315. Error_Message_Type;
  316. typedef struct
  317. {
  318. Error_Message_Type *head;
  319. Error_Message_Type *tail;
  320. }
  321. Error_Queue_Type;
  322. static Error_Queue_Type *Default_Error_Queue;
  323. static void free_error_msg (Error_Message_Type *m)
  324. {
  325. if (m == NULL)
  326. return;
  327. if (m->msg != NULL)
  328. SLang_free_slstring (m->msg);
  329. SLfree ((char *)m);
  330. }
  331. static Error_Message_Type *allocate_error_msg (char *msg, int msg_type)
  332. {
  333. Error_Message_Type *m;
  334. if (NULL == (m = (Error_Message_Type*) SLcalloc (1, sizeof (Error_Message_Type))))
  335. return NULL;
  336. if ((NULL != msg) && (NULL == (m->msg = SLang_create_slstring (msg))))
  337. {
  338. free_error_msg (m);
  339. return NULL;
  340. }
  341. m->msg_type = msg_type;
  342. return m;
  343. }
  344. static void free_queued_messages (Error_Queue_Type *q)
  345. {
  346. Error_Message_Type *m;
  347. if (q == NULL)
  348. return;
  349. m = q->head;
  350. while (m != NULL)
  351. {
  352. Error_Message_Type *m1 = m->next;
  353. free_error_msg (m);
  354. m = m1;
  355. }
  356. q->head = NULL;
  357. q->tail = NULL;
  358. }
  359. static void delete_msg_queue (Error_Queue_Type *q)
  360. {
  361. if (q == NULL)
  362. return;
  363. free_queued_messages (q);
  364. SLfree ((char *)q);
  365. }
  366. static Error_Queue_Type *create_msg_queue (void)
  367. {
  368. Error_Queue_Type *q;
  369. if (NULL == (q = (Error_Queue_Type *)SLcalloc (1, sizeof(Error_Queue_Type))))
  370. return NULL;
  371. return q;
  372. }
  373. static int queue_message (Error_Queue_Type *q, char *msg, int msg_type)
  374. {
  375. Error_Message_Type *m;
  376. if (NULL == (m = allocate_error_msg (msg, msg_type)))
  377. return -1;
  378. if (q->tail != NULL)
  379. q->tail->next = m;
  380. if (q->head == NULL)
  381. q->head = m;
  382. q->tail = m;
  383. return 0;
  384. }
  385. static void print_error (int msg_type, char *err)
  386. {
  387. unsigned int len;
  388. switch (msg_type)
  389. {
  390. case _SLERR_MSG_ERROR:
  391. if (SLang_Error_Hook != NULL)
  392. {
  393. (*SLang_Error_Hook)(err);
  394. return;
  395. }
  396. break;
  397. case _SLERR_MSG_TRACEBACK:
  398. case _SLERR_MSG_WARNING:
  399. if (SLang_Dump_Routine != NULL)
  400. {
  401. (*SLang_Dump_Routine)(err);
  402. return;
  403. }
  404. break;
  405. }
  406. len = strlen (err);
  407. if (len == 0)
  408. return;
  409. fputs (err, stderr);
  410. if ((err[len-1] != '\n')
  411. && (msg_type != _SLERR_MSG_TRACEBACK))
  412. fputs("\n", stderr);
  413. fflush (stderr);
  414. }
  415. static void print_queue (void)
  416. {
  417. if (-1 == _pSLerr_init ())
  418. print_error (_SLERR_MSG_ERROR, "Unable to initialize SLerr module");
  419. if (_pSLang_Error == 0)
  420. return;
  421. if (Default_Error_Queue != NULL)
  422. {
  423. Error_Queue_Type *q = Default_Error_Queue;
  424. Error_Message_Type *m = q->head;
  425. while (m != NULL)
  426. {
  427. Error_Message_Type *m_next = m->next;
  428. if (m->msg != NULL)
  429. print_error (m->msg_type, m->msg);
  430. m = m_next;
  431. }
  432. free_queued_messages (q);
  433. }
  434. #if 0
  435. if (_pSLang_Error != SL_Usage_Error)
  436. {
  437. print_error (_SLERR_MSG_ERROR, SLerr_strerror (_pSLang_Error));
  438. }
  439. #endif
  440. }
  441. /* This function returns a pointer to the first error message in the queue.
  442. * Make no attempts to free the returned pointer.
  443. */
  444. char *_pSLerr_get_error_from_queue (void)
  445. {
  446. Error_Queue_Type *q;
  447. Error_Message_Type *m;
  448. unsigned int len;
  449. char *err, *err1, *err_max;
  450. if (NULL == (q = Default_Error_Queue))
  451. return NULL;
  452. len = 0;
  453. m = q->head;
  454. while (m != NULL)
  455. {
  456. if (m->msg_type == _SLERR_MSG_ERROR)
  457. len += 1 + strlen (m->msg);
  458. m = m->next;
  459. }
  460. if (len)
  461. len--; /* last \n not needed */
  462. if (NULL == (err = _pSLallocate_slstring (len)))
  463. return NULL;
  464. err_max = err + len;
  465. err1 = err;
  466. m = q->head;
  467. while (m != NULL)
  468. {
  469. if (m->msg_type == _SLERR_MSG_ERROR)
  470. {
  471. unsigned int dlen = strlen (m->msg);
  472. strcpy (err1, m->msg);
  473. err1 += dlen;
  474. if (err1 != err_max)
  475. *err1++ = '\n';
  476. }
  477. m = m->next;
  478. }
  479. *err1 = 0;
  480. return _pSLcreate_via_alloced_slstring (err, len);
  481. }
  482. void _pSLerr_print_message_queue (void)
  483. {
  484. print_queue ();
  485. }
  486. static volatile int Suspend_Error_Messages = 0;
  487. int _pSLerr_resume_messages (void)
  488. {
  489. if (Suspend_Error_Messages == 0)
  490. return 0;
  491. Suspend_Error_Messages--;
  492. if (Suspend_Error_Messages == 0)
  493. print_queue ();
  494. return 0;
  495. }
  496. int _pSLerr_suspend_messages (void)
  497. {
  498. Suspend_Error_Messages++;
  499. return 0;
  500. }
  501. void _pSLerr_free_queued_messages (void)
  502. {
  503. free_queued_messages (Default_Error_Queue);
  504. }
  505. void SLang_verror (int err_code, char *fmt, ...)
  506. {
  507. va_list ap;
  508. char err [4096];
  509. if (-1 == _pSLerr_init ())
  510. {
  511. print_queue ();
  512. return;
  513. }
  514. if (err_code == 0)
  515. err_code = SL_INTRINSIC_ERROR;
  516. if (_pSLang_Error == 0)
  517. SLang_set_error (err_code);
  518. if (fmt == NULL)
  519. return;
  520. va_start(ap, fmt);
  521. (void) SLvsnprintf (err, sizeof (err), fmt, ap);
  522. va_end(ap);
  523. if (Suspend_Error_Messages)
  524. (void) queue_message (Default_Error_Queue, err, _SLERR_MSG_ERROR);
  525. else
  526. print_error (_SLERR_MSG_ERROR, err);
  527. }
  528. int _pSLerr_traceback_msg (char *fmt, ...)
  529. {
  530. va_list ap;
  531. char msg [4096];
  532. va_start(ap, fmt);
  533. (void) SLvsnprintf (msg, sizeof (msg), fmt, ap);
  534. va_end(ap);
  535. return queue_message (Default_Error_Queue, msg, _SLERR_MSG_TRACEBACK);
  536. }
  537. void SLang_exit_error (char *fmt, ...)
  538. {
  539. va_list ap;
  540. print_queue ();
  541. va_start (ap, fmt);
  542. if (SLang_Exit_Error_Hook != NULL)
  543. {
  544. (*SLang_Exit_Error_Hook) (fmt, ap);
  545. exit (1);
  546. }
  547. if (fmt != NULL)
  548. {
  549. vfprintf (stderr, fmt, ap);
  550. fputs ("\n", stderr);
  551. fflush (stderr);
  552. }
  553. va_end (ap);
  554. exit (1);
  555. }
  556. int SLang_set_error (int error)
  557. {
  558. /* Only allow an error to be cleared (error==0), but not changed
  559. * if there already is an error.
  560. */
  561. if ((error == 0)
  562. || (_pSLang_Error == 0))
  563. _pSLang_Error = error;
  564. if (_pSLinterpreter_Error_Hook != NULL)
  565. (*_pSLinterpreter_Error_Hook) (_pSLang_Error);
  566. return 0;
  567. }
  568. int SLang_get_error (void)
  569. {
  570. return _pSLang_Error;
  571. }
  572. void SLang_vmessage (char *fmt, ...)
  573. {
  574. va_list ap;
  575. if (fmt == NULL)
  576. return;
  577. va_start (ap, fmt);
  578. if (SLang_VMessage_Hook != NULL)
  579. (*SLang_VMessage_Hook) (fmt, ap);
  580. else
  581. {
  582. vfprintf (stdout, fmt, ap);
  583. fputs ("\n", stdout);
  584. }
  585. va_end (ap);
  586. }
  587. /* This routine does not queue messages. It is used for tracing, etc. */
  588. void _pSLerr_dump_msg (char *fmt, ...)
  589. {
  590. char buf[1024];
  591. va_list ap;
  592. va_start (ap, fmt);
  593. if (SLang_Dump_Routine != NULL)
  594. {
  595. (void) SLvsnprintf (buf, sizeof (buf), fmt, ap);
  596. (*SLang_Dump_Routine) (buf);
  597. }
  598. else
  599. {
  600. vfprintf (stderr, fmt, ap);
  601. fflush (stderr);
  602. }
  603. va_end (ap);
  604. }
  605. int _pSLerr_init (void)
  606. {
  607. if (Default_Error_Queue == NULL)
  608. {
  609. Suspend_Error_Messages = 0;
  610. if (NULL == (Default_Error_Queue = create_msg_queue ()))
  611. return -1;
  612. }
  613. if (-1 == init_exceptions ())
  614. return -1;
  615. return 0;
  616. }
  617. void _pSLerr_deinit (void)
  618. {
  619. deinit_exceptions ();
  620. delete_msg_queue (Default_Error_Queue);
  621. Suspend_Error_Messages = 0;
  622. Default_Error_Queue = NULL;
  623. }