diff options
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 214 |
1 files changed, 129 insertions, 85 deletions
diff --git a/src/eval.c b/src/eval.c index 6609d3b5c8a..cb1d435cb8b 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -767,24 +767,46 @@ The return value is BASE-VARIABLE. */) | |||
| 767 | CHECK_SYMBOL (new_alias); | 767 | CHECK_SYMBOL (new_alias); |
| 768 | CHECK_SYMBOL (base_variable); | 768 | CHECK_SYMBOL (base_variable); |
| 769 | 769 | ||
| 770 | if (SYMBOL_CONSTANT_P (new_alias)) | ||
| 771 | error ("Cannot make a constant an alias"); | ||
| 772 | |||
| 773 | sym = XSYMBOL (new_alias); | 770 | sym = XSYMBOL (new_alias); |
| 771 | |||
| 772 | if (sym->constant) | ||
| 773 | if (sym->redirect == SYMBOL_VARALIAS) | ||
| 774 | sym->constant = 0; /* Reset. */ | ||
| 775 | else | ||
| 776 | /* Not sure why. */ | ||
| 777 | error ("Cannot make a constant an alias"); | ||
| 778 | |||
| 779 | switch (sym->redirect) | ||
| 780 | { | ||
| 781 | case SYMBOL_FORWARDED: | ||
| 782 | error ("Cannot make an internal variable an alias"); | ||
| 783 | case SYMBOL_LOCALIZED: | ||
| 784 | error ("Don't know how to make a localized variable an alias"); | ||
| 785 | } | ||
| 786 | |||
| 774 | /* http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg00834.html | 787 | /* http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg00834.html |
| 775 | If n_a is bound, but b_v is not, set the value of b_v to n_a. | 788 | If n_a is bound, but b_v is not, set the value of b_v to n_a, |
| 776 | This is for the sake of define-obsolete-variable-alias and user | 789 | so that old-code that affects n_a before the aliasing is setup |
| 777 | customizations. */ | 790 | still works. */ |
| 778 | if (NILP (Fboundp (base_variable)) && !NILP (Fboundp (new_alias))) | 791 | if (NILP (Fboundp (base_variable))) |
| 779 | XSYMBOL(base_variable)->value = sym->value; | 792 | set_internal (base_variable, find_symbol_value (new_alias), NULL, 1); |
| 780 | sym->indirect_variable = 1; | 793 | |
| 781 | sym->value = base_variable; | 794 | { |
| 795 | struct specbinding *p; | ||
| 796 | |||
| 797 | for (p = specpdl_ptr - 1; p >= specpdl; p--) | ||
| 798 | if (p->func == NULL | ||
| 799 | && (EQ (new_alias, | ||
| 800 | CONSP (p->symbol) ? XCAR (p->symbol) : p->symbol))) | ||
| 801 | error ("Don't know how to make a let-bound variable an alias"); | ||
| 802 | } | ||
| 803 | |||
| 804 | sym->redirect = SYMBOL_VARALIAS; | ||
| 805 | SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable)); | ||
| 782 | sym->constant = SYMBOL_CONSTANT_P (base_variable); | 806 | sym->constant = SYMBOL_CONSTANT_P (base_variable); |
| 783 | LOADHIST_ATTACH (new_alias); | 807 | LOADHIST_ATTACH (new_alias); |
| 784 | if (!NILP (docstring)) | 808 | /* Even if docstring is nil: remove old docstring. */ |
| 785 | Fput (new_alias, Qvariable_documentation, docstring); | 809 | Fput (new_alias, Qvariable_documentation, docstring); |
| 786 | else | ||
| 787 | Fput (new_alias, Qvariable_documentation, Qnil); | ||
| 788 | 810 | ||
| 789 | return base_variable; | 811 | return base_variable; |
| 790 | } | 812 | } |
| @@ -944,7 +966,7 @@ chain of symbols. */) | |||
| 944 | return Qnil; | 966 | return Qnil; |
| 945 | 967 | ||
| 946 | /* If indirect and there's an alias loop, don't check anything else. */ | 968 | /* If indirect and there's an alias loop, don't check anything else. */ |
| 947 | if (XSYMBOL (variable)->indirect_variable | 969 | if (XSYMBOL (variable)->redirect == SYMBOL_VARALIAS |
| 948 | && NILP (internal_condition_case_1 (lisp_indirect_variable, variable, | 970 | && NILP (internal_condition_case_1 (lisp_indirect_variable, variable, |
| 949 | Qt, user_variable_p_eh))) | 971 | Qt, user_variable_p_eh))) |
| 950 | return Qnil; | 972 | return Qnil; |
| @@ -968,11 +990,11 @@ chain of symbols. */) | |||
| 968 | || (!NILP (Fget (variable, intern ("custom-autoload"))))) | 990 | || (!NILP (Fget (variable, intern ("custom-autoload"))))) |
| 969 | return Qt; | 991 | return Qt; |
| 970 | 992 | ||
| 971 | if (!XSYMBOL (variable)->indirect_variable) | 993 | if (!(XSYMBOL (variable)->redirect == SYMBOL_VARALIAS)) |
| 972 | return Qnil; | 994 | return Qnil; |
| 973 | 995 | ||
| 974 | /* An indirect variable? Let's follow the chain. */ | 996 | /* An indirect variable? Let's follow the chain. */ |
| 975 | variable = XSYMBOL (variable)->value; | 997 | XSETSYMBOL (variable, SYMBOL_ALIAS (XSYMBOL (variable))); |
| 976 | } | 998 | } |
| 977 | } | 999 | } |
| 978 | 1000 | ||
| @@ -3263,78 +3285,94 @@ void | |||
| 3263 | specbind (symbol, value) | 3285 | specbind (symbol, value) |
| 3264 | Lisp_Object symbol, value; | 3286 | Lisp_Object symbol, value; |
| 3265 | { | 3287 | { |
| 3266 | Lisp_Object valcontents; | 3288 | struct Lisp_Symbol *sym; |
| 3289 | |||
| 3290 | eassert (!handling_signal); | ||
| 3267 | 3291 | ||
| 3268 | CHECK_SYMBOL (symbol); | 3292 | CHECK_SYMBOL (symbol); |
| 3293 | sym = XSYMBOL (symbol); | ||
| 3269 | if (specpdl_ptr == specpdl + specpdl_size) | 3294 | if (specpdl_ptr == specpdl + specpdl_size) |
| 3270 | grow_specpdl (); | 3295 | grow_specpdl (); |
| 3271 | 3296 | ||
| 3272 | /* The most common case is that of a non-constant symbol with a | 3297 | start: |
| 3273 | trivial value. Make that as fast as we can. */ | 3298 | switch (sym->redirect) |
| 3274 | valcontents = SYMBOL_VALUE (symbol); | 3299 | { |
| 3275 | if (!MISCP (valcontents) && !SYMBOL_CONSTANT_P (symbol)) | 3300 | case SYMBOL_VARALIAS: |
| 3276 | { | 3301 | sym = indirect_variable (sym); XSETSYMBOL (symbol, sym); goto start; |
| 3277 | specpdl_ptr->symbol = symbol; | 3302 | case SYMBOL_PLAINVAL: |
| 3278 | specpdl_ptr->old_value = valcontents; | 3303 | { /* The most common case is that of a non-constant symbol with a |
| 3279 | specpdl_ptr->func = NULL; | 3304 | trivial value. Make that as fast as we can. */ |
| 3280 | ++specpdl_ptr; | 3305 | specpdl_ptr->symbol = symbol; |
| 3281 | SET_SYMBOL_VALUE (symbol, value); | 3306 | specpdl_ptr->old_value = SYMBOL_VAL (sym); |
| 3282 | } | 3307 | specpdl_ptr->func = NULL; |
| 3283 | else | 3308 | ++specpdl_ptr; |
| 3284 | { | 3309 | if (!sym->constant) |
| 3285 | Lisp_Object ovalue = find_symbol_value (symbol); | 3310 | SET_SYMBOL_VAL (sym, value); |
| 3286 | specpdl_ptr->func = 0; | ||
| 3287 | specpdl_ptr->old_value = ovalue; | ||
| 3288 | |||
| 3289 | valcontents = XSYMBOL (symbol)->value; | ||
| 3290 | |||
| 3291 | if (BUFFER_LOCAL_VALUEP (valcontents) | ||
| 3292 | || BUFFER_OBJFWDP (valcontents)) | ||
| 3293 | { | ||
| 3294 | Lisp_Object where, current_buffer; | ||
| 3295 | |||
| 3296 | current_buffer = Fcurrent_buffer (); | ||
| 3297 | |||
| 3298 | /* For a local variable, record both the symbol and which | ||
| 3299 | buffer's or frame's value we are saving. */ | ||
| 3300 | if (!NILP (Flocal_variable_p (symbol, Qnil))) | ||
| 3301 | where = current_buffer; | ||
| 3302 | else if (BUFFER_LOCAL_VALUEP (valcontents) | ||
| 3303 | && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame) | ||
| 3304 | where = XBUFFER_LOCAL_VALUE (valcontents)->frame; | ||
| 3305 | else | 3311 | else |
| 3306 | where = Qnil; | 3312 | set_internal (symbol, value, 0, 1); |
| 3307 | 3313 | break; | |
| 3308 | /* We're not using the `unused' slot in the specbinding | ||
| 3309 | structure because this would mean we have to do more | ||
| 3310 | work for simple variables. */ | ||
| 3311 | specpdl_ptr->symbol = Fcons (symbol, Fcons (where, current_buffer)); | ||
| 3312 | |||
| 3313 | /* If SYMBOL is a per-buffer variable which doesn't have a | ||
| 3314 | buffer-local value here, make the `let' change the global | ||
| 3315 | value by changing the value of SYMBOL in all buffers not | ||
| 3316 | having their own value. This is consistent with what | ||
| 3317 | happens with other buffer-local variables. */ | ||
| 3318 | if (NILP (where) | ||
| 3319 | && BUFFER_OBJFWDP (valcontents)) | ||
| 3320 | { | ||
| 3321 | ++specpdl_ptr; | ||
| 3322 | Fset_default (symbol, value); | ||
| 3323 | return; | ||
| 3324 | } | ||
| 3325 | } | 3314 | } |
| 3326 | else | 3315 | case SYMBOL_LOCALIZED: case SYMBOL_FORWARDED: |
| 3327 | specpdl_ptr->symbol = symbol; | 3316 | { |
| 3328 | 3317 | Lisp_Object ovalue = find_symbol_value (symbol); | |
| 3329 | specpdl_ptr++; | 3318 | specpdl_ptr->func = 0; |
| 3330 | /* We used to do | 3319 | specpdl_ptr->old_value = ovalue; |
| 3331 | if (BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue)) | 3320 | |
| 3332 | store_symval_forwarding (symbol, ovalue, value, NULL); | 3321 | eassert (sym->redirect != SYMBOL_LOCALIZED |
| 3333 | else | 3322 | || (EQ (SYMBOL_BLV (sym)->where, |
| 3334 | but ovalue comes from find_symbol_value which should never return | 3323 | SYMBOL_BLV (sym)->frame_local ? |
| 3335 | such an internal value. */ | 3324 | Fselected_frame () : Fcurrent_buffer ()))); |
| 3336 | eassert (!(BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue))); | 3325 | |
| 3337 | set_internal (symbol, value, 0, 1); | 3326 | if (sym->redirect == SYMBOL_LOCALIZED |
| 3327 | || BUFFER_OBJFWDP (SYMBOL_FWD (sym))) | ||
| 3328 | { | ||
| 3329 | Lisp_Object where, cur_buf = Fcurrent_buffer (); | ||
| 3330 | |||
| 3331 | /* For a local variable, record both the symbol and which | ||
| 3332 | buffer's or frame's value we are saving. */ | ||
| 3333 | if (!NILP (Flocal_variable_p (symbol, Qnil))) | ||
| 3334 | { | ||
| 3335 | eassert (sym->redirect != SYMBOL_LOCALIZED | ||
| 3336 | || (BLV_FOUND (SYMBOL_BLV (sym)) | ||
| 3337 | && EQ (cur_buf, SYMBOL_BLV (sym)->where))); | ||
| 3338 | where = cur_buf; | ||
| 3339 | } | ||
| 3340 | else if (sym->redirect == SYMBOL_LOCALIZED | ||
| 3341 | && BLV_FOUND (SYMBOL_BLV (sym))) | ||
| 3342 | where = SYMBOL_BLV (sym)->where; | ||
| 3343 | else | ||
| 3344 | where = Qnil; | ||
| 3345 | |||
| 3346 | /* We're not using the `unused' slot in the specbinding | ||
| 3347 | structure because this would mean we have to do more | ||
| 3348 | work for simple variables. */ | ||
| 3349 | /* FIXME: The third value `current_buffer' is only used in | ||
| 3350 | let_shadows_buffer_binding_p which is itself only used | ||
| 3351 | in set_internal for local_if_set. */ | ||
| 3352 | specpdl_ptr->symbol = Fcons (symbol, Fcons (where, cur_buf)); | ||
| 3353 | |||
| 3354 | /* If SYMBOL is a per-buffer variable which doesn't have a | ||
| 3355 | buffer-local value here, make the `let' change the global | ||
| 3356 | value by changing the value of SYMBOL in all buffers not | ||
| 3357 | having their own value. This is consistent with what | ||
| 3358 | happens with other buffer-local variables. */ | ||
| 3359 | if (NILP (where) | ||
| 3360 | && sym->redirect == SYMBOL_FORWARDED) | ||
| 3361 | { | ||
| 3362 | eassert (BUFFER_OBJFWDP (SYMBOL_FWD (sym))); | ||
| 3363 | ++specpdl_ptr; | ||
| 3364 | Fset_default (symbol, value); | ||
| 3365 | return; | ||
| 3366 | } | ||
| 3367 | } | ||
| 3368 | else | ||
| 3369 | specpdl_ptr->symbol = symbol; | ||
| 3370 | |||
| 3371 | specpdl_ptr++; | ||
| 3372 | set_internal (symbol, value, 0, 1); | ||
| 3373 | break; | ||
| 3374 | } | ||
| 3375 | default: abort (); | ||
| 3338 | } | 3376 | } |
| 3339 | } | 3377 | } |
| 3340 | 3378 | ||
| @@ -3394,7 +3432,12 @@ unbind_to (count, value) | |||
| 3394 | if (NILP (where)) | 3432 | if (NILP (where)) |
| 3395 | Fset_default (symbol, this_binding.old_value); | 3433 | Fset_default (symbol, this_binding.old_value); |
| 3396 | else if (BUFFERP (where)) | 3434 | else if (BUFFERP (where)) |
| 3397 | set_internal (symbol, this_binding.old_value, XBUFFER (where), 1); | 3435 | if (!NILP (Flocal_variable_p (symbol, where))) |
| 3436 | set_internal (symbol, this_binding.old_value, XBUFFER (where), 1); | ||
| 3437 | /* else if (!NILP (Fbuffer_live_p (where))) | ||
| 3438 | error ("Unbinding local %s to global!", symbol); */ | ||
| 3439 | else | ||
| 3440 | ; | ||
| 3398 | else | 3441 | else |
| 3399 | set_internal (symbol, this_binding.old_value, NULL, 1); | 3442 | set_internal (symbol, this_binding.old_value, NULL, 1); |
| 3400 | } | 3443 | } |
| @@ -3403,8 +3446,9 @@ unbind_to (count, value) | |||
| 3403 | /* If variable has a trivial value (no forwarding), we can | 3446 | /* If variable has a trivial value (no forwarding), we can |
| 3404 | just set it. No need to check for constant symbols here, | 3447 | just set it. No need to check for constant symbols here, |
| 3405 | since that was already done by specbind. */ | 3448 | since that was already done by specbind. */ |
| 3406 | if (!MISCP (SYMBOL_VALUE (this_binding.symbol))) | 3449 | if (XSYMBOL (this_binding.symbol)->redirect == SYMBOL_PLAINVAL) |
| 3407 | SET_SYMBOL_VALUE (this_binding.symbol, this_binding.old_value); | 3450 | SET_SYMBOL_VAL (XSYMBOL (this_binding.symbol), |
| 3451 | this_binding.old_value); | ||
| 3408 | else | 3452 | else |
| 3409 | set_internal (this_binding.symbol, this_binding.old_value, 0, 1); | 3453 | set_internal (this_binding.symbol, this_binding.old_value, 0, 1); |
| 3410 | } | 3454 | } |