emacs-pretest-bug
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Formatting `interactive' strings.


From: Chong Yidong
Subject: Re: Formatting `interactive' strings.
Date: Wed, 18 Oct 2006 19:14:14 -0400
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux)

address@hidden (Johan Bockgård) writes:

> The doc for `interactive' claims that "prompts are passed to format".
> This isn't quite true (it uses doprnt), and there are some problems:
>
> * Number formatting is broken:
>     (interactive "n\ns%d")  <-- C-x C-e 0 RET
> * %X isn't recognized. (Ditto for %i, but it's undocumented anyway.)
> * The `#' flag isn't recognized.

This is because, for some reason, the interactive argument is handled
using the C-level format function doprnt instead of Fformat.  Maybe
this is historical, since I don't see any other rationale for it.  The
following patch should fix it.  It's unfortunately rather big, but it
admits dramatic simplifications to the code.  I'll check it into CVS
soon if no one objects.

*** emacs/src/callint.c.~1.147.~        2006-10-17 16:40:23.000000000 -0400
--- emacs/src/callint.c 2006-10-18 19:05:33.000000000 -0400
***************
*** 58,68 ****
  /* Marker used within call-interactively to refer to point.  */
  static Lisp_Object point_marker;
  
! /* Buffer for the prompt text used in Fcall_interactively.  */
! static char *callint_message;
! 
! /* Allocated length of that buffer.  */
! static int callint_message_size;
  
  /* ARGSUSED */
  DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
--- 58,65 ----
  /* Marker used within call-interactively to refer to point.  */
  static Lisp_Object point_marker;
  
! /* String for the prompt text used in Fcall_interactively.  */
! static Lisp_Object callint_message;
  
  /* ARGSUSED */
  DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
