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