Mercurial > hg > xemacs-beta
comparison src/symbols.c @ 4502:8748a3f7ceb4
Handle varalias chains, custom variables in #'user-variable-p.
src/ChangeLog addition:
2008-08-23 Aidan Kehoe <kehoea@parhasard.net>
* eval.c (Fuser_variable_p): Moved to symbols.c
* symbols.c (Fcustom_variable_p): Moved here from custom.el.
(user_variable_alias_check_fun): Mapper function used in
`user-variable-p'.
(Fuser_variable_p): Moved here from eval.c, to allow it to examine
the variable alias chain. Expanded to check each entry in the
variable alias chain for signs of being a user variable;
documentation updated, noting the differences between GNU's
behaviour and ours (ours is a little more sensible)
(map_varalias_chain): New.
Given a C function, call it at least once for each symbol in a
symbol's varalias chain, signalling an error if there's a cycle,
and returning immediately if the function returns something other
than Qzero.
(Fdefvaralias): Correct the use of the word "alias" in the
docstring and in the argument name. Motivate this in a
comment. Add support for a DOCSTRING argument, something GNU has
too, and document this
* gc.c (vars_of_gc): Start the docstring of
`garbage-collection-messages' with an asterisk, to indicate that
it's a user variable.
lisp/ChangeLog addition:
2008-08-23 Aidan Kehoe <kehoea@parhasard.net>
* custom.el: Move #'custom-variable-p to C, since it's now called
from #'user-variable-p.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sat, 23 Aug 2008 16:38:51 +0200 |
parents | a2af1ff1761f |
children | af95657e0bfd |
comparison
equal
deleted
inserted
replaced
4501:c4fd85dd95bd | 4502:8748a3f7ceb4 |
---|---|
82 static Lisp_Object fetch_value_maybe_past_magic (Lisp_Object sym, | 82 static Lisp_Object fetch_value_maybe_past_magic (Lisp_Object sym, |
83 Lisp_Object follow_past_lisp_magic); | 83 Lisp_Object follow_past_lisp_magic); |
84 static Lisp_Object *value_slot_past_magic (Lisp_Object sym); | 84 static Lisp_Object *value_slot_past_magic (Lisp_Object sym); |
85 static Lisp_Object follow_varalias_pointers (Lisp_Object symbol, | 85 static Lisp_Object follow_varalias_pointers (Lisp_Object symbol, |
86 Lisp_Object follow_past_lisp_magic); | 86 Lisp_Object follow_past_lisp_magic); |
87 static Lisp_Object map_varalias_chain (Lisp_Object symbol, | |
88 Lisp_Object follow_past_lisp_magic, | |
89 Lisp_Object (*fn) (Lisp_Object arg)); | |
87 | 90 |
88 | 91 |
89 static Lisp_Object | 92 static Lisp_Object |
90 mark_symbol (Lisp_Object obj) | 93 mark_symbol (Lisp_Object obj) |
91 { | 94 { |
2752 if (NILP (after_set)) | 2755 if (NILP (after_set)) |
2753 return local_info > 0 ? Qt : Qnil; | 2756 return local_info > 0 ? Qt : Qnil; |
2754 else | 2757 else |
2755 return local_info != 0 ? Qt : Qnil; | 2758 return local_info != 0 ? Qt : Qnil; |
2756 } | 2759 } |
2760 | |
2761 DEFUN ("custom-variable-p", Fcustom_variable_p, 1, 1, 0, /* | |
2762 Return non-nil if SYMBOL names a custom variable. | |
2763 Does not follow the variable alias chain. | |
2764 */ | |
2765 (symbol)) | |
2766 { | |
2767 return (!(NILP (Fget(symbol, intern ("standard-value"), Qnil))) | |
2768 || !(NILP (Fget(symbol, intern ("custom-autoload"), Qnil)))) ? | |
2769 Qt: Qnil; | |
2770 } | |
2771 | |
2772 static Lisp_Object | |
2773 user_variable_alias_check_fun (Lisp_Object symbol) | |
2774 { | |
2775 Lisp_Object documentation = Fget (symbol, Qvariable_documentation, Qnil); | |
2776 | |
2777 if ((INTP (documentation) && XINT (documentation) < 0) || | |
2778 (STRINGP (documentation) && | |
2779 (string_byte (documentation, 0) == '*')) || | |
2780 /* If (STRING . INTEGER), a negative integer means a user variable. */ | |
2781 (CONSP (documentation) | |
2782 && STRINGP (XCAR (documentation)) | |
2783 && INTP (XCDR (documentation)) | |
2784 && XINT (XCDR (documentation)) < 0) || | |
2785 !NILP (Fcustom_variable_p (symbol))) | |
2786 { | |
2787 return make_int(1); | |
2788 } | |
2789 | |
2790 return Qzero; | |
2791 } | |
2792 | |
2793 DEFUN ("user-variable-p", Fuser_variable_p, 1, 1, 0, /* | |
2794 Return t if SYMBOL names a variable intended to be set and modified by users. | |
2795 \(The alternative is a variable used internally in a Lisp program.) | |
2796 A symbol names a user variable if | |
2797 \(1) the first character of its documentation is `*', or | |
2798 \(2) it is customizable (`custom-variable-p' gives t), or | |
2799 \(3) it names a variable alias that eventually resolves to another user variable. | |
2800 | |
2801 The GNU Emacs implementation of `user-variable-p' returns nil if there is a | |
2802 loop in the chain of symbols. Since this is indistinguishable from the case | |
2803 where a symbol names a non-user variable, XEmacs signals a | |
2804 `cyclic-variable-indirection' error instead; use `condition-case' to catch | |
2805 this error if you really want to avoid this. | |
2806 */ | |
2807 (symbol)) | |
2808 { | |
2809 Lisp_Object mapped; | |
2810 | |
2811 if (!SYMBOLP (symbol)) | |
2812 { | |
2813 return Qnil; | |
2814 } | |
2815 | |
2816 /* Called for its side-effects, we want it to signal if there's a loop. */ | |
2817 follow_varalias_pointers (symbol, Qt); | |
2818 | |
2819 /* Look through the various aliases. */ | |
2820 mapped = map_varalias_chain (symbol, Qt, user_variable_alias_check_fun); | |
2821 if (EQ (Qzero, mapped)) | |
2822 { | |
2823 return Qnil; | |
2824 } | |
2825 | |
2826 assert (make_int (1) == mapped); | |
2827 | |
2828 return Qt; | |
2829 } | |
2830 | |
2831 | |
2757 | 2832 |
2758 | 2833 |
2759 /* | 2834 /* |
2760 I've gone ahead and partially implemented this because it's | 2835 I've gone ahead and partially implemented this because it's |
2761 super-useful for dealing with the compatibility problems in supporting | 2836 super-useful for dealing with the compatibility problems in supporting |
3134 } | 3209 } |
3135 | 3210 |
3136 return hare; | 3211 return hare; |
3137 } | 3212 } |
3138 | 3213 |
3139 DEFUN ("defvaralias", Fdefvaralias, 2, 2, 0, /* | 3214 /* Map FN over the chain of variable aliases for SYMBOL. If FN returns |
3215 something other than Qzero for some link in the chain, return that | |
3216 immediately. Otherwise return Qzero (which is not a symbol). | |
3217 | |
3218 FN may be called twice on the same symbol if the varalias chain is | |
3219 cyclic. Prevent this by calling follow_varalias_pointers first for its | |
3220 side-effects. | |
3221 | |
3222 Signals a cyclic-variable-indirection error if a cyclic structure is | |
3223 detected. */ | |
3224 | |
3225 static Lisp_Object | |
3226 map_varalias_chain (Lisp_Object symbol, | |
3227 Lisp_Object follow_past_lisp_magic, | |
3228 Lisp_Object (*fn) (Lisp_Object arg)) | |
3229 { | |
3230 #define VARALIAS_INDIRECTION_SUSPICION_LENGTH 16 | |
3231 Lisp_Object tortoise, hare, val, res; | |
3232 int count; | |
3233 | |
3234 assert (fn); | |
3235 | |
3236 /* quick out just in case */ | |
3237 if (!SYMBOL_VALUE_MAGIC_P (XSYMBOL (symbol)->value)) | |
3238 { | |
3239 return (fn)(symbol); | |
3240 } | |
3241 | |
3242 /* Compare implementation of indirect_function(). */ | |
3243 for (hare = tortoise = symbol, count = 0; | |
3244 val = fetch_value_maybe_past_magic (hare, follow_past_lisp_magic), | |
3245 SYMBOL_VALUE_VARALIAS_P (val); | |
3246 hare = symbol_value_varalias_aliasee (XSYMBOL_VALUE_VARALIAS (val)), | |
3247 count++) | |
3248 { | |
3249 res = (fn) (hare); | |
3250 if (Qzero != res) | |
3251 { | |
3252 return res; | |
3253 } | |
3254 | |
3255 if (count < VARALIAS_INDIRECTION_SUSPICION_LENGTH) continue; | |
3256 | |
3257 if (count & 1) | |
3258 tortoise = symbol_value_varalias_aliasee | |
3259 (XSYMBOL_VALUE_VARALIAS (fetch_value_maybe_past_magic | |
3260 (tortoise, follow_past_lisp_magic))); | |
3261 if (EQ (hare, tortoise)) | |
3262 return Fsignal (Qcyclic_variable_indirection, list1 (symbol)); | |
3263 } | |
3264 | |
3265 return (fn) (hare); | |
3266 } | |
3267 | |
3268 /* | |
3269 | |
3270 OED entry, 2nd edition, IPA transliterated using Kirshenbaum: | |
3271 | |
3272 alias ('eIlI@s, '&lI@s), adv. and n. | |
3273 [...] | |
3274 B. n. (with pl. aliases.) | |
3275 1. Another name, an assumed name. | |
3276 1605 Camden Rem. (1614) 147 An Alias or double name cannot preiudice the honest. | |
3277 1831 Edin. Rev. LIII. 364 He has been assuming various aliases. | |
3278 1861 Macaulay Hist. Eng. V. 92 The monk who was sometimes called Harrison | |
3279 and sometimes went by the alias of Johnson. | |
3280 | |
3281 The alias is the fake name. Let's try to follow that usage in our | |
3282 documentation. | |
3283 | |
3284 */ | |
3285 | |
3286 DEFUN ("defvaralias", Fdefvaralias, 2, 3, 0, /* | |
3140 Define a variable as an alias for another variable. | 3287 Define a variable as an alias for another variable. |
3141 Thenceforth, any operations performed on VARIABLE will actually be | 3288 Thenceforth, any operations performed on VARIABLE will actually be |
3142 performed on ALIAS. Both VARIABLE and ALIAS should be symbols. | 3289 performed on ALIASED. Both VARIABLE and ALIASED should be symbols. |
3143 If ALIAS is nil, remove any aliases for VARIABLE. | 3290 If ALIASED is nil and VARIABLE is an existing alias, remove that alias. |
3144 ALIAS can itself be aliased, and the chain of variable aliases | 3291 ALIASED can itself be an alias, and the chain of variable aliases |
3145 will be followed appropriately. | 3292 will be followed appropriately. |
3146 If VARIABLE already has a value, this value will be shadowed | 3293 If VARIABLE already has a value, this value will be shadowed |
3147 until the alias is removed, at which point it will be restored. | 3294 until the alias is removed, at which point it will be restored. |
3148 Currently VARIABLE cannot be a built-in variable, a variable that | 3295 Currently VARIABLE cannot be a built-in variable, a variable that |
3149 has a buffer-local value in any buffer, or the symbols nil or t. | 3296 has a buffer-local value in any buffer, or the symbols nil or t. |
3150 \(ALIAS, however, can be any type of variable.) | 3297 \(ALIASED, however, can be any type of variable.) |
3151 */ | 3298 |
3152 (variable, alias)) | 3299 Optional argument DOCSTRING is documentation for VARIABLE in its use as an |
3300 alias for ALIASED. The XEmacs help code ignores this documentation, using | |
3301 the documentation of ALIASED instead, and the docstring, if specified, is | |
3302 not shadowed in the same way that the value is. Only use it if you know | |
3303 what you're doing. | |
3304 */ | |
3305 (variable, aliased, docstring)) | |
3153 { | 3306 { |
3154 struct symbol_value_varalias *bfwd; | 3307 struct symbol_value_varalias *bfwd; |
3155 Lisp_Object valcontents; | 3308 Lisp_Object valcontents; |
3156 | 3309 |
3157 CHECK_SYMBOL (variable); | 3310 CHECK_SYMBOL (variable); |
3158 reject_constant_symbols (variable, Qunbound, 0, Qt); | 3311 reject_constant_symbols (variable, Qunbound, 0, Qt); |
3159 | 3312 |
3160 valcontents = XSYMBOL (variable)->value; | 3313 valcontents = XSYMBOL (variable)->value; |
3161 | 3314 |
3162 if (NILP (alias)) | 3315 if (NILP (aliased)) |
3163 { | 3316 { |
3164 if (SYMBOL_VALUE_VARALIAS_P (valcontents)) | 3317 if (SYMBOL_VALUE_VARALIAS_P (valcontents)) |
3165 { | 3318 { |
3166 XSYMBOL (variable)->value = | 3319 XSYMBOL (variable)->value = |
3167 symbol_value_varalias_shadowed | 3320 symbol_value_varalias_shadowed |
3168 (XSYMBOL_VALUE_VARALIAS (valcontents)); | 3321 (XSYMBOL_VALUE_VARALIAS (valcontents)); |
3169 } | 3322 } |
3170 return Qnil; | 3323 return Qnil; |
3171 } | 3324 } |
3172 | 3325 |
3173 CHECK_SYMBOL (alias); | 3326 CHECK_SYMBOL (aliased); |
3327 | |
3328 if (!NILP (docstring)) | |
3329 Fput (variable, Qvariable_documentation, docstring); | |
3330 | |
3174 if (SYMBOL_VALUE_VARALIAS_P (valcontents)) | 3331 if (SYMBOL_VALUE_VARALIAS_P (valcontents)) |
3175 { | 3332 { |
3176 /* transmogrify */ | 3333 /* transmogrify */ |
3177 XSYMBOL_VALUE_VARALIAS (valcontents)->aliasee = alias; | 3334 XSYMBOL_VALUE_VARALIAS (valcontents)->aliasee = aliased; |
3178 return Qnil; | 3335 return Qnil; |
3179 } | 3336 } |
3180 | 3337 |
3181 if (SYMBOL_VALUE_MAGIC_P (valcontents) | 3338 if (SYMBOL_VALUE_MAGIC_P (valcontents) |
3182 && !UNBOUNDP (valcontents)) | 3339 && !UNBOUNDP (valcontents)) |
3184 reject_constant_symbols (variable, Qunbound, 0, Qt); | 3341 reject_constant_symbols (variable, Qunbound, 0, Qt); |
3185 | 3342 |
3186 bfwd = ALLOC_LCRECORD_TYPE (struct symbol_value_varalias, | 3343 bfwd = ALLOC_LCRECORD_TYPE (struct symbol_value_varalias, |
3187 &lrecord_symbol_value_varalias); | 3344 &lrecord_symbol_value_varalias); |
3188 bfwd->magic.type = SYMVAL_VARALIAS; | 3345 bfwd->magic.type = SYMVAL_VARALIAS; |
3189 bfwd->aliasee = alias; | 3346 bfwd->aliasee = aliased; |
3190 bfwd->shadowed = valcontents; | 3347 bfwd->shadowed = valcontents; |
3191 | 3348 |
3192 valcontents = wrap_symbol_value_magic (bfwd); | 3349 valcontents = wrap_symbol_value_magic (bfwd); |
3193 XSYMBOL (variable)->value = valcontents; | 3350 XSYMBOL (variable)->value = valcontents; |
3194 return Qnil; | 3351 return Qnil; |
3195 } | 3352 } |
3196 | 3353 |
3197 DEFUN ("variable-alias", Fvariable_alias, 1, 2, 0, /* | 3354 DEFUN ("variable-alias", Fvariable_alias, 1, 2, 0, /* |
3198 If VARIABLE is aliased to another variable, return that variable. | 3355 If VARIABLE is an alias of another variable, return that variable. |
3199 VARIABLE should be a symbol. If VARIABLE is not aliased, return nil. | 3356 VARIABLE should be a symbol. If VARIABLE is not an alias, return nil. |
3200 Variable aliases are created with `defvaralias'. See also | 3357 Variable aliases are created with `defvaralias'. See also |
3201 `indirect-variable'. | 3358 `indirect-variable'. |
3202 */ | 3359 */ |
3203 (variable, follow_past_lisp_magic)) | 3360 (variable, follow_past_lisp_magic)) |
3204 { | 3361 { |
3753 DEFSUBR (Fmake_variable_buffer_local); | 3910 DEFSUBR (Fmake_variable_buffer_local); |
3754 DEFSUBR (Fmake_local_variable); | 3911 DEFSUBR (Fmake_local_variable); |
3755 DEFSUBR (Fkill_local_variable); | 3912 DEFSUBR (Fkill_local_variable); |
3756 DEFSUBR (Fkill_console_local_variable); | 3913 DEFSUBR (Fkill_console_local_variable); |
3757 DEFSUBR (Flocal_variable_p); | 3914 DEFSUBR (Flocal_variable_p); |
3915 DEFSUBR (Fcustom_variable_p); | |
3916 DEFSUBR (Fuser_variable_p); | |
3758 DEFSUBR (Fdefvaralias); | 3917 DEFSUBR (Fdefvaralias); |
3759 DEFSUBR (Fvariable_alias); | 3918 DEFSUBR (Fvariable_alias); |
3760 DEFSUBR (Findirect_variable); | 3919 DEFSUBR (Findirect_variable); |
3761 DEFSUBR (Fvariable_binding_locus); | 3920 DEFSUBR (Fvariable_binding_locus); |
3762 DEFSUBR (Fdontusethis_set_symbol_value_handler); | 3921 DEFSUBR (Fdontusethis_set_symbol_value_handler); |