aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2013-08-02 17:16:33 -0400
committerStefan Monnier2013-08-02 17:16:33 -0400
commita104f656c8217b027866d32e8d7bf024a671e3cc (patch)
treeb62ddfb915099ba3398b2f0b1f9ddc0ed6203102 /src
parent185e3b5a2f3dc2b5163eb1fe97499c6af1edaa9c (diff)
downloademacs-a104f656c8217b027866d32e8d7bf024a671e3cc.tar.gz
emacs-a104f656c8217b027866d32e8d7bf024a671e3cc.zip
Make defvar affect the default binding outside of any let.
* src/eval.c (default_toplevel_binding): New function. (Fdefvar): Use it. (unbind_to, backtrace_eval_unrewind): Do a bit of CSE simplification. (Fdefault_toplevel_value, Fset_default_toplevel_value): New subrs. (syms_of_eval): Export them. * src/data.c (Fdefault_value): Micro cleanup. * src/term.c (init_tty): Use "false". * lisp/custom.el (custom-initialize-default, custom-initialize-set) (custom-initialize-reset, custom-initialize-changed): Affect the toplevel-default-value (bug#6275, bug#14586). * lisp/emacs-lisp/advice.el (ad-compile-function): Undo previous workaround for bug#6275. * test/automated/core-elisp-tests.el: New file.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog10
-rw-r--r--src/data.c4
-rw-r--r--src/eval.c124
-rw-r--r--src/term.c24
4 files changed, 105 insertions, 57 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 2a511d2fc8a..c6e349010a7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
12013-08-02 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * eval.c (default_toplevel_binding): New function.
4 (Fdefvar): Use it.
5 (unbind_to, backtrace_eval_unrewind): Do a bit of CSE simplification.
6 (Fdefault_toplevel_value, Fset_default_toplevel_value): New subrs.
7 (syms_of_eval): Export them.
8 * data.c (Fdefault_value): Micro cleanup.
9 * term.c (init_tty): Use "false".
10
12013-08-02 Dmitry Antipov <dmantipov@yandex.ru> 112013-08-02 Dmitry Antipov <dmantipov@yandex.ru>
2 12
3 Fix X GC leak in GTK and raw (no toolkit) X ports. 13 Fix X GC leak in GTK and raw (no toolkit) X ports.
diff --git a/src/data.c b/src/data.c
index f04d6da618f..d1e43ac1b5f 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1384,9 +1384,7 @@ for this variable. The default value is meaningful for variables with
1384local bindings in certain buffers. */) 1384local bindings in certain buffers. */)
1385 (Lisp_Object symbol) 1385 (Lisp_Object symbol)
1386{ 1386{
1387 register Lisp_Object value; 1387 Lisp_Object value = default_value (symbol);
1388
1389 value = default_value (symbol);
1390 if (!EQ (value, Qunbound)) 1388 if (!EQ (value, Qunbound))
1391 return value; 1389 return value;
1392 1390
diff --git a/src/eval.c b/src/eval.c
index cb716690e3c..8ee259110f4 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -658,6 +658,51 @@ The return value is BASE-VARIABLE. */)
658 return base_variable; 658 return base_variable;
659} 659}
660 660
661static union specbinding *
662default_toplevel_binding (Lisp_Object symbol)
663{
664 union specbinding *binding = NULL;
665 union specbinding *pdl = specpdl_ptr;
666 while (pdl > specpdl)
667 {
668 switch ((--pdl)->kind)
669 {
670 case SPECPDL_LET_DEFAULT:
671 case SPECPDL_LET:
672 if (EQ (specpdl_symbol (pdl), symbol))
673 binding = pdl;
674 break;
675 }
676 }
677 return binding;
678}
679
680DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_value, 1, 1, 0,
681 doc: /* Return SYMBOL's toplevel default value.
682"Toplevel" means outside of any let binding. */)
683 (Lisp_Object symbol)
684{
685 union specbinding *binding = default_toplevel_binding (symbol);
686 Lisp_Object value
687 = binding ? specpdl_old_value (binding) : Fdefault_value (symbol);
688 if (!EQ (value, Qunbound))
689 return value;
690 xsignal1 (Qvoid_variable, symbol);
691}
692
693DEFUN ("set-default-toplevel-value", Fset_default_toplevel_value,
694 Sset_default_toplevel_value, 2, 2, 0,
695 doc: /* Set SYMBOL's toplevel default value to VALUE.
696"Toplevel" means outside of any let binding. */)
697 (Lisp_Object symbol, Lisp_Object value)
698{
699 union specbinding *binding = default_toplevel_binding (symbol);
700 if (binding)
701 set_specpdl_old_value (binding, value);
702 else
703 Fset_default (symbol, value);
704 return Qnil;
705}
661 706
662DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0, 707DEFUN ("defvar", Fdefvar, Sdefvar, 1, UNEVALLED, 0,
663 doc: /* Define SYMBOL as a variable, and return SYMBOL. 708 doc: /* Define SYMBOL as a variable, and return SYMBOL.
@@ -706,18 +751,10 @@ usage: (defvar SYMBOL &optional INITVALUE DOCSTRING) */)
706 else 751 else
707 { /* Check if there is really a global binding rather than just a let 752 { /* Check if there is really a global binding rather than just a let
708 binding that shadows the global unboundness of the var. */ 753 binding that shadows the global unboundness of the var. */
709 union specbinding *pdl = specpdl_ptr; 754 union specbinding *binding = default_toplevel_binding (sym);
710 while (pdl > specpdl) 755 if (binding && EQ (specpdl_old_value (binding), Qunbound))
711 { 756 {
712 if ((--pdl)->kind >= SPECPDL_LET 757 set_specpdl_old_value (binding, eval_sub (XCAR (tail)));
713 && EQ (specpdl_symbol (pdl), sym)
714 && EQ (specpdl_old_value (pdl), Qunbound))
715 {
716 message_with_string
717 ("Warning: defvar ignored because %s is let-bound",
718 SYMBOL_NAME (sym), 1);
719 break;
720 }
721 } 758 }
722 } 759 }
723 tail = XCDR (tail); 760 tail = XCDR (tail);
@@ -3311,19 +3348,21 @@ unbind_to (ptrdiff_t count, Lisp_Object value)
3311 case SPECPDL_BACKTRACE: 3348 case SPECPDL_BACKTRACE:
3312 break; 3349 break;
3313 case SPECPDL_LET: 3350 case SPECPDL_LET:
3314 /* If variable has a trivial value (no forwarding), we can 3351 { /* If variable has a trivial value (no forwarding), we can
3315 just set it. No need to check for constant symbols here, 3352 just set it. No need to check for constant symbols here,
3316 since that was already done by specbind. */ 3353 since that was already done by specbind. */
3317 if (XSYMBOL (specpdl_symbol (specpdl_ptr))->redirect 3354 struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (specpdl_ptr));
3318 == SYMBOL_PLAINVAL) 3355 if (sym->redirect == SYMBOL_PLAINVAL)
3319 SET_SYMBOL_VAL (XSYMBOL (specpdl_symbol (specpdl_ptr)), 3356 {
3320 specpdl_old_value (specpdl_ptr)); 3357 SET_SYMBOL_VAL (sym, specpdl_old_value (specpdl_ptr));
3321 else 3358 break;
3322 /* NOTE: we only ever come here if make_local_foo was used for 3359 }
3323 the first time on this var within this let. */ 3360 else
3324 Fset_default (specpdl_symbol (specpdl_ptr), 3361 { /* FALLTHROUGH!!
3325 specpdl_old_value (specpdl_ptr)); 3362 NOTE: we only ever come here if make_local_foo was used for
3326 break; 3363 the first time on this var within this let. */
3364 }
3365 }
3327 case SPECPDL_LET_DEFAULT: 3366 case SPECPDL_LET_DEFAULT:
3328 Fset_default (specpdl_symbol (specpdl_ptr), 3367 Fset_default (specpdl_symbol (specpdl_ptr),
3329 specpdl_old_value (specpdl_ptr)); 3368 specpdl_old_value (specpdl_ptr));
@@ -3511,24 +3550,23 @@ backtrace_eval_unrewind (int distance)
3511 case SPECPDL_BACKTRACE: 3550 case SPECPDL_BACKTRACE:
3512 break; 3551 break;
3513 case SPECPDL_LET: 3552 case SPECPDL_LET:
3514 /* If variable has a trivial value (no forwarding), we can 3553 { /* If variable has a trivial value (no forwarding), we can
3515 just set it. No need to check for constant symbols here, 3554 just set it. No need to check for constant symbols here,
3516 since that was already done by specbind. */ 3555 since that was already done by specbind. */
3517 if (XSYMBOL (specpdl_symbol (tmp))->redirect 3556 struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (tmp));
3518 == SYMBOL_PLAINVAL) 3557 if (sym->redirect == SYMBOL_PLAINVAL)
3519 { 3558 {
3520 struct Lisp_Symbol *sym = XSYMBOL (specpdl_symbol (tmp)); 3559 Lisp_Object old_value = specpdl_old_value (tmp);
3521 Lisp_Object old_value = specpdl_old_value (tmp); 3560 set_specpdl_old_value (tmp, SYMBOL_VAL (sym));
3522 set_specpdl_old_value (tmp, SYMBOL_VAL (sym)); 3561 SET_SYMBOL_VAL (sym, old_value);
3523 SET_SYMBOL_VAL (sym, old_value); 3562 break;
3524 break; 3563 }
3525 } 3564 else
3526 else 3565 { /* FALLTHROUGH!!
3527 { 3566 NOTE: we only ever come here if make_local_foo was used for
3528 /* FALLTHROUGH! 3567 the first time on this var within this let. */
3529 NOTE: we only ever come here if make_local_foo was used for 3568 }
3530 the first time on this var within this let. */ 3569 }
3531 }
3532 case SPECPDL_LET_DEFAULT: 3570 case SPECPDL_LET_DEFAULT:
3533 { 3571 {
3534 Lisp_Object sym = specpdl_symbol (tmp); 3572 Lisp_Object sym = specpdl_symbol (tmp);
@@ -3796,6 +3834,8 @@ alist of active lexical bindings. */);
3796 defsubr (&Ssetq); 3834 defsubr (&Ssetq);
3797 defsubr (&Squote); 3835 defsubr (&Squote);
3798 defsubr (&Sfunction); 3836 defsubr (&Sfunction);
3837 defsubr (&Sdefault_toplevel_value);
3838 defsubr (&Sset_default_toplevel_value);
3799 defsubr (&Sdefvar); 3839 defsubr (&Sdefvar);
3800 defsubr (&Sdefvaralias); 3840 defsubr (&Sdefvaralias);
3801 defsubr (&Sdefconst); 3841 defsubr (&Sdefconst);
diff --git a/src/term.c b/src/term.c
index 376d6e7831a..f5f4882161e 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2933,7 +2933,7 @@ dissociate_if_controlling_tty (int fd)
2933 2933
2934 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100". 2934 TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
2935 2935
2936 If MUST_SUCCEED is true, then all errors are fatal. */ 2936 If MUST_SUCCEED is true, then all errors are fatal. */
2937 2937
2938struct terminal * 2938struct terminal *
2939init_tty (const char *name, const char *terminal_type, bool must_succeed) 2939init_tty (const char *name, const char *terminal_type, bool must_succeed)
@@ -2944,7 +2944,7 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed)
2944 int status; 2944 int status;
2945 struct tty_display_info *tty = NULL; 2945 struct tty_display_info *tty = NULL;
2946 struct terminal *terminal = NULL; 2946 struct terminal *terminal = NULL;
2947 bool ctty = 0; /* True if asked to open controlling tty. */ 2947 bool ctty = false; /* True if asked to open controlling tty. */
2948 2948
2949 if (!terminal_type) 2949 if (!terminal_type)
2950 maybe_fatal (must_succeed, 0, 2950 maybe_fatal (must_succeed, 0,
@@ -3031,7 +3031,7 @@ init_tty (const char *name, const char *terminal_type, bool must_succeed)
3031 tty->termcap_term_buffer = xmalloc (buffer_size); 3031 tty->termcap_term_buffer = xmalloc (buffer_size);
3032 3032
3033 /* On some systems, tgetent tries to access the controlling 3033 /* On some systems, tgetent tries to access the controlling
3034 terminal. */ 3034 terminal. */
3035 block_tty_out_signal (); 3035 block_tty_out_signal ();
3036 status = tgetent (tty->termcap_term_buffer, terminal_type); 3036 status = tgetent (tty->termcap_term_buffer, terminal_type);
3037 unblock_tty_out_signal (); 3037 unblock_tty_out_signal ();
@@ -3101,13 +3101,13 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3101 Right (tty) = tgetstr ("nd", address); 3101 Right (tty) = tgetstr ("nd", address);
3102 Down (tty) = tgetstr ("do", address); 3102 Down (tty) = tgetstr ("do", address);
3103 if (!Down (tty)) 3103 if (!Down (tty))
3104 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */ 3104 Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do". */
3105 if (tgetflag ("bs")) 3105 if (tgetflag ("bs"))
3106 Left (tty) = "\b"; /* can't possibly be longer! */ 3106 Left (tty) = "\b"; /* Can't possibly be longer! */
3107 else /* (Actually, "bs" is obsolete...) */ 3107 else /* (Actually, "bs" is obsolete...) */
3108 Left (tty) = tgetstr ("le", address); 3108 Left (tty) = tgetstr ("le", address);
3109 if (!Left (tty)) 3109 if (!Left (tty))
3110 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */ 3110 Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le". */
3111 tty->TS_pad_char = tgetstr ("pc", address); 3111 tty->TS_pad_char = tgetstr ("pc", address);
3112 tty->TS_repeat = tgetstr ("rp", address); 3112 tty->TS_repeat = tgetstr ("rp", address);
3113 tty->TS_end_standout_mode = tgetstr ("se", address); 3113 tty->TS_end_standout_mode = tgetstr ("se", address);
@@ -3229,7 +3229,7 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3229 don't think we're losing anything by turning it off. */ 3229 don't think we're losing anything by turning it off. */
3230 terminal->line_ins_del_ok = 0; 3230 terminal->line_ins_del_ok = 0;
3231 3231
3232 tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */ 3232 tty->TN_max_colors = 16; /* Must be non-zero for tty-display-color-p. */
3233#endif /* DOS_NT */ 3233#endif /* DOS_NT */
3234 3234
3235#ifdef HAVE_GPM 3235#ifdef HAVE_GPM
@@ -3325,16 +3325,16 @@ use the Bourne shell command `TERM=... export TERM' (C-shell:\n\
3325 tty->Wcm->cm_tab = 0; 3325 tty->Wcm->cm_tab = 0;
3326 /* We can't support standout mode, because it uses magic cookies. */ 3326 /* We can't support standout mode, because it uses magic cookies. */
3327 tty->TS_standout_mode = 0; 3327 tty->TS_standout_mode = 0;
3328 /* But that means we cannot rely on ^M to go to column zero! */ 3328 /* But that means we cannot rely on ^M to go to column zero! */
3329 CR (tty) = 0; 3329 CR (tty) = 0;
3330 /* LF can't be trusted either -- can alter hpos */ 3330 /* LF can't be trusted either -- can alter hpos. */
3331 /* if move at column 0 thru a line with TS_standout_mode */ 3331 /* If move at column 0 thru a line with TS_standout_mode. */
3332 Down (tty) = 0; 3332 Down (tty) = 0;
3333 } 3333 }
3334 3334
3335 tty->specified_window = FrameRows (tty); 3335 tty->specified_window = FrameRows (tty);
3336 3336
3337 if (Wcm_init (tty) == -1) /* can't do cursor motion */ 3337 if (Wcm_init (tty) == -1) /* Can't do cursor motion. */
3338 { 3338 {
3339 maybe_fatal (must_succeed, terminal, 3339 maybe_fatal (must_succeed, terminal,
3340 "Terminal type \"%s\" is not powerful enough to run Emacs", 3340 "Terminal type \"%s\" is not powerful enough to run Emacs",