* Makefile.am (DEFS): Added. automake adds -I options to DEFS,
[bpt/guile.git] / libguile / feature.c
1 /* Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
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 /* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
45 \f
46
47 #include <stdio.h>
48 #include "libguile/_scm.h"
49
50 #include "libguile/eval.h"
51 #include "libguile/ports.h"
52 #include "libguile/procprop.h"
53 #include "libguile/root.h"
54 #include "libguile/smob.h"
55 #include "libguile/strings.h"
56
57 #include "libguile/validate.h"
58 #include "libguile/feature.h"
59
60 #ifdef HAVE_STRING_H
61 #include <string.h>
62 #endif
63 \f
64
65 static SCM *scm_loc_features;
66
67 void
68 scm_add_feature (const char *str)
69 {
70 *scm_loc_features = scm_cons (SCM_CAR (scm_intern (str, strlen (str))),
71 *scm_loc_features);
72 }
73
74
75 \f
76
77 SCM_DEFINE (scm_program_arguments, "program-arguments", 0, 0, 0,
78 (),
79 "")
80 #define FUNC_NAME s_scm_program_arguments
81 {
82 return scm_progargs;
83 }
84 #undef FUNC_NAME
85
86 /* Set the value returned by program-arguments, given ARGC and ARGV.
87
88 If FIRST is non-zero, make it the first element; we do this in
89 situations where other code (like getopt) has parsed out a few
90 arguments, but we still want the script name to be the first
91 element. */
92 void
93 scm_set_program_arguments (int argc, char **argv, char *first)
94 {
95 scm_progargs = scm_makfromstrs (argc, argv);
96 if (first)
97 scm_progargs = scm_cons (scm_makfrom0str (first), scm_progargs);
98 }
99
100
101 \f
102 /* Hooks
103 *
104 * A hook is basically a list of procedures to be called at well defined
105 * points in time.
106 *
107 * Hook name and arity are not full members of this type and therefore
108 * lack accessors. They are added to aid debugging and are not
109 * intended to be used in programs.
110 *
111 */
112
113 long scm_tc16_hook;
114
115
116 static SCM
117 make_hook (SCM name, SCM n_args, const char *subr)
118 {
119 int n;
120 SCM_ASSERT (SCM_FALSEP (name) || (SCM_SYMBOLP (name)),
121 name,
122 SCM_ARG1,
123 subr);
124 if (SCM_UNBNDP (n_args))
125 n = 0;
126 else
127 {
128 SCM_ASSERT (SCM_INUMP (n_args), n_args, SCM_ARGn, subr);
129 n = SCM_INUM (n_args);
130 }
131 SCM_ASSERT (n >= 0 && n <= 16, n_args, SCM_OUTOFRANGE, subr);
132 SCM_RETURN_NEWSMOB (scm_tc16_hook + (n << 16), SCM_UNPACK (SCM_LIST1 (name)));
133 }
134
135
136 static int
137 print_hook (SCM hook, SCM port, scm_print_state *pstate)
138 {
139 SCM ls, name;
140 scm_puts ("#<hook ", port);
141 if (SCM_NFALSEP (SCM_HOOK_NAME (hook)))
142 {
143 scm_iprin1 (SCM_HOOK_NAME (hook), port, pstate);
144 scm_putc (' ', port);
145 }
146 scm_intprint (SCM_HOOK_ARITY (hook), 10, port);
147 scm_putc (' ', port);
148 scm_intprint (SCM_UNPACK (hook), 16, port);
149 ls = SCM_HOOK_PROCEDURES (hook);
150 while (SCM_NIMP (ls))
151 {
152 scm_putc (' ', port);
153 name = scm_procedure_name (SCM_CAR (ls));
154 if (SCM_NFALSEP (name))
155 scm_iprin1 (name, port, pstate);
156 else
157 scm_putc ('?', port);
158 ls = SCM_CDR (ls);
159 }
160 scm_putc ('>', port);
161 return 1;
162 }
163
164
165 SCM
166 scm_create_hook (const char* name, int n_args)
167 {
168 SCM vcell = scm_sysintern0 (name);
169 SCM hook = make_hook (SCM_CAR (vcell), SCM_MAKINUM (n_args),
170 "scm_create_hook");
171 SCM_SETCDR (vcell, hook);
172 scm_protect_object (vcell);
173 return hook;
174 }
175
176
177 /* This function is deprecated. It will be removed in next release. */
178 SCM
179 scm_make_named_hook (const char* name, int n_args)
180 {
181 return scm_create_hook (name, n_args);
182 }
183
184
185 SCM_DEFINE (scm_make_hook_with_name, "make-hook-with-name", 1, 1, 0,
186 (SCM name, SCM n_args),
187 "")
188 #define FUNC_NAME s_scm_make_hook_with_name
189 {
190 return make_hook (name, n_args, FUNC_NAME);
191 }
192 #undef FUNC_NAME
193
194
195 SCM_DEFINE (scm_make_hook, "make-hook", 0, 1, 0,
196 (SCM n_args),
197 "")
198 #define FUNC_NAME s_scm_make_hook
199 {
200 return make_hook (SCM_BOOL_F, n_args, FUNC_NAME);
201 }
202 #undef FUNC_NAME
203
204
205 SCM_DEFINE (scm_hook_p, "hook?", 1, 0, 0,
206 (SCM x),
207 "")
208 #define FUNC_NAME s_scm_hook_p
209 {
210 return SCM_BOOL(SCM_HOOKP (x));
211 }
212 #undef FUNC_NAME
213
214
215 SCM_DEFINE (scm_hook_empty_p, "hook-empty?", 1, 0, 0,
216 (SCM hook),
217 "")
218 #define FUNC_NAME s_scm_hook_empty_p
219 {
220 SCM_VALIDATE_HOOK (1,hook);
221 return SCM_BOOL(SCM_NULLP (SCM_HOOK_PROCEDURES (hook)));
222 }
223 #undef FUNC_NAME
224
225
226 SCM_DEFINE (scm_add_hook_x, "add-hook!", 2, 1, 0,
227 (SCM hook, SCM proc, SCM append_p),
228 "")
229 #define FUNC_NAME s_scm_add_hook_x
230 {
231 SCM arity, rest;
232 int n_args;
233 SCM_VALIDATE_HOOK (1,hook);
234 SCM_ASSERT (SCM_NFALSEP (arity = scm_i_procedure_arity (proc)),
235 proc, SCM_ARG2, FUNC_NAME);
236 n_args = SCM_HOOK_ARITY (hook);
237 if (SCM_INUM (SCM_CAR (arity)) > n_args
238 || (SCM_FALSEP (SCM_CADDR (arity))
239 && (SCM_INUM (SCM_CAR (arity)) + SCM_INUM (SCM_CADR (arity))
240 < n_args)))
241 scm_wrong_type_arg (FUNC_NAME, 2, proc);
242 rest = scm_delq_x (proc, SCM_HOOK_PROCEDURES (hook));
243 SCM_SET_HOOK_PROCEDURES (hook,
244 (!SCM_UNBNDP (append_p) && SCM_NFALSEP (append_p)
245 ? scm_append_x (SCM_LIST2 (rest, SCM_LIST1 (proc)))
246 : scm_cons (proc, rest)));
247 return SCM_UNSPECIFIED;
248 }
249 #undef FUNC_NAME
250
251
252 SCM_DEFINE (scm_remove_hook_x, "remove-hook!", 2, 0, 0,
253 (SCM hook, SCM proc),
254 "")
255 #define FUNC_NAME s_scm_remove_hook_x
256 {
257 SCM_VALIDATE_HOOK (1,hook);
258 SCM_SET_HOOK_PROCEDURES (hook,
259 scm_delq_x (proc, SCM_HOOK_PROCEDURES (hook)));
260 return SCM_UNSPECIFIED;
261 }
262 #undef FUNC_NAME
263
264
265 SCM_DEFINE (scm_reset_hook_x, "reset-hook!", 1, 0, 0,
266 (SCM hook),
267 "")
268 #define FUNC_NAME s_scm_reset_hook_x
269 {
270 SCM_VALIDATE_HOOK (1,hook);
271 SCM_SET_HOOK_PROCEDURES (hook, SCM_EOL);
272 return SCM_UNSPECIFIED;
273 }
274 #undef FUNC_NAME
275
276
277 SCM_DEFINE (scm_run_hook, "run-hook", 1, 0, 1,
278 (SCM hook, SCM args),
279 "")
280 #define FUNC_NAME s_scm_run_hook
281 {
282 SCM_VALIDATE_HOOK (1,hook);
283 if (SCM_UNBNDP (args))
284 args = SCM_EOL;
285 if (scm_ilength (args) != SCM_HOOK_ARITY (hook))
286 SCM_MISC_ERROR ("Hook ~S requires ~A arguments",
287 SCM_LIST2 (hook,SCM_MAKINUM (SCM_HOOK_ARITY (hook))));
288 scm_c_run_hook (hook, args);
289 return SCM_UNSPECIFIED;
290 }
291 #undef FUNC_NAME
292
293
294 void
295 scm_c_run_hook (SCM hook, SCM args)
296 {
297 SCM procs = SCM_HOOK_PROCEDURES (hook);
298 while (SCM_NIMP (procs))
299 {
300 scm_apply (SCM_CAR (procs), args, SCM_EOL);
301 procs = SCM_CDR (procs);
302 }
303 }
304
305
306 SCM_DEFINE (scm_hook_to_list, "hook->list", 1, 0, 0,
307 (SCM hook),
308 "")
309 #define FUNC_NAME s_scm_hook_to_list
310 {
311 SCM_VALIDATE_HOOK (1,hook);
312 return scm_list_copy (SCM_HOOK_PROCEDURES (hook));
313 }
314 #undef FUNC_NAME
315
316
317 \f
318
319 void
320 scm_init_feature()
321 {
322 scm_loc_features = SCM_CDRLOC (scm_sysintern ("*features*", SCM_EOL));
323 #ifdef SCM_RECKLESS
324 scm_add_feature("reckless");
325 #endif
326 #ifndef _Windows
327 scm_add_feature("system");
328 #endif
329 #ifdef vms
330 scm_add_feature(s_ed);
331 #endif
332 #ifdef SICP
333 scm_add_feature("sicp");
334 #endif
335 #ifndef GO32
336 scm_add_feature("char-ready?");
337 #endif
338 #ifndef CHEAP_CONTINUATIONS
339 scm_add_feature ("full-continuation");
340 #endif
341 #ifdef USE_THREADS
342 scm_add_feature ("threads");
343 #endif
344
345 scm_sysintern ("char-code-limit", SCM_MAKINUM (SCM_CHAR_CODE_LIMIT));
346
347 scm_tc16_hook = scm_make_smob_type ("hook", 0);
348 scm_set_smob_mark (scm_tc16_hook, scm_markcdr);
349 scm_set_smob_print (scm_tc16_hook, print_hook);
350
351 #include "libguile/feature.x"
352 }
353
354 /*
355 Local Variables:
356 c-file-style: "gnu"
357 End:
358 */