deprecation.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /* Copyright (C) 2001, 2006, 2010, 2011 Free Software Foundation, Inc.
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public License
  5. * as published by the Free Software Foundation; either version 3 of
  6. * the License, or (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. * 02110-1301 USA
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. # include <config.h>
  20. #endif
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdarg.h>
  24. #include "libguile/_scm.h"
  25. #include "libguile/deprecation.h"
  26. #include "libguile/strings.h"
  27. #include "libguile/ports.h"
  28. #include "libguile/private-options.h"
  29. struct issued_warning {
  30. struct issued_warning *prev;
  31. const char *message;
  32. };
  33. static scm_i_pthread_mutex_t warn_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
  34. static struct issued_warning *issued_warnings;
  35. static int print_summary = 0;
  36. void
  37. scm_c_issue_deprecation_warning (const char *msg)
  38. {
  39. if (!SCM_WARN_DEPRECATED)
  40. print_summary = 1;
  41. else
  42. {
  43. struct issued_warning *iw;
  44. scm_i_pthread_mutex_lock (&warn_lock);
  45. for (iw = issued_warnings; iw; iw = iw->prev)
  46. if (!strcmp (iw->message, msg))
  47. {
  48. msg = NULL;
  49. break;
  50. }
  51. if (msg)
  52. {
  53. msg = strdup (msg);
  54. iw = malloc (sizeof (struct issued_warning));
  55. if (msg == NULL || iw == NULL)
  56. /* Nothing sensible to do if you can't allocate this small
  57. amount of memory. */
  58. abort ();
  59. iw->message = msg;
  60. iw->prev = issued_warnings;
  61. issued_warnings = iw;
  62. }
  63. scm_i_pthread_mutex_unlock (&warn_lock);
  64. /* All this dance is to avoid printing to a port inside a mutex,
  65. which could recurse and deadlock. */
  66. if (msg)
  67. {
  68. if (scm_gc_running_p)
  69. fprintf (stderr, "%s\n", msg);
  70. else
  71. {
  72. scm_puts_unlocked (msg, scm_current_warning_port ());
  73. scm_newline (scm_current_warning_port ());
  74. }
  75. }
  76. }
  77. }
  78. void
  79. scm_c_issue_deprecation_warning_fmt (const char *msg, ...)
  80. {
  81. va_list ap;
  82. char buf[512];
  83. va_start (ap, msg);
  84. vsnprintf (buf, 511, msg, ap);
  85. va_end (ap);
  86. buf[511] = '\0';
  87. scm_c_issue_deprecation_warning (buf);
  88. }
  89. SCM_DEFINE(scm_issue_deprecation_warning,
  90. "issue-deprecation-warning", 0, 0, 1,
  91. (SCM msgs),
  92. "Output @var{msgs} to @code{(current-error-port)} when this "
  93. "is the first call to @code{issue-deprecation-warning} with "
  94. "this specific @var{msgs}. Do nothing otherwise. "
  95. "The argument @var{msgs} should be a list of strings; "
  96. "they are printed in turn, each one followed by a newline.")
  97. #define FUNC_NAME s_scm_issue_deprecation_warning
  98. {
  99. if (!SCM_WARN_DEPRECATED)
  100. print_summary = 1;
  101. else
  102. {
  103. SCM nl = scm_from_locale_string ("\n");
  104. SCM msgs_nl = SCM_EOL;
  105. char *c_msgs;
  106. while (scm_is_pair (msgs))
  107. {
  108. if (!scm_is_null (msgs_nl))
  109. msgs_nl = scm_cons (nl, msgs_nl);
  110. msgs_nl = scm_cons (SCM_CAR (msgs), msgs_nl);
  111. msgs = SCM_CDR (msgs);
  112. }
  113. msgs_nl = scm_string_append (scm_reverse_x (msgs_nl, SCM_EOL));
  114. c_msgs = scm_to_locale_string (msgs_nl);
  115. scm_c_issue_deprecation_warning (c_msgs);
  116. free (c_msgs);
  117. }
  118. return SCM_UNSPECIFIED;
  119. }
  120. #undef FUNC_NAME
  121. static void
  122. print_deprecation_summary (void)
  123. {
  124. if (print_summary)
  125. {
  126. fputs ("\n"
  127. "Some deprecated features have been used. Set the environment\n"
  128. "variable GUILE_WARN_DEPRECATED to \"detailed\" and rerun the\n"
  129. "program to get more information. Set it to \"no\" to suppress\n"
  130. "this message.\n", stderr);
  131. }
  132. }
  133. SCM_DEFINE(scm_include_deprecated_features,
  134. "include-deprecated-features", 0, 0, 0,
  135. (),
  136. "Return @code{#t} iff deprecated features should be included "
  137. "in public interfaces.")
  138. #define FUNC_NAME s_scm_include_deprecated_features
  139. {
  140. return scm_from_bool (SCM_ENABLE_DEPRECATED == 1);
  141. }
  142. #undef FUNC_NAME
  143. void
  144. scm_init_deprecation ()
  145. {
  146. const char *level = getenv ("GUILE_WARN_DEPRECATED");
  147. if (level == NULL)
  148. level = SCM_WARN_DEPRECATED_DEFAULT;
  149. if (!strcmp (level, "detailed"))
  150. SCM_WARN_DEPRECATED = 1;
  151. else if (!strcmp (level, "no"))
  152. SCM_WARN_DEPRECATED = 0;
  153. else
  154. {
  155. SCM_WARN_DEPRECATED = 0;
  156. atexit (print_deprecation_summary);
  157. }
  158. #include "libguile/deprecation.x"
  159. }
  160. /*
  161. Local Variables:
  162. c-file-style: "gnu"
  163. End:
  164. */