***************
*** 266,272 ****
       Lisp_Object function, record_flag, keys;
  {
    Lisp_Object *args, *visargs;
-   unsigned char **argstrings;
    Lisp_Object fun;
    Lisp_Object specs;
    Lisp_Object filter_specs;
--- 263,268 ----
***************
*** 492,498 ****
  
    args = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
    visargs = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
-   argstrings = (unsigned char **) alloca ((count + 1) * sizeof (char *));
    varies = (int *) alloca ((count + 1) * sizeof (int));
  
    for (i = 0; i < (count + 1); i++)
--- 488,493 ----
***************
*** 516,549 ****
        prompt1[sizeof prompt1 - 1] = 0;
        tem1 = (char *) index (prompt1, '\n');
        if (tem1) *tem1 = 0;
!       /* Fill argstrings with a vector of C strings
!        corresponding to the Lisp strings in visargs.  */
!       for (j = 1; j < i; j++)
!       argstrings[j]
!         = (EQ (visargs[j], Qnil)
!            ? (unsigned char *) ""
!            : SDATA (visargs[j]));
! 
!       /* Process the format-string in prompt1, putting the output
!        into callint_message.  Make callint_message bigger if necessary.
!        We don't use a buffer on the stack, because the contents
!        need to stay stable for a while.  */
!       while (1)
!       {
!         int nchars = doprnt (callint_message, callint_message_size,
!                              prompt1, (char *)0,
!                              j - 1, (char **) argstrings + 1);
!         if (nchars < callint_message_size - 1)
!           break;
!         callint_message_size *= 2;
!         callint_message
!           = (char *) xrealloc (callint_message, callint_message_size);
!       }
  
        switch (*tem)
        {
        case 'a':               /* Symbol defined as a function */
!         visargs[i] = Fcompleting_read (build_string (callint_message),
                                         Vobarray, Qfboundp, Qt,
                                         Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
--- 511,524 ----
        prompt1[sizeof prompt1 - 1] = 0;
        tem1 = (char *) index (prompt1, '\n');
        if (tem1) *tem1 = 0;
! 
!       visargs[0] = build_string (prompt1);
!       callint_message = Fformat (i, visargs);
  
        switch (*tem)
        {
        case 'a':               /* Symbol defined as a function */
!         visargs[i] = Fcompleting_read (callint_message,
                                         Vobarray, Qfboundp, Qt,
                                         Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
***************
*** 555,571 ****
          args[i] = Fcurrent_buffer ();
          if (EQ (selected_window, minibuf_window))
            args[i] = Fother_buffer (args[i], Qnil, Qnil);
!         args[i] = Fread_buffer (build_string (callint_message), args[i], Qt);
          break;
  
        case 'B':               /* Name of buffer, possibly nonexistent */
!         args[i] = Fread_buffer (build_string (callint_message),
                                  Fother_buffer (Fcurrent_buffer (), Qnil, 
Qnil),
                                  Qnil);
          break;
  
          case 'c':             /* Character */
!         args[i] = Fread_char (build_string (callint_message), Qnil, Qnil);
          message1_nolog ((char *) 0);
          /* Passing args[i] directly stimulates compiler bug */
          teml = args[i];
--- 530,546 ----
          args[i] = Fcurrent_buffer ();
          if (EQ (selected_window, minibuf_window))
            args[i] = Fother_buffer (args[i], Qnil, Qnil);
!         args[i] = Fread_buffer (callint_message, args[i], Qt);
          break;
  
        case 'B':               /* Name of buffer, possibly nonexistent */
!         args[i] = Fread_buffer (callint_message,
                                  Fother_buffer (Fcurrent_buffer (), Qnil, 
Qnil),
                                  Qnil);
          break;
  
          case 'c':             /* Character */
!         args[i] = Fread_char (callint_message, Qnil, Qnil);
          message1_nolog ((char *) 0);
          /* Passing args[i] directly stimulates compiler bug */
          teml = args[i];
***************
*** 573,579 ****
          break;
  
        case 'C':               /* Command: symbol with interactive function */
!         visargs[i] = Fcompleting_read (build_string (callint_message),
                                         Vobarray, Qcommandp,
                                         Qt, Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
--- 548,554 ----
          break;
  
        case 'C':               /* Command: symbol with interactive function */
!         visargs[i] = Fcompleting_read (callint_message,
                                         Vobarray, Qcommandp,
                                         Qt, Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
***************
*** 589,612 ****
          break;
  
        case 'D':               /* Directory name. */
!         args[i] = Fread_file_name (build_string (callint_message), Qnil,
                                     current_buffer->directory, Qlambda, Qnil,
                                     Qfile_directory_p);
          break;
  
        case 'f':               /* Existing file name. */
!         args[i] = Fread_file_name (build_string (callint_message),
                                     Qnil, Qnil, Qlambda, Qnil, Qnil);
          break;
  
        case 'F':               /* Possibly nonexistent file name. */
!         args[i] = Fread_file_name (build_string (callint_message),
                                     Qnil, Qnil, Qnil, Qnil, Qnil);
          break;
  
        case 'G':               /* Possibly nonexistent file name,
                                   default to directory alone. */
!         args[i] = Fread_file_name (build_string (callint_message),
                                     Qnil, Qnil, Qnil, build_string (""), Qnil);
          break;
  
--- 564,587 ----
          break;
  
        case 'D':               /* Directory name. */
!         args[i] = Fread_file_name (callint_message, Qnil,
                                     current_buffer->directory, Qlambda, Qnil,
                                     Qfile_directory_p);
          break;
  
        case 'f':               /* Existing file name. */
!         args[i] = Fread_file_name (callint_message,
                                     Qnil, Qnil, Qlambda, Qnil, Qnil);
          break;
  
        case 'F':               /* Possibly nonexistent file name. */
!         args[i] = Fread_file_name (callint_message,
                                     Qnil, Qnil, Qnil, Qnil, Qnil);
          break;
  
        case 'G':               /* Possibly nonexistent file name,
                                   default to directory alone. */
!         args[i] = Fread_file_name (callint_message,
                                     Qnil, Qnil, Qnil, build_string (""), Qnil);
          break;
  
***************
*** 618,624 ****
          {
            int speccount1 = SPECPDL_INDEX ();
            specbind (Qcursor_in_echo_area, Qt);
!           args[i] = Fread_key_sequence (build_string (callint_message),
                                          Qnil, Qnil, Qnil, Qnil);
            unbind_to (speccount1, Qnil);
            teml = args[i];
--- 593,599 ----
          {
            int speccount1 = SPECPDL_INDEX ();
            specbind (Qcursor_in_echo_area, Qt);
!           args[i] = Fread_key_sequence (callint_message,
                                          Qnil, Qnil, Qnil, Qnil);
            unbind_to (speccount1, Qnil);
            teml = args[i];
***************
*** 646,652 ****
          {
            int speccount1 = SPECPDL_INDEX ();
            specbind (Qcursor_in_echo_area, Qt);
!           args[i] = Fread_key_sequence (build_string (callint_message),
                                          Qnil, Qt, Qnil, Qnil);
            teml = args[i];
            visargs[i] = Fkey_description (teml, Qnil);
--- 621,627 ----
          {
            int speccount1 = SPECPDL_INDEX ();
            specbind (Qcursor_in_echo_area, Qt);
!           args[i] = Fread_key_sequence (callint_message,
                                          Qnil, Qt, Qnil, Qnil);
            teml = args[i];
            visargs[i] = Fkey_description (teml, Qnil);
***************
*** 706,712 ****
  
        case 'M':               /* String read via minibuffer with
                                   inheriting the current input method.  */
!         args[i] = Fread_string (build_string (callint_message),
                                  Qnil, Qnil, Qnil, Qt);
          break;
  
--- 681,687 ----
  
        case 'M':               /* String read via minibuffer with
                                   inheriting the current input method.  */
!         args[i] = Fread_string (callint_message,
                                  Qnil, Qnil, Qnil, Qt);
          break;
  
***************
*** 726,732 ****
                  }
                first = 0;
  
!               tem = Fread_from_minibuffer (build_string (callint_message),
                                             Qnil, Qnil, Qnil, Qnil, Qnil,
                                             Qnil);
                if (! STRINGP (tem) || SCHARS (tem) == 0)
--- 701,707 ----
                  }
                first = 0;
  
!               tem = Fread_from_minibuffer (callint_message,
                                             Qnil, Qnil, Qnil, Qnil, Qnil,
                                             Qnil);
                if (! STRINGP (tem) || SCHARS (tem) == 0)
***************
*** 736,742 ****
              }
            while (! NUMBERP (args[i]));
          }
!         visargs[i] = last_minibuf_string;
          break;
  
        case 'P':               /* Prefix arg in raw form.  Does no I/O.  */
--- 711,717 ----
              }
            while (! NUMBERP (args[i]));
          }
!         visargs[i] = args[i];
          break;
  
        case 'P':               /* Prefix arg in raw form.  Does no I/O.  */
***************
*** 766,777 ****
  
        case 's':               /* String read via minibuffer without
                                   inheriting the current input method.  */
!         args[i] = Fread_string (build_string (callint_message),
                                  Qnil, Qnil, Qnil, Qnil);
          break;
  
        case 'S':               /* Any symbol.  */
!         visargs[i] = Fread_string (build_string (callint_message),
                                     Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
          teml = visargs[i];
--- 741,752 ----
  
        case 's':               /* String read via minibuffer without
                                   inheriting the current input method.  */
!         args[i] = Fread_string (callint_message,
                                  Qnil, Qnil, Qnil, Qnil);
          break;
  
        case 'S':               /* Any symbol.  */
!         visargs[i] = Fread_string (callint_message,
                                     Qnil, Qnil, Qnil, Qnil);
          /* Passing args[i] directly stimulates compiler bug */
          teml = visargs[i];
***************
*** 780,796 ****
  
        case 'v':               /* Variable name: symbol that is
                                   user-variable-p. */
!         args[i] = Fread_variable (build_string (callint_message), Qnil);
          visargs[i] = last_minibuf_string;
          break;
  
        case 'x':               /* Lisp expression read but not evaluated */
!         args[i] = Fread_minibuffer (build_string (callint_message), Qnil);
          visargs[i] = last_minibuf_string;
          break;
  
        case 'X':               /* Lisp expression read and evaluated */
!         args[i] = Feval_minibuffer (build_string (callint_message), Qnil);
          visargs[i] = last_minibuf_string;
          break;
  
--- 755,771 ----
  
        case 'v':               /* Variable name: symbol that is
                                   user-variable-p. */
!         args[i] = Fread_variable (callint_message, Qnil);
          visargs[i] = last_minibuf_string;
          break;
  
        case 'x':               /* Lisp expression read but not evaluated */
!         args[i] = Fread_minibuffer (callint_message, Qnil);
          visargs[i] = last_minibuf_string;
          break;
  
        case 'X':               /* Lisp expression read and evaluated */
!         args[i] = Feval_minibuffer (callint_message, Qnil);
          visargs[i] = last_minibuf_string;
          break;
  
***************
*** 804,816 ****
          else
            {
              args[i]
!               = Fread_non_nil_coding_system (build_string (callint_message));
              visargs[i] = last_minibuf_string;
            }
          break;
  
        case 'z':               /* Coding-system symbol or nil */
!         args[i] = Fread_coding_system (build_string (callint_message), Qnil);
          visargs[i] = last_minibuf_string;
          break;
  
--- 779,791 ----
          else
            {
              args[i]
!               = Fread_non_nil_coding_system (callint_message);
              visargs[i] = last_minibuf_string;
            }
          break;
  
        case 'z':               /* Coding-system symbol or nil */
!         args[i] = Fread_coding_system (callint_message, Qnil);
          visargs[i] = last_minibuf_string;
          break;
  
***************
*** 954,963 ****
    Qmouse_leave_buffer_hook = intern ("mouse-leave-buffer-hook");
    staticpro (&Qmouse_leave_buffer_hook);
  
-   callint_message_size = 100;
-   callint_message = (char *) xmalloc (callint_message_size);
- 
- 
    DEFVAR_KBOARD ("prefix-arg", Vprefix_arg,
                 doc: /* The value of the prefix argument for the next editing 
command.
  It may be a number, or the symbol `-' for just a minus sign as arg,
--- 929,934 ----





reply via email to

[Prev in Thread] Current Thread [Next in Thread]