options.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /* Copyright (C) 1995, 1996, 1998, 2000, 2002 Free Software Foundation
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2, or (at your option)
  6. * any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; see the file COPYING. If not, write to
  15. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. * Boston, MA 02111-1307 USA
  17. *
  18. * As a special exception, the Free Software Foundation gives permission
  19. * for additional uses of the text contained in its release of GUILE.
  20. *
  21. * The exception is that, if you link the GUILE library with other files
  22. * to produce an executable, this does not by itself cause the
  23. * resulting executable to be covered by the GNU General Public License.
  24. * Your use of that executable is in no way restricted on account of
  25. * linking the GUILE library code into it.
  26. *
  27. * This exception does not however invalidate any other reasons why
  28. * the executable file might be covered by the GNU General Public License.
  29. *
  30. * This exception applies only to the code released by the
  31. * Free Software Foundation under the name GUILE. If you copy
  32. * code from other Free Software Foundation releases into a copy of
  33. * GUILE, as the General Public License permits, the exception does
  34. * not apply to the code that you add in this way. To avoid misleading
  35. * anyone as to the status of such modified files, you must delete
  36. * this exception notice from them.
  37. *
  38. * If you write modifications of your own for GUILE, it is your choice
  39. * whether to permit this exception to apply to your modifications.
  40. * If you do not wish that, delete this exception notice.
  41. *
  42. * The author can be reached at djurfeldt@nada.kth.se
  43. * Mikael Djurfeldt, SANS/NADA KTH, 10044 STOCKHOLM, SWEDEN */
  44. #include <stdio.h>
  45. #include "libguile/_scm.h"
  46. #include "libguile/strings.h"
  47. #include "libguile/options.h"
  48. /* {Run-time options}
  49. *
  50. * This is the basic interface for low-level configuration of the
  51. * Guile library. It is used for configuring the reader, evaluator,
  52. * printer and debugger.
  53. *
  54. * Motivation:
  55. *
  56. * 1. Altering option settings can have side effects.
  57. * 2. Option values can be stored in native format.
  58. * (Important for efficiency in, e. g., the evaluator.)
  59. * 3. Doesn't use up name space.
  60. * 4. Options can be naturally grouped => ease of use.
  61. */
  62. /* scm_options is the core of all options interface procedures.
  63. *
  64. * Some definitions:
  65. *
  66. * Run time options in Guile are arranged in groups. Each group
  67. * affects a certain aspect of the behaviour of the library.
  68. *
  69. * An "options interface procedure" manages one group of options. It
  70. * can be used to check or set options, or to get documentation for
  71. * all options of a group. The options interface procedure is not
  72. * intended to be called directly by the user. The user should
  73. * instead call
  74. *
  75. * (<group>-options)
  76. * (<group>-options 'help)
  77. * (<group>-options 'full)
  78. *
  79. * to display current option settings (The second version also
  80. * displays documentation. The third version also displays
  81. * information about programmer's options.), and
  82. *
  83. * (<group>-enable '<option-symbol>)
  84. * (<group>-disable '<option-symbol>)
  85. * (<group>-set! <option-symbol> <value>)
  86. * (<group>-options <option setting>)
  87. *
  88. * to alter the state of an option (The last version sets all
  89. * options according to <option setting>.) where <group> is the name
  90. * of the option group.
  91. *
  92. * An "option setting" represents the state of all low-level options
  93. * managed by one options interface procedure. It is a list of
  94. * single symbols and symbols followed by a value.
  95. *
  96. * For boolean options, the presence of the symbol of that option in
  97. * the option setting indicates a true value. If the symbol isn't a
  98. * member of the option setting this represents a false value.
  99. *
  100. * Other options are represented by a symbol followed by the value.
  101. *
  102. * If scm_options is called without arguments, the current option
  103. * setting is returned. If the argument is an option setting, options
  104. * are altered and the old setting is returned. If the argument isn't
  105. * a list, a list of sublists is returned, where each sublist contains
  106. * option name, value and documentation string.
  107. */
  108. SCM_SYMBOL (scm_yes_sym, "yes");
  109. SCM_SYMBOL (scm_no_sym, "no");
  110. static SCM protected_objects;
  111. SCM
  112. scm_options (SCM arg, scm_option options[], int n, const char *s)
  113. {
  114. int i, docp = (!SCM_UNBNDP (arg) && !SCM_NULLP (arg) && !SCM_CONSP (arg));
  115. /* Let `arg' GC protect the arguments */
  116. SCM new_mode = arg, ans = SCM_EOL, ls;
  117. for (i = 0; i < n; ++i)
  118. {
  119. ls = docp ? scm_cons ((SCM) options[i].doc, SCM_EOL) : ans;
  120. switch (options[i].type)
  121. {
  122. case SCM_OPTION_BOOLEAN:
  123. if (docp)
  124. ls = scm_cons ((int) options[i].val
  125. ? scm_yes_sym
  126. : scm_no_sym,
  127. ls);
  128. break;
  129. case SCM_OPTION_INTEGER:
  130. ls = scm_cons (SCM_MAKINUM ((int) options[i].val), ls);
  131. break;
  132. case SCM_OPTION_SCM:
  133. ls = scm_cons ((SCM) options[i].val, ls);
  134. }
  135. if (!((options[i].type == SCM_OPTION_BOOLEAN)
  136. && !docp
  137. && ! (int) options[i].val))
  138. ls = scm_cons ((SCM) options[i].name, ls);
  139. ans = docp ? scm_cons (ls, ans) : ls;
  140. }
  141. if (!(SCM_UNBNDP (new_mode) || docp))
  142. {
  143. unsigned long *flags;
  144. flags = (unsigned long *) scm_must_malloc (n * sizeof (unsigned long),
  145. "mode buffer");
  146. for (i = 0; i < n; ++i)
  147. if (options[i].type == SCM_OPTION_BOOLEAN)
  148. flags[i] = 0;
  149. else
  150. flags[i] = (unsigned long) options[i].val;
  151. while (SCM_NNULLP (new_mode))
  152. {
  153. SCM_ASSERT (SCM_CONSP (new_mode),
  154. new_mode,
  155. SCM_ARG1,
  156. s);
  157. for (i = 0; i < n; ++i)
  158. if (SCM_CAR (new_mode) == (SCM) options[i].name)
  159. switch (options[i].type)
  160. {
  161. case SCM_OPTION_BOOLEAN:
  162. flags[i] = 1;
  163. goto cont;
  164. case SCM_OPTION_INTEGER:
  165. new_mode = SCM_CDR (new_mode);
  166. SCM_ASSERT ( SCM_CONSP (new_mode)
  167. && SCM_INUMP (SCM_CAR (new_mode)),
  168. new_mode,
  169. SCM_ARG1,
  170. s);
  171. flags[i] = (unsigned long) SCM_INUM (SCM_CAR (new_mode));
  172. goto cont;
  173. case SCM_OPTION_SCM:
  174. new_mode = SCM_CDR (new_mode);
  175. flags[i] = SCM_UNPACK (SCM_CAR (new_mode));
  176. goto cont;
  177. }
  178. #ifndef SCM_RECKLESS
  179. scm_must_free ((char *) flags);
  180. scm_wta (SCM_CAR (new_mode), "Unknown mode flag", s);
  181. #endif
  182. cont:
  183. new_mode = SCM_CDR (new_mode);
  184. }
  185. for (i = 0; i < n; ++i)
  186. {
  187. /* scm_option doesn't know if its a long or an SCM */
  188. if (options[i].type == SCM_OPTION_SCM)
  189. SCM_SETCDR (protected_objects,
  190. scm_cons (SCM_PACK(flags[i]),
  191. scm_delq1_x (SCM_PACK(options[i].val),
  192. SCM_CDR (protected_objects))));
  193. options[i].val = flags[i];
  194. }
  195. scm_must_free ((char *) flags);
  196. }
  197. return ans;
  198. }
  199. void
  200. scm_init_opts (SCM (*func) (SCM), scm_option options[], int n)
  201. {
  202. int i;
  203. for (i = 0; i < n; ++i)
  204. {
  205. options[i].name = (char *) SCM_CAR (scm_sysintern0 (options[i].name));
  206. options[i].doc = (char *) scm_permanent_object (scm_take0str
  207. (options[i].doc));
  208. if (options[i].type == SCM_OPTION_SCM)
  209. SCM_SETCDR (protected_objects,
  210. scm_cons (SCM_PACK(options[i].val), SCM_CDR (protected_objects)));
  211. }
  212. func (SCM_UNDEFINED);
  213. }
  214. void
  215. scm_init_options ()
  216. {
  217. protected_objects = scm_permanent_object (scm_cons (SCM_UNDEFINED, SCM_EOL));
  218. #include "libguile/options.x"
  219. }
  220. /*
  221. Local Variables:
  222. c-file-style: "gnu"
  223. End:
  224. */