Avoid signed overflow and use size_t in bytevectors.c.
[bpt/guile.git] / libguile / procprop.c
CommitLineData
fe2400c9
LC
1/* Copyright (C) 1995, 1996, 1998, 2000, 2001, 2003, 2004, 2006,
2 * 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
0f2d19dd 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
0f2d19dd 13 *
73be1d9e
MV
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
1bbd0b84 19
1bbd0b84 20
0f2d19dd 21\f
dbb605f5
LC
22#ifdef HAVE_CONFIG_H
23# include <config.h>
24#endif
0f2d19dd 25
3fc7e2c1
AW
26#define SCM_BUILDING_DEPRECATED_CODE
27
a0599745
MD
28#include "libguile/_scm.h"
29
30#include "libguile/alist.h"
3fc7e2c1
AW
31#include "libguile/deprecation.h"
32#include "libguile/deprecated.h"
a0599745
MD
33#include "libguile/eval.h"
34#include "libguile/procs.h"
35#include "libguile/gsubr.h"
5540e847 36#include "libguile/smob.h"
a0599745
MD
37#include "libguile/root.h"
38#include "libguile/vectors.h"
82c76fd3 39#include "libguile/hashtab.h"
2fb924f6 40#include "libguile/programs.h"
a0599745
MD
41
42#include "libguile/validate.h"
43#include "libguile/procprop.h"
0f2d19dd
JB
44\f
45
c083a529 46SCM_GLOBAL_SYMBOL (scm_sym_system_procedure, "system-procedure");
3fc7e2c1 47#if (SCM_ENABLE_DEPRECATED == 1)
67e60655 48SCM_GLOBAL_SYMBOL (scm_sym_arity, "arity");
3fc7e2c1 49#endif
fd12a19a 50SCM_GLOBAL_SYMBOL (scm_sym_name, "name");
67e60655 51
e1bdf9e2
AW
52static SCM overrides;
53static scm_i_pthread_mutex_t overrides_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
56164a5a 54
f3cf9421
AW
55static SCM arity_overrides;
56
314b8716
AW
57int
58scm_i_procedure_arity (SCM proc, int *req, int *opt, int *rest)
67e60655 59{
f3cf9421
AW
60 SCM o;
61
62 scm_i_pthread_mutex_lock (&overrides_lock);
63 o = scm_hashq_ref (arity_overrides, proc, SCM_BOOL_F);
64 scm_i_pthread_mutex_unlock (&overrides_lock);
65
66 if (scm_is_true (o))
67 {
68 *req = scm_to_int (scm_car (o));
69 *opt = scm_to_int (scm_cadr (o));
70 *rest = scm_is_true (scm_caddr (o));
71 return 1;
72 }
73
75c3ed28 74 while (!SCM_PROGRAM_P (proc))
67e60655 75 {
75c3ed28 76 if (SCM_IMP (proc))
314b8716 77 return 0;
75c3ed28
AW
78 switch (SCM_TYP7 (proc))
79 {
80 case scm_tc7_smob:
81 if (!SCM_SMOB_APPLICABLE_P (proc))
82 return 0;
c05805a4
AW
83 if (!scm_i_program_arity
84 (SCM_SMOB_DESCRIPTOR (proc).apply_trampoline_objcode,
85 req, opt, rest))
86 return 0;
87
88 /* The trampoline gets the smob too, which users don't
89 see. */
90 *req -= 1;
91
92 return 1;
75c3ed28
AW
93 case scm_tcs_struct:
94 if (!SCM_STRUCT_APPLICABLE_P (proc))
95 return 0;
96 proc = SCM_STRUCT_PROCEDURE (proc);
97 break;
98 default:
99 return 0;
100 }
67e60655 101 }
f3cf9421 102
75c3ed28 103 return scm_i_program_arity (proc, req, opt, rest);
67e60655
MD
104}
105
f3cf9421
AW
106SCM_DEFINE (scm_set_procedure_minimum_arity_x, "set-procedure-minimum-arity!",
107 4, 0, 0, (SCM proc, SCM req, SCM opt, SCM rest),
108 "")
109#define FUNC_NAME s_scm_set_procedure_minimum_arity_x
110{
111 int t SCM_UNUSED;
112
113 SCM_VALIDATE_PROC (1, proc);
114 SCM_VALIDATE_INT_COPY (2, req, t);
115 SCM_VALIDATE_INT_COPY (3, opt, t);
116 SCM_VALIDATE_BOOL (4, rest);
117
118 scm_i_pthread_mutex_lock (&overrides_lock);
119 scm_hashq_set_x (arity_overrides, proc, scm_list_3 (req, opt, rest));
120 scm_i_pthread_mutex_unlock (&overrides_lock);
121 return SCM_UNDEFINED;
122}
123#undef FUNC_NAME
124
cb2ce548
AW
125SCM_DEFINE (scm_procedure_minimum_arity, "procedure-minimum-arity", 1, 0, 0,
126 (SCM proc),
127 "Return the \"minimum arity\" of a procedure.\n\n"
128 "If the procedure has only one arity, that arity is returned\n"
129 "as a list of three values: the number of required arguments,\n"
130 "the number of optional arguments, and a boolean indicating\n"
131 "whether or not the procedure takes rest arguments.\n\n"
132 "For a case-lambda procedure, the arity returned is the one\n"
133 "with the lowest minimum number of arguments, and the highest\n"
134 "maximum number of arguments.\n\n"
135 "If it was not possible to determine the arity of the procedure,\n"
136 "@code{#f} is returned.")
137#define FUNC_NAME s_scm_procedure_minimum_arity
138{
139 int req, opt, rest;
140
141 if (scm_i_procedure_arity (proc, &req, &opt, &rest))
142 return scm_list_3 (scm_from_int (req),
143 scm_from_int (opt),
144 scm_from_bool (rest));
145 else
146 return SCM_BOOL_F;
147}
148#undef FUNC_NAME
149
3b3b36dd 150SCM_DEFINE (scm_procedure_properties, "procedure-properties", 1, 0, 0,
1bbd0b84 151 (SCM proc),
b7e64f8b 152 "Return @var{proc}'s property list.")
1bbd0b84 153#define FUNC_NAME s_scm_procedure_properties
0f2d19dd 154{
314b8716 155 SCM ret;
56164a5a 156
34d19ef6 157 SCM_VALIDATE_PROC (1, proc);
314b8716 158
e1bdf9e2
AW
159 scm_i_pthread_mutex_lock (&overrides_lock);
160 ret = scm_hashq_ref (overrides, proc, SCM_BOOL_F);
161 scm_i_pthread_mutex_unlock (&overrides_lock);
314b8716 162
e1bdf9e2
AW
163 if (scm_is_false (ret))
164 {
165 if (SCM_PROGRAM_P (proc))
07e424b7 166 ret = scm_i_program_properties (proc);
e1bdf9e2
AW
167 else
168 ret = SCM_EOL;
169 }
170
3fc7e2c1
AW
171#if (SCM_ENABLE_DEPRECATED == 1)
172 ret = scm_acons (scm_sym_arity, scm_procedure_minimum_arity (proc), ret);
173#endif
314b8716 174
3fc7e2c1 175 return ret;
0f2d19dd 176}
1bbd0b84 177#undef FUNC_NAME
0f2d19dd 178
3b3b36dd 179SCM_DEFINE (scm_set_procedure_properties_x, "set-procedure-properties!", 2, 0, 0,
56164a5a
AW
180 (SCM proc, SCM alist),
181 "Set @var{proc}'s property list to @var{alist}.")
1bbd0b84 182#define FUNC_NAME s_scm_set_procedure_properties_x
0f2d19dd 183{
56164a5a
AW
184 SCM_VALIDATE_PROC (1, proc);
185
3fc7e2c1 186#if (SCM_ENABLE_DEPRECATED == 1)
fe2400c9 187 if (scm_is_true (scm_assq (scm_sym_arity, alist)))
e1bdf9e2 188 SCM_MISC_ERROR ("arity is a read-only property", SCM_EOL);
3fc7e2c1 189#endif
e1bdf9e2
AW
190
191 scm_i_pthread_mutex_lock (&overrides_lock);
192 scm_hashq_set_x (overrides, proc, alist);
193 scm_i_pthread_mutex_unlock (&overrides_lock);
314b8716 194
0f2d19dd
JB
195 return SCM_UNSPECIFIED;
196}
1bbd0b84 197#undef FUNC_NAME
0f2d19dd 198
3b3b36dd 199SCM_DEFINE (scm_procedure_property, "procedure-property", 2, 0, 0,
56164a5a
AW
200 (SCM proc, SCM key),
201 "Return the property of @var{proc} with name @var{key}.")
1bbd0b84 202#define FUNC_NAME s_scm_procedure_property
0f2d19dd 203{
56164a5a
AW
204 SCM_VALIDATE_PROC (1, proc);
205
3fc7e2c1 206#if (SCM_ENABLE_DEPRECATED == 1)
56164a5a 207 if (scm_is_eq (key, scm_sym_arity))
3fc7e2c1
AW
208 scm_c_issue_deprecation_warning
209 ("Accessing a procedure's arity via `procedure-property' is deprecated.\n"
210 "Use `procedure-minimum-arity instead.");
211#endif
212
213 return scm_assq_ref (scm_procedure_properties (proc), key);
0f2d19dd 214}
1bbd0b84 215#undef FUNC_NAME
0f2d19dd 216
3b3b36dd 217SCM_DEFINE (scm_set_procedure_property_x, "set-procedure-property!", 3, 0, 0,
56164a5a
AW
218 (SCM proc, SCM key, SCM val),
219 "In @var{proc}'s property list, set the property named @var{key} to\n"
220 "@var{val}.")
1bbd0b84 221#define FUNC_NAME s_scm_set_procedure_property_x
0f2d19dd 222{
90fa152c 223 SCM props;
56164a5a 224
e1bdf9e2 225 SCM_VALIDATE_PROC (1, proc);
3fc7e2c1
AW
226
227#if (SCM_ENABLE_DEPRECATED == 1)
56164a5a 228 if (scm_is_eq (key, scm_sym_arity))
3fc7e2c1
AW
229 SCM_MISC_ERROR ("arity is a deprecated read-only property", SCM_EOL);
230#endif
c783b082 231
8571dbde
MW
232 scm_dynwind_begin (0);
233 /* Here we must block asyncs while overrides_lock is held, to avoid
234 deadlocks which can happen as follows: scm_i_program_properties
235 calls out to the VM, which will run asyncs. Asyncs are permitted
236 to run VM code, which sometimes checks procedure properties, which
237 locks overrides_lock. */
238 scm_i_dynwind_pthread_mutex_lock_block_asyncs (&overrides_lock);
f2ed4473
AW
239 props = scm_hashq_ref (overrides, proc, SCM_BOOL_F);
240 if (scm_is_false (props))
241 {
242 if (SCM_PROGRAM_P (proc))
243 props = scm_i_program_properties (proc);
244 else
245 props = SCM_EOL;
246 }
90fa152c 247 scm_hashq_set_x (overrides, proc, scm_assq_set_x (props, key, val));
8571dbde 248 scm_dynwind_end ();
c783b082 249
0f2d19dd
JB
250 return SCM_UNSPECIFIED;
251}
1bbd0b84 252#undef FUNC_NAME
0f2d19dd
JB
253
254\f
255
1cc91f1b 256
0f2d19dd
JB
257void
258scm_init_procprop ()
0f2d19dd 259{
e1bdf9e2 260 overrides = scm_make_weak_key_hash_table (SCM_UNDEFINED);
f3cf9421 261 arity_overrides = scm_make_weak_key_hash_table (SCM_UNDEFINED);
a0599745 262#include "libguile/procprop.x"
0f2d19dd
JB
263}
264
89e00824
ML
265
266/*
267 Local Variables:
268 c-file-style: "gnu"
269 End:
270*/