category.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /* $Id$
  2. *
  3. * category.h
  4. *
  5. * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
  6. *
  7. * See the COPYING file for the terms of usage and distribution.
  8. */
  9. #ifndef log4c_category_h
  10. #define log4c_category_h
  11. /**
  12. * @file category.h
  13. *
  14. * @brief central class in the log4c package.
  15. *
  16. * One of the distintive features of log4j (and hence log4c) are
  17. * hierarchical categories and their evaluation.
  18. *
  19. **/
  20. #include <stdio.h>
  21. #include <stdarg.h>
  22. #include <log4c/defs.h>
  23. #include <log4c/priority.h>
  24. #include <log4c/location_info.h>
  25. __LOG4C_BEGIN_DECLS
  26. struct __log4c_appender;
  27. struct __log4c_category;
  28. /**
  29. * log4c category class
  30. **/
  31. typedef struct __log4c_category log4c_category_t;
  32. /**
  33. * Instantiate a log4c_category_t with name @a name. This method
  34. * does not set priority of the category which is by default @c
  35. * LOG4C_PRIORITY_NOTSET.
  36. *
  37. * @param a_name The name of the category to retrieve.
  38. **/
  39. LOG4C_API log4c_category_t* log4c_category_get(const char* a_name);
  40. /**
  41. * Fill in an array with the log4c categories.
  42. *
  43. * @param a_cats array of categories that will be filled
  44. * @param a_ncats number of categories in the array
  45. *
  46. * @returns -1 if it fails or the number of available categories in
  47. * log4c.
  48. **/
  49. LOG4C_API int log4c_category_list(log4c_category_t** a_cats, int a_ncats);
  50. /**
  51. * Constructor for a log4c_category_t.
  52. *
  53. * @param a_name the category name
  54. * @returns a log4c_category object
  55. * @warning this method should not be called directly. You should use the
  56. * log4c_category_get() method in order to preserve the categories
  57. * hierarchy.
  58. **/
  59. LOG4C_API log4c_category_t* log4c_category_new(const char* a_name);
  60. /**
  61. * Destructor for a log4c_category_t.
  62. *
  63. * @param a_category the log4c_category_t object
  64. **/
  65. LOG4C_API void log4c_category_delete(log4c_category_t* a_category);
  66. /**
  67. * Return the category name.
  68. * @param a_category the log4c_category_t object
  69. * @returns the category name.
  70. */
  71. LOG4C_API const char* log4c_category_get_name(const log4c_category_t* a_category);
  72. /**
  73. * Returns the Appender for this log4c_category_t, or NULL if no Appender has
  74. * been set.
  75. * @param a_category the log4c_category_t object
  76. * @returns The Appender.
  77. **/
  78. LOG4C_API const struct __log4c_appender* log4c_category_get_appender(
  79. const log4c_category_t* a_category);
  80. /**
  81. * Get the additivity flag for this log4c_category_t..
  82. *
  83. * @param a_category the log4c_category_t object
  84. * @return the category additivity
  85. **/
  86. LOG4C_API int log4c_category_get_additivity(const log4c_category_t* a_category);
  87. /**
  88. * Returns the assigned Priority, if any, for this log4c_category_t.
  89. * @param a_category the log4c_category_t object
  90. * @return Priority - the assigned Priority, can be LOG4C_PRIORITY_NOTSET
  91. **/
  92. LOG4C_API int log4c_category_get_priority(const log4c_category_t* a_category);
  93. /**
  94. * Starting from this category, search the category hierarchy for a set
  95. * priority and return it. Otherwise, return the priority of the root
  96. * category.
  97. *
  98. * @param a_category the log4c_category_t object
  99. *
  100. * @todo the log4c_category_t is designed so that this method executes as
  101. * quickly as possible. It could even be faster if the set priority was
  102. * propagated through the children hierarchy of a category.
  103. **/
  104. LOG4C_API int log4c_category_get_chainedpriority(const log4c_category_t* a_category);
  105. /**
  106. * Sets a new appender for this category.
  107. *
  108. * @param a_category the log4c_category_t object
  109. * @param a_appender the new category appender
  110. * @return the previous category appender
  111. **/
  112. LOG4C_API const struct __log4c_appender* log4c_category_set_appender(
  113. log4c_category_t* a_category,
  114. struct __log4c_appender* a_appender);
  115. /**
  116. * Sets a new priority of this category.
  117. *
  118. * @param a_category the log4c_category_t object
  119. * @param a_priority the new priority to set. Use LOG4C_PRIORITY_NOTSET to
  120. * let the category use its parents priority as effective priority.
  121. * @return the previous category priority
  122. **/
  123. LOG4C_API int log4c_category_set_priority(log4c_category_t* a_category,
  124. int a_priority);
  125. /**
  126. * Sets a new additivity flag for this category.
  127. *
  128. * @param a_category the log4c_category_t object
  129. * @param a_additivity the new category additivity
  130. * @return the previous category additivity
  131. **/
  132. LOG4C_API int log4c_category_set_additivity(log4c_category_t* a_category,
  133. int a_additivity);
  134. /**
  135. * prints the log4c_category_t object on a stream
  136. *
  137. * @param a_category the log4c_category_t object
  138. * @param a_stream The stream
  139. **/
  140. LOG4C_API void log4c_category_print(const log4c_category_t* a_category, FILE* a_stream);
  141. /**
  142. * Returns true if the chained priority of the log4c_category_t is equal to
  143. * or higher than given priority.
  144. * @param a_category the log4c_category_t object
  145. * @param a_priority The priority to compare with.
  146. * @returns whether logging is enable for this priority.
  147. **/
  148. #if !defined(_WIN32) && !defined(__HP_cc)
  149. static inline int log4c_category_is_priority_enabled(const log4c_category_t* a_category,
  150. int a_priority)
  151. {
  152. return log4c_category_get_chainedpriority(a_category) >= a_priority;
  153. }
  154. #else
  155. #define log4c_category_is_priority_enabled(a,b) \
  156. (log4c_category_get_chainedpriority(a) >= b)
  157. #endif
  158. /**
  159. * Return true if the category will log messages with priority @c
  160. * LOG4C_PRIORITY_FATAL.
  161. *
  162. * @param a_category the log4c_category_t object
  163. * @returns Whether the category will log.
  164. **/
  165. #if !defined(_WIN32) && !defined(__HP_cc)
  166. static inline int log4c_category_is_fatal_enabled(const log4c_category_t* a_category)
  167. {
  168. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_FATAL);
  169. }
  170. #else
  171. #define log4c_category_is_fatal_enabled(a) \
  172. (log4c_category_is_priority_enabled(a,LOG4C_PRIORITY_FATAL))
  173. #endif
  174. /**
  175. * Return true if the category will log messages with priority @c
  176. * LOG4C_PRIORITY_ALERT.
  177. *
  178. * @param a_category the log4c_category_t object
  179. * @returns Whether the category will log.
  180. **/
  181. #if !defined(_WIN32) && !defined(__HP_cc)
  182. static inline int log4c_category_is_alert_enabled(const log4c_category_t* a_category)
  183. {
  184. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_ALERT);
  185. }
  186. #else
  187. #define log4c_category_is_alert_enabled(a) \
  188. (log4c_category_is_priority_enabled(a,LOG4C_PRIORITY_ALERT))
  189. #endif
  190. /**
  191. * Return true if the category will log messages with priority @c
  192. * LOG4C_PRIORITY_CRIT.
  193. *
  194. * @param a_category the log4c_category_t object
  195. * @returns Whether the category will log.
  196. **/
  197. #if !defined(_WIN32) && !defined(__HP_cc)
  198. static inline int log4c_category_is_crit_enabled(const log4c_category_t* a_category)
  199. {
  200. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_CRIT);
  201. }
  202. #else
  203. #define log4c_category_is_crit_enabled(a) \
  204. (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_CRIT))
  205. #endif
  206. /**
  207. * Return true if the category will log messages with priority @c
  208. * LOG4C_PRIORITY_ERROR.
  209. *
  210. * @param a_category the log4c_category_t object
  211. * @returns Whether the category will log.
  212. **/
  213. #if !defined(_WIN32) && !defined(__HP_cc)
  214. static inline int log4c_category_is_error_enabled(const log4c_category_t* a_category)
  215. {
  216. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_ERROR);
  217. }
  218. #else
  219. #define log4c_category_is_error_enabled(a) \
  220. (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_ERROR))
  221. #endif
  222. /**
  223. * Return true if the category will log messages with priority @c
  224. * LOG4C_PRIORITY_WARN.
  225. *
  226. * @param a_category the log4c_category_t object
  227. * @returns Whether the category will log.
  228. **/
  229. #if !defined(_WIN32) && !defined(__HP_cc)
  230. static inline int log4c_category_is_warn_enabled(const log4c_category_t* a_category)
  231. {
  232. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_WARN);
  233. }
  234. #else
  235. #define log4c_category_is_warn_enabled(a) \
  236. log4c_category_is_warn_enabled(a) \
  237. (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_WARN))
  238. #endif
  239. /**
  240. * Return true if the category will log messages with priority @c
  241. * LOG4C_PRIORITY_NOTICE.
  242. *
  243. * @param a_category the log4c_category_t object
  244. * @returns Whether the category will log.
  245. **/
  246. #if !defined(_WIN32) && !defined(__HP_cc)
  247. static inline int log4c_category_is_notice_enabled(const log4c_category_t* a_category)
  248. {
  249. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_NOTICE);
  250. }
  251. #else
  252. #define log4c_category_is_notice_enabled(a) \
  253. (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_NOTICE))
  254. #endif
  255. /**
  256. * Return true if the category will log messages with priority @c
  257. * LOG4C_PRIORITY_INFO.
  258. *
  259. * @param a_category the log4c_category_t object
  260. * @returns Whether the category will log.
  261. **/
  262. #if !defined(_WIN32) && !defined(__HP_cc)
  263. static inline int log4c_category_is_info_enabled(const log4c_category_t* a_category)
  264. {
  265. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_INFO);
  266. }
  267. #else
  268. #define log4c_category_is_info_enabled(a) \
  269. (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_INFO))
  270. #endif
  271. /**
  272. * Return true if the category will log messages with priority @c
  273. * LOG4C_PRIORITY_DEBUG.
  274. *
  275. * @param a_category the log4c_category_t object
  276. * @returns Whether the category will log.
  277. **/
  278. #if !defined(_WIN32) && !defined(__HP_cc)
  279. static inline int log4c_category_is_debug_enabled(const log4c_category_t* a_category)
  280. {
  281. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_DEBUG);
  282. }
  283. #else
  284. #define log4c_category_is_debug_enabled(a) \
  285. (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_DEBUG))
  286. #endif
  287. /**
  288. * Return true if the category will log messages with priority @c
  289. * LOG4C_PRIORITY_TRACE.
  290. *
  291. * @param a_category the log4c_category_t object
  292. * @returns Whether the category will log.
  293. **/
  294. #if !defined(_WIN32) && !defined(__HP_cc)
  295. static inline int log4c_category_is_trace_enabled(const log4c_category_t* a_category)
  296. {
  297. return log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_TRACE);
  298. }
  299. #else
  300. #define log4c_category_is_trace_enabled(a) \
  301. (log4c_category_is_priority_enabled(a, LOG4C_PRIORITY_TRACE))
  302. #endif
  303. /**
  304. * @internal
  305. **/
  306. LOG4C_API void __log4c_category_vlog(const log4c_category_t* a_category,
  307. const log4c_location_info_t* a_locinfo,
  308. int a_priority,
  309. const char* a_format,
  310. va_list a_args);
  311. /**
  312. * @internal
  313. **/
  314. LOG4C_API void __log4c_category_vlog_no_file_num_no_layout(
  315. const log4c_category_t* a_category,
  316. const log4c_location_info_t* a_locinfo,
  317. int a_priority,
  318. const char* a_format,
  319. va_list a_args);
  320. /**
  321. * @internal
  322. *
  323. * @bug the log4c_location_info_t object is not set correctly. A macro is
  324. * needed.
  325. **/
  326. /* msvc doesn't allow "inline" nor variable args in a macro
  327. * so cannot #define these ones.
  328. */
  329. static LOG4C_INLINE void log4c_category_vlog(const log4c_category_t* a_category,
  330. int a_priority,
  331. const char* a_format,
  332. va_list a_args)
  333. {
  334. const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL);
  335. __log4c_category_vlog(a_category, &locinfo, a_priority, a_format, a_args);
  336. }
  337. /**
  338. * @internal
  339. *
  340. * @bug the log4c_location_info_t object is not set correctly. A macro is
  341. * needed.
  342. **/
  343. /* msvc doesn't allow "inline" nor variable args in a macro
  344. * so cannot #define these ones.
  345. */
  346. static LOG4C_INLINE void log4c_category_vlog_no_file_num_no_layout(const log4c_category_t* a_category,
  347. int a_priority,
  348. const char* a_format,
  349. va_list a_args)
  350. {
  351. const log4c_location_info_t locinfo = LOG4C_LOCATION_INFO_INITIALIZER(NULL);
  352. __log4c_category_vlog_no_file_num_no_layout(a_category, &locinfo, a_priority, a_format, a_args);
  353. }
  354. /**
  355. * Log a message with the specified priority.
  356. * @param a_category the log4c_category_t object
  357. * @param a_priority The priority of this log message.
  358. * @param a_format Format specifier for the string to write
  359. * in the log file.
  360. * @param ... The arguments for a_format
  361. **/
  362. static LOG4C_INLINE void log4c_category_log(const log4c_category_t* a_category,
  363. int a_priority,
  364. const char* a_format,
  365. ...)
  366. {
  367. if (log4c_category_is_priority_enabled(a_category, a_priority)) {
  368. va_list va;
  369. va_start(va, a_format);
  370. log4c_category_vlog(a_category, a_priority, a_format, va);
  371. va_end(va);
  372. }
  373. }
  374. /**
  375. * Log a message with the specified priority and a user location info.
  376. * @param a_category the log4c_category_t object
  377. * @param a_locinfo a user location info
  378. * @param a_priority The priority of this log message.
  379. * @param a_format Format specifier for the string to write
  380. * in the log file.
  381. * @param ... The arguments for a_format
  382. **/
  383. static LOG4C_INLINE void log4c_category_log_locinfo(
  384. const log4c_category_t* a_category,
  385. const log4c_location_info_t* a_locinfo,
  386. int a_priority,
  387. const char* a_format,
  388. ...)
  389. {
  390. if (log4c_category_is_priority_enabled(a_category, a_priority)) {
  391. va_list va;
  392. va_start(va, a_format);
  393. __log4c_category_vlog(a_category, a_locinfo, a_priority, a_format, va);
  394. va_end(va);
  395. }
  396. }
  397. /**
  398. * Log a message with fatal priority.
  399. * @param a_category the log4c_category_t object
  400. * @param a_format Format specifier for the string to write
  401. * in the log file.
  402. * @param ... The arguments for a_format
  403. **/
  404. static LOG4C_INLINE void log4c_category_fatal(const log4c_category_t* a_category,
  405. const char* a_format,
  406. ...)
  407. {
  408. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_FATAL)) {
  409. va_list va;
  410. va_start(va, a_format);
  411. log4c_category_vlog(a_category, LOG4C_PRIORITY_FATAL, a_format, va);
  412. va_end(va);
  413. }
  414. }
  415. /**
  416. * Log a message with alert priority.
  417. * @param a_category the log4c_category_t object
  418. * @param a_format Format specifier for the string to write
  419. * in the log file.
  420. * @param ... The arguments for a_format
  421. **/
  422. static LOG4C_INLINE void log4c_category_alert(const log4c_category_t* a_category,
  423. const char* a_format,
  424. ...)
  425. {
  426. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_ALERT)) {
  427. va_list va;
  428. va_start(va, a_format);
  429. log4c_category_vlog(a_category, LOG4C_PRIORITY_ALERT, a_format, va);
  430. va_end(va);
  431. }
  432. }
  433. /**
  434. * Log a message with crit priority.
  435. * @param a_category the log4c_category_t object
  436. * @param a_format Format specifier for the string to write
  437. * in the log file.
  438. * @param ... The arguments for a_format
  439. **/
  440. static LOG4C_INLINE void log4c_category_crit(const log4c_category_t* a_category,
  441. const char* a_format,
  442. ...)
  443. {
  444. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_CRIT)) {
  445. va_list va;
  446. va_start(va, a_format);
  447. log4c_category_vlog(a_category, LOG4C_PRIORITY_CRIT, a_format, va);
  448. va_end(va);
  449. }
  450. }
  451. /**
  452. * Log a message with error priority.
  453. * @param a_category the log4c_category_t object
  454. * @param a_format Format specifier for the string to write
  455. * in the log file.
  456. * @param ... The arguments for a_format
  457. **/
  458. static LOG4C_INLINE void log4c_category_error(const log4c_category_t* a_category,
  459. const char* a_format,
  460. ...)
  461. {
  462. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_ERROR)) {
  463. va_list va;
  464. va_start(va, a_format);
  465. log4c_category_vlog(a_category, LOG4C_PRIORITY_ERROR, a_format, va);
  466. va_end(va);
  467. }
  468. }
  469. /**
  470. * Log a message with warn priority.
  471. * @param a_category the log4c_category_t object
  472. * @param a_format Format specifier for the string to write
  473. * in the log file.
  474. * @param ... The arguments for a_format
  475. **/
  476. static LOG4C_INLINE void log4c_category_warn(const log4c_category_t* a_category,
  477. const char* a_format,
  478. ...)
  479. {
  480. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_WARN)) {
  481. va_list va;
  482. va_start(va, a_format);
  483. log4c_category_vlog(a_category, LOG4C_PRIORITY_WARN, a_format, va);
  484. va_end(va);
  485. }
  486. }
  487. /**
  488. * Log a message with notice priority.
  489. * @param a_category the log4c_category_t object
  490. * @param a_format Format specifier for the string to write
  491. * in the log file.
  492. * @param ... The arguments for a_format
  493. **/
  494. static LOG4C_INLINE void log4c_category_notice(const log4c_category_t* a_category,
  495. const char* a_format,
  496. ...)
  497. {
  498. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_NOTICE)) {
  499. va_list va;
  500. va_start(va, a_format);
  501. log4c_category_vlog(a_category, LOG4C_PRIORITY_NOTICE, a_format, va);
  502. va_end(va);
  503. }
  504. }
  505. /**
  506. * Log a message with info priority.
  507. * @param a_category the log4c_category_t object
  508. * @param a_format Format specifier for the string to write
  509. * in the log file.
  510. * @param ... The arguments for a_format
  511. **/
  512. static LOG4C_INLINE void log4c_category_info(const log4c_category_t* a_category,
  513. const char* a_format,
  514. ...)
  515. {
  516. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_INFO)) {
  517. va_list va;
  518. va_start(va, a_format);
  519. log4c_category_vlog(a_category, LOG4C_PRIORITY_INFO, a_format, va);
  520. va_end(va);
  521. }
  522. }
  523. /**
  524. * Log a message with debug priority.
  525. * @param a_category the log4c_category_t object
  526. * @param a_format Format specifier for the string to write
  527. * in the log file.
  528. * @param ... The arguments for a_format
  529. **/
  530. static LOG4C_INLINE void log4c_category_debug(const log4c_category_t* a_category,
  531. const char* a_format,
  532. ...)
  533. {
  534. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_DEBUG)) {
  535. va_list va;
  536. va_start(va, a_format);
  537. log4c_category_vlog(a_category, LOG4C_PRIORITY_DEBUG, a_format, va);
  538. va_end(va);
  539. }
  540. }
  541. /**
  542. * Log a message with trace priority.
  543. * @param a_category the log4c_category_t object
  544. * @param a_format Format specifier for the string to write
  545. * in the log file.
  546. * @param ... The arguments for a_format
  547. **/
  548. static LOG4C_INLINE void __log4c_category_trace(const log4c_category_t* a_category,
  549. const char* a_format,
  550. ...)
  551. {
  552. if (log4c_category_is_priority_enabled(a_category, LOG4C_PRIORITY_TRACE)) {
  553. va_list va;
  554. va_start(va, a_format);
  555. log4c_category_vlog(a_category, LOG4C_PRIORITY_TRACE, a_format, va);
  556. va_end(va);
  557. }
  558. }
  559. #ifdef __GNUC__
  560. #ifdef OLD_VARIADIC_MACRO
  561. # define log4c_category_trace(a_category, a_format, args...) \
  562. __log4c_category_trace(a_category, log4c_location "\n" a_format, ##args )
  563. #else
  564. # define log4c_category_trace(a_category, a_format, ...) \
  565. __log4c_category_trace(a_category, log4c_location "\n" a_format, ##__VA_ARGS__ )
  566. #endif /* OLD_VARIADIC_MACRO */
  567. #else
  568. # define log4c_category_trace __log4c_category_trace
  569. #endif /* __GNUC__ */
  570. /**
  571. * Helper macro to define static categories.
  572. *
  573. * @param a_category the log4c_category_t pointer name
  574. * @param a_name the category name
  575. **/
  576. #ifdef __GNUC__
  577. # define log4c_category_define(a_category, a_name) \
  578. typedef log4c_category_t log4c_category_define_##a_category __attribute__((deprecated)); \
  579. static log4c_category_define_##a_category* a_category __attribute__ ((unused)) = NULL;
  580. #else
  581. # define log4c_category_define(a_category, a_name)
  582. #endif
  583. /**
  584. * @internal
  585. **/
  586. struct __sd_factory;
  587. LOG4C_API struct __sd_factory* log4c_category_factory;
  588. __LOG4C_END_DECLS
  589. #endif