all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Problem report #60
@ 2006-04-11 15:48 Dan Nicolaescu
  2006-04-11 17:54 ` Stuart D. Herring
  0 siblings, 1 reply; 6+ messages in thread
From: Dan Nicolaescu @ 2006-04-11 15:48 UTC (permalink / raw)


CID: 60
Checker: UNINIT (help)
File: emacs/src/keyboard.c
Function: read_key_sequence
Description: Using uninitialized value "original_uppercase"

Event var_decl: Declared variable "original_uppercase" without initializer
Also see events: [uninit_use]

8608 	  volatile Lisp_Object original_uppercase;
8609 	  volatile int original_uppercase_position = -1;
8610 	
8611 	  /* Gets around Microsoft compiler limitations.  */
8612 	  int dummyflag = 0;
8613 	
8614 	  struct buffer *starting_buffer;
8615 	
8616 	  /* List of events for which a fake prefix key has been generated.  */
8617 	  volatile Lisp_Object fake_prefixed_keys = Qnil;
8618 	
8619 	#if defined (GOBBLE_FIRST_EVENT)
8620 	  int junk;
8621 	#endif
8622 	
8623 	  struct gcpro gcpro1;
8624 	
8625 	  GCPRO1 (fake_prefixed_keys);
8626 	  raw_keybuf_count = 0;
8627 	
8628 	  last_nonmenu_event = Qnil;
8629 	
8630 	  delayed_switch_frame = Qnil;
8631 	  fkey.map = fkey.parent = Vfunction_key_map;
8632 	  keytran.map = keytran.parent = Vkey_translation_map;
8633 	  /* If there is no translation-map, turn off scanning.  */
8634 	  fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
8635 	  keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
8636 	
8637 	  if (INTERACTIVE)
8638 	    {
8639 	      if (!NILP (prompt))
8640 		echo_prompt (prompt);
8641 	      else if (cursor_in_echo_area
8642 		       && (FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
8643 		       && NILP (Fzerop (Vecho_keystrokes)))
8644 		/* This doesn't put in a dash if the echo buffer is empty, so
8645 		   you don't always see a dash hanging out in the minibuffer.  */
8646 		echo_dash ();
8647 	    }
8648 	
8649 	  /* Record the initial state of the echo area and this_command_keys;
8650 	     we will need to restore them if we replay a key sequence.  */
8651 	  if (INTERACTIVE)
8652 	    echo_start = echo_length ();
8653 	  keys_start = this_command_key_count;
8654 	  this_single_command_key_start = keys_start;
8655 	
8656 	#if defined (GOBBLE_FIRST_EVENT)
8657 	  /* This doesn't quite work, because some of the things that read_char
8658 	     does cannot safely be bypassed.  It seems too risky to try to make
8659 	     this work right.  */
8660 	
8661 	  /* Read the first char of the sequence specially, before setting
8662 	     up any keymaps, in case a filter runs and switches buffers on us.  */
8663 	  first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
8664 				   &junk);
8665 	#endif /* GOBBLE_FIRST_EVENT */
8666 	
8667 	  orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
8668 	  orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
8669 	  from_string = Qnil;
8670 	
8671 	  /* We jump here when the key sequence has been thoroughly changed, and
8672 	     we need to rescan it starting from the beginning.  When we jump here,
8673 	     keybuf[0..mock_input] holds the sequence we should reread.  */
8674 	 replay_sequence:
8675 	
8676 	  starting_buffer = current_buffer;
8677 	  first_unbound = bufsize + 1;
8678 	
8679 	  /* Build our list of keymaps.
8680 	     If we recognize a function key and replace its escape sequence in
8681 	     keybuf with its symbol, or if the sequence starts with a mouse
8682 	     click and we need to switch buffers, we jump back here to rebuild
8683 	     the initial keymaps from the current buffer.  */
8684 	  nmaps = 0;
8685 	
8686 	  if (!NILP (current_kboard->Voverriding_terminal_local_map)
8687 	      || !NILP (Voverriding_local_map))
8688 	    {
8689 	      if (3 > nmaps_allocated)
8690 		{
8691 		  submaps = (Lisp_Object *) alloca (3 * sizeof (submaps[0]));
8692 		  defs    = (Lisp_Object *) alloca (3 * sizeof (defs[0]));
8693 		  nmaps_allocated = 3;
8694 		}
8695 	      if (!NILP (current_kboard->Voverriding_terminal_local_map))
8696 		submaps[nmaps++] = current_kboard->Voverriding_terminal_local_map;
8697 	      if (!NILP (Voverriding_local_map))
8698 		submaps[nmaps++] = Voverriding_local_map;
8699 	    }
8700 	  else
8701 	    {
8702 	      int nminor;
8703 	      int total;
8704 	      Lisp_Object *maps;
8705 	
8706 	      nminor = current_minor_maps (0, &maps);
8707 	      total = nminor + (!NILP (orig_keymap) ? 3 : 2);
8708 	
8709 	      if (total > nmaps_allocated)
8710 		{
8711 		  submaps = (Lisp_Object *) alloca (total * sizeof (submaps[0]));
8712 		  defs    = (Lisp_Object *) alloca (total * sizeof (defs[0]));
8713 		  nmaps_allocated = total;
8714 		}
8715 	
8716 	      if (!NILP (orig_keymap))
8717 		submaps[nmaps++] = orig_keymap;
8718 	
8719 	      bcopy (maps, (void *) (submaps + nmaps),
8720 		     nminor * sizeof (submaps[0]));
8721 	
8722 	      nmaps += nminor;
8723 	
8724 	      submaps[nmaps++] = orig_local_map;
8725 	    }
8726 	  submaps[nmaps++] = current_global_map;
8727 	
8728 	  /* Find an accurate initial value for first_binding.  */
8729 	  for (first_binding = 0; first_binding < nmaps; first_binding++)
8730 	    if (! NILP (submaps[first_binding]))
8731 	      break;
8732 	
8733 	  /* Start from the beginning in keybuf.  */
8734 	  t = 0;
8735 	
8736 	  /* These are no-ops the first time through, but if we restart, they
8737 	     revert the echo area and this_command_keys to their original state.  */
8738 	  this_command_key_count = keys_start;
8739 	  if (INTERACTIVE && t < mock_input)
8740 	    echo_truncate (echo_start);
8741 	
8742 	  /* If the best binding for the current key sequence is a keymap, or
8743 	     we may be looking at a function key's escape sequence, keep on
8744 	     reading.  */

At conditional (1): "((first_binding < nmaps) ? ((*(submaps + (first_binding * 4)) != Qnil) ? 1 : (0)) : ((fkey).start < t || (keytran).start < t)) != 0" taking true path

8745 	  while (first_binding < nmaps
8746 		 /* Keep reading as long as there's a prefix binding.  */
8747 		 ? !NILP (submaps[first_binding])
8748 		 /* Don't return in the middle of a possible function key sequence,
8749 		    if the only bindings we found were via case conversion.
8750 		    Thus, if ESC O a has a function-key-map translation
8751 		    and ESC o has a binding, don't return after ESC O,
8752 		    so that we can translate ESC O plus the next character.  */
8753 		 : (fkey.start < t || keytran.start < t))
8754 	    {
8755 	      Lisp_Object key;
8756 	      int used_mouse_menu = 0;
8757 	
8758 	      /* Where the last real key started.  If we need to throw away a
8759 	         key that has expanded into more than one element of keybuf
8760 	         (say, a mouse click on the mode line which is being treated
8761 	         as [mode-line (mouse-...)], then we backtrack to this point
8762 	         of keybuf.  */
8763 	      volatile int last_real_key_start;
8764 	
8765 	      /* These variables are analogous to echo_start and keys_start;
8766 		 while those allow us to restart the entire key sequence,
8767 		 echo_local_start and keys_local_start allow us to throw away
8768 		 just one key.  */
8769 	      volatile int echo_local_start, keys_local_start, local_first_binding;
8770 	
8771 	      eassert (fkey.end == t || (fkey.end > t && fkey.end <= mock_input));
8772 	      eassert (fkey.start <= fkey.end);
8773 	      eassert (keytran.start <= keytran.end);
8774 	      /* key-translation-map is applied *after* function-key-map.  */
8775 	      eassert (keytran.end <= fkey.start);
8776 	

At conditional (2): "first_unbound < (fkey).start" taking true path
At conditional (3): "first_unbound < (keytran).start" taking false path

8777 	      if (first_unbound < fkey.start && first_unbound < keytran.start)
8778 		{ /* The prefix upto first_unbound has no binding and has
8779 		     no translation left to do either, so we know it's unbound.
8780 		     If we don't stop now, we risk staying here indefinitely
8781 		     (if the user keeps entering fkey or keytran prefixes
8782 		     like C-c ESC ESC ESC ESC ...)  */
8783 		  int i;
8784 		  for (i = first_unbound + 1; i < t; i++)
8785 		    keybuf[i - first_unbound - 1] = keybuf[i];
8786 		  mock_input = t - first_unbound - 1;
8787 		  fkey.end = fkey.start -= first_unbound + 1;
8788 		  fkey.map = fkey.parent;
8789 		  keytran.end = keytran.start -= first_unbound + 1;
8790 		  keytran.map = keytran.parent;
8791 		  goto replay_sequence;
8792 		}
8793 	

At conditional (4): "t >= bufsize" taking false path

8794 	      if (t >= bufsize)
8795 		error ("Key sequence too long");
8796 	

At conditional (5): "Vexecuting_kbd_macro == Qnil" taking true path
At conditional (6): "noninteractive == 0" taking true path

8797 	      if (INTERACTIVE)
8798 		echo_local_start = echo_length ();
8799 	      keys_local_start = this_command_key_count;
8800 	      local_first_binding = first_binding;
8801 	
8802 	    replay_key:
8803 	      /* These are no-ops, unless we throw away a keystroke below and
8804 		 jumped back up to replay_key; in that case, these restore the
8805 		 variables to their original state, allowing us to replay the
8806 		 loop.  */

At conditional (7): "Vexecuting_kbd_macro == Qnil" taking true path
At conditional (8): "noninteractive == 0" taking true path
At conditional (9): "t < mock_input" taking false path

8807 	      if (INTERACTIVE && t < mock_input)
8808 		echo_truncate (echo_local_start);
8809 	      this_command_key_count = keys_local_start;
8810 	      first_binding = local_first_binding;
8811 	
8812 	      /* By default, assume each event is "real".  */
8813 	      last_real_key_start = t;
8814 	
8815 	      /* Does mock_input indicate that we are re-reading a key sequence?  */

At conditional (10): "t < mock_input" taking false path

8816 	      if (t < mock_input)
8817 		{
8818 		  key = keybuf[t];
8819 		  add_command_key (key);
8820 		  if ((FLOATP (Vecho_keystrokes) || INTEGERP (Vecho_keystrokes))
8821 		      && NILP (Fzerop (Vecho_keystrokes)))
8822 		    echo_char (key);
8823 		}
8824 	
8825 	      /* If not, we should actually read a character.  */
8826 	      else
8827 		{
8828 		  {
8829 	#ifdef MULTI_KBOARD
8830 		    KBOARD *interrupted_kboard = current_kboard;

At conditional (11): "selected_frame & 7 == 4" taking true path
At conditional (12): "((0), (selected_frame & -8))->size & 1073742848 == 1073742848" taking true path
At conditional (13): "(((0), (selected_frame & -8))->output_data).nothing != 0" taking true path

8831 		    struct frame *interrupted_frame = SELECTED_FRAME ();

At conditional (14): "_setjmp != 0" taking false path

8832 		    if (setjmp (wrong_kboard_jmpbuf))
8833 		      {
8834 			if (!NILP (delayed_switch_frame))
8835 			  {
8836 			    interrupted_kboard->kbd_queue
8837 			      = Fcons (delayed_switch_frame,
8838 				       interrupted_kboard->kbd_queue);
8839 			    delayed_switch_frame = Qnil;
8840 			  }
8841 			while (t > 0)
8842 			  interrupted_kboard->kbd_queue
8843 			    = Fcons (keybuf[--t], interrupted_kboard->kbd_queue);
8844 	
8845 			/* If the side queue is non-empty, ensure it begins with a
8846 			   switch-frame, so we'll replay it in the right context.  */
8847 			if (CONSP (interrupted_kboard->kbd_queue)
8848 			    && (key = XCAR (interrupted_kboard->kbd_queue),
8849 				!(EVENT_HAS_PARAMETERS (key)
8850 				  && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)),
8851 					 Qswitch_frame))))
8852 			  {
8853 			    Lisp_Object frame;
8854 			    XSETFRAME (frame, interrupted_frame);
8855 			    interrupted_kboard->kbd_queue
8856 			      = Fcons (make_lispy_switch_frame (frame),
8857 				       interrupted_kboard->kbd_queue);
8858 			  }
8859 			mock_input = 0;
8860 			orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
8861 			orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
8862 			goto replay_sequence;
8863 		      }
8864 	#endif

At conditional (15): "prompt == Qnil" taking false path

8865 		    key = read_char (NILP (prompt), nmaps,
8866 				     (Lisp_Object *) submaps, last_nonmenu_event,
8867 				     &used_mouse_menu);
8868 		  }
8869 	
8870 		  /* read_char returns t when it shows a menu and the user rejects it.
8871 		     Just return -1.  */

At conditional (16): "key == Qt" taking false path

8872 		  if (EQ (key, Qt))
8873 		    {
8874 		      unbind_to (count, Qnil);
8875 		      UNGCPRO;
8876 		      return -1;
8877 		    }
8878 	
8879 		  /* read_char returns -1 at the end of a macro.
8880 		     Emacs 18 handles this by returning immediately with a
8881 		     zero, so that's what we'll do.  */

At conditional (17): "key & 7 == 0" taking true path
At conditional (18): "key >> 3 == -1" taking true path

8882 		  if (INTEGERP (key) && XINT (key) == -1)
8883 		    {
8884 		      t = 0;
8885 		      /* The Microsoft C compiler can't handle the goto that
8886 			 would go here.  */
8887 		      dummyflag = 1;
8888 		      break;
8889 		    }
8890 	
8891 		  /* If the current buffer has been changed from under us, the
8892 		     keymap may have changed, so replay the sequence.  */
8893 		  if (BUFFERP (key))
8894 		    {
8895 		      timer_resume_idle ();
8896 	
8897 		      mock_input = t;
8898 		      /* Reset the current buffer from the selected window
8899 			 in case something changed the former and not the latter.
8900 			 This is to be more consistent with the behavior
8901 			 of the command_loop_1.  */
8902 		      if (fix_current_buffer)
8903 			{
8904 			  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
8905 			    Fkill_emacs (Qnil);
8906 			  if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
8907 			    Fset_buffer (XWINDOW (selected_window)->buffer);
8908 			}
8909 	
8910 		      orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
8911 		      orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
8912 		      goto replay_sequence;
8913 		    }
8914 	
8915 		  /* If we have a quit that was typed in another frame, and
8916 		     quit_throw_to_read_char switched buffers,
8917 		     replay to get the right keymap.  */
8918 		  if (INTEGERP (key)
8919 		      && XINT (key) == quit_char
8920 		      && current_buffer != starting_buffer)
8921 		    {
8922 		      GROW_RAW_KEYBUF;
8923 		      XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
8924 		      keybuf[t++] = key;
8925 		      mock_input = t;
8926 		      Vquit_flag = Qnil;
8927 		      orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
8928 		      orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
8929 		      goto replay_sequence;
8930 		    }
8931 	
8932 		  Vquit_flag = Qnil;
8933 	
8934 		  if (EVENT_HAS_PARAMETERS (key)
8935 		      /* Either a `switch-frame' or a `select-window' event.  */
8936 		      && EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)), Qswitch_frame))
8937 		    {
8938 		      /* If we're at the beginning of a key sequence, and the caller
8939 			 says it's okay, go ahead and return this event.  If we're
8940 			 in the midst of a key sequence, delay it until the end. */
8941 		      if (t > 0 || !can_return_switch_frame)
8942 			{
8943 			  delayed_switch_frame = key;
8944 			  goto replay_key;
8945 			}
8946 		    }
8947 	
8948 		  GROW_RAW_KEYBUF;
8949 		  XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
8950 		}
8951 	
8952 	      /* Clicks in non-text areas get prefixed by the symbol
8953 		 in their CHAR-ADDRESS field.  For example, a click on
8954 		 the mode line is prefixed by the symbol `mode-line'.
8955 	
8956 		 Furthermore, key sequences beginning with mouse clicks
8957 		 are read using the keymaps of the buffer clicked on, not
8958 		 the current buffer.  So we may have to switch the buffer
8959 		 here.
8960 	
8961 		 When we turn one event into two events, we must make sure
8962 		 that neither of the two looks like the original--so that,
8963 		 if we replay the events, they won't be expanded again.
8964 		 If not for this, such reexpansion could happen either here
8965 		 or when user programs play with this-command-keys.  */
8966 	      if (EVENT_HAS_PARAMETERS (key))
8967 		{
8968 		  Lisp_Object kind;
8969 		  Lisp_Object string;
8970 	
8971 		  kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
8972 		  if (EQ (kind, Qmouse_click))
8973 		    {
8974 		      Lisp_Object window, posn;
8975 	
8976 		      window = POSN_WINDOW      (EVENT_START (key));
8977 		      posn   = POSN_POSN (EVENT_START (key));
8978 	
8979 		      if (CONSP (posn)
8980 			  || (!NILP (fake_prefixed_keys)
8981 			      && !NILP (Fmemq (key, fake_prefixed_keys))))
8982 			{
8983 			  /* We're looking a second time at an event for which
8984 			     we generated a fake prefix key.  Set
8985 			     last_real_key_start appropriately.  */
8986 			  if (t > 0)
8987 			    last_real_key_start = t - 1;
8988 			}
8989 	
8990 		      /* Key sequences beginning with mouse clicks are
8991 			 read using the keymaps in the buffer clicked on,
8992 			 not the current buffer.  If we're at the
8993 			 beginning of a key sequence, switch buffers.  */
8994 		      if (last_real_key_start == 0
8995 			  && WINDOWP (window)
8996 			  && BUFFERP (XWINDOW (window)->buffer)
8997 			  && XBUFFER (XWINDOW (window)->buffer) != current_buffer)
8998 			{
8999 			  XVECTOR (raw_keybuf)->contents[raw_keybuf_count++] = key;
9000 			  keybuf[t] = key;
9001 			  mock_input = t + 1;
9002 	
9003 			  /* Arrange to go back to the original buffer once we're
9004 			     done reading the key sequence.  Note that we can't
9005 			     use save_excursion_{save,restore} here, because they
9006 			     save point as well as the current buffer; we don't
9007 			     want to save point, because redisplay may change it,
9008 			     to accommodate a Fset_window_start or something.  We
9009 			     don't want to do this at the top of the function,
9010 			     because we may get input from a subprocess which
9011 			     wants to change the selected window and stuff (say,
9012 			     emacsclient).  */
9013 			  record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
9014 	
9015 			  if (! FRAME_LIVE_P (XFRAME (selected_frame)))
9016 			    Fkill_emacs (Qnil);
9017 			  set_buffer_internal (XBUFFER (XWINDOW (window)->buffer));
9018 			  orig_local_map = get_local_map (PT, current_buffer,
9019 							  Qlocal_map);
9020 			  orig_keymap = get_local_map (PT, current_buffer, Qkeymap);
9021 			  goto replay_sequence;
9022 			}
9023 	
9024 		      /* For a mouse click, get the local text-property keymap
9025 			 of the place clicked on, rather than point.  */
9026 		      if (last_real_key_start == 0
9027 			  && CONSP (XCDR (key))
9028 			  && ! localized_local_map)
9029 			{
9030 			  Lisp_Object map_here, start, pos;
9031 	
9032 			  localized_local_map = 1;
9033 			  start = EVENT_START (key);
9034 	
9035 			  if (CONSP (start) && POSN_INBUFFER_P (start))
9036 			    {
9037 			      pos = POSN_BUFFER_POSN (start);
9038 			      if (INTEGERP (pos)
9039 				  && XINT (pos) >= BEG && XINT (pos) <= Z)
9040 				{
9041 				  map_here = get_local_map (XINT (pos),
9042 							    current_buffer, Qlocal_map);
9043 				  if (!EQ (map_here, orig_local_map))
9044 				    {
9045 				      orig_local_map = map_here;
9046 				      keybuf[t] = key;
9047 				      mock_input = t + 1;
9048 	
9049 				      goto replay_sequence;
9050 				    }
9051 				  map_here = get_local_map (XINT (pos),
9052 							     current_buffer, Qkeymap);
9053 				  if (!EQ (map_here, orig_keymap))
9054 				    {
9055 				      orig_keymap = map_here;
9056 				      keybuf[t] = key;
9057 				      mock_input = t + 1;
9058 	
9059 				      goto replay_sequence;
9060 				    }
9061 				}
9062 			    }
9063 			}
9064 	
9065 		      /* Expand mode-line and scroll-bar events into two events:
9066 			 use posn as a fake prefix key.  */
9067 		      if (SYMBOLP (posn)
9068 			  && (NILP (fake_prefixed_keys)
9069 			      || NILP (Fmemq (key, fake_prefixed_keys))))
9070 			{
9071 			  if (t + 1 >= bufsize)
9072 			    error ("Key sequence too long");
9073 	
9074 			  keybuf[t]     = posn;
9075 			  keybuf[t + 1] = key;
9076 			  mock_input    = t + 2;
9077 	
9078 			  /* Record that a fake prefix key has been generated
9079 			     for KEY.  Don't modify the event; this would
9080 			     prevent proper action when the event is pushed
9081 			     back into unread-command-events.  */
9082 			  fake_prefixed_keys = Fcons (key, fake_prefixed_keys);
9083 	
9084 			  /* If on a mode line string with a local keymap,
9085 			     reconsider the key sequence with that keymap.  */
9086 			  if (string = POSN_STRING (EVENT_START (key)),
9087 			      (CONSP (string) && STRINGP (XCAR (string))))
9088 			    {
9089 			      Lisp_Object pos, map, map2;
9090 	
9091 			      pos = XCDR (string);
9092 			      string = XCAR (string);
9093 	                      if (XINT (pos) >= 0
9094 				  && XINT (pos) < SCHARS (string))
9095 	                        {
9096 	                          map = Fget_text_property (pos, Qlocal_map, string);
9097 	                          if (!NILP (map))
9098 	                            orig_local_map = map;
9099 	                          map2 = Fget_text_property (pos, Qkeymap, string);
9100 	                          if (!NILP (map2))
9101 	                            orig_keymap = map2;
9102 	                          if (!NILP (map) || !NILP (map2))
9103 	                            goto replay_sequence;
9104 	                        }
9105 			    }
9106 	
9107 			  goto replay_key;
9108 			}
9109 		      else if (NILP (from_string)
9110 			       && (string = POSN_STRING (EVENT_START (key)),
9111 				   (CONSP (string) && STRINGP (XCAR (string)))))
9112 			{
9113 			  /* For a click on a string, i.e. overlay string or a
9114 			     string displayed via the `display' property,
9115 			     consider `local-map' and `keymap' properties of
9116 			     that string.  */
9117 			  Lisp_Object pos, map, map2;
9118 	
9119 			  pos = XCDR (string);
9120 			  string = XCAR (string);
9121 			  if (XINT (pos) >= 0
9122 			      && XINT (pos) < SCHARS (string))
9123 			    {
9124 			      map = Fget_text_property (pos, Qlocal_map, string);
9125 			      if (!NILP (map))
9126 				orig_local_map = map;
9127 			      map2 = Fget_text_property (pos, Qkeymap, string);
9128 			      if (!NILP (map2))
9129 				orig_keymap = map2;
9130 	
9131 			      if (!NILP (map) || !NILP (map2))
9132 				{
9133 				  from_string = string;
9134 				  goto replay_sequence;
9135 				}
9136 			    }
9137 			}
9138 		    }
9139 		  else if (CONSP (XCDR (key))
9140 			   && CONSP (EVENT_START (key))
9141 			   && CONSP (XCDR (EVENT_START (key))))
9142 		    {
9143 		      Lisp_Object posn;
9144 	
9145 		      posn = POSN_POSN (EVENT_START (key));
9146 		      /* Handle menu-bar events:
9147 			 insert the dummy prefix event `menu-bar'.  */
9148 		      if (EQ (posn, Qmenu_bar) || EQ (posn, Qtool_bar))
9149 			{
9150 			  if (t + 1 >= bufsize)
9151 			    error ("Key sequence too long");
9152 			  keybuf[t] = posn;
9153 			  keybuf[t+1] = key;
9154 	
9155 			  /* Zap the position in key, so we know that we've
9156 			     expanded it, and don't try to do so again.  */
9157 			  POSN_SET_POSN (EVENT_START (key),
9158 					 Fcons (posn, Qnil));
9159 	
9160 			  mock_input = t + 2;
9161 			  goto replay_sequence;
9162 			}
9163 		      else if (CONSP (posn))
9164 			{
9165 			  /* We're looking at the second event of a
9166 			     sequence which we expanded before.  Set
9167 			     last_real_key_start appropriately.  */
9168 			  if (last_real_key_start == t && t > 0)
9169 			    last_real_key_start = t - 1;
9170 			}
9171 		    }
9172 		}
9173 	
9174 	      /* We have finally decided that KEY is something we might want
9175 		 to look up.  */
9176 	      first_binding = (follow_key (key,
9177 					   nmaps   - first_binding,
9178 					   submaps + first_binding,
9179 					   defs    + first_binding,
9180 					   submaps + first_binding)
9181 			       + first_binding);
9182 	
9183 	      /* If KEY wasn't bound, we'll try some fallbacks.  */
9184 	      if (first_binding < nmaps)
9185 		/* This is needed for the following scenario:
9186 		   event 0: a down-event that gets dropped by calling replay_key.
9187 		   event 1: some normal prefix like C-h.
9188 		   After event 0, first_unbound is 0, after event 1 fkey.start
9189 		   and keytran.start are both 1, so when we see that C-h is bound,
9190 		   we need to update first_unbound.  */
9191 		first_unbound = max (t + 1, first_unbound);
9192 	      else
9193 		{
9194 		  Lisp_Object head;
9195 	
9196 		  /* Remember the position to put an upper bound on fkey.start.  */
9197 		  first_unbound = min (t, first_unbound);
9198 	
9199 		  head = EVENT_HEAD (key);
9200 		  if (help_char_p (head) && t > 0)
9201 		    {
9202 		      read_key_sequence_cmd = Vprefix_help_command;
9203 		      keybuf[t++] = key;
9204 		      last_nonmenu_event = key;
9205 		      /* The Microsoft C compiler can't handle the goto that
9206 			 would go here.  */
9207 		      dummyflag = 1;
9208 		      break;
9209 		    }
9210 	
9211 		  if (SYMBOLP (head))
9212 		    {
9213 		      Lisp_Object breakdown;
9214 		      int modifiers;
9215 	
9216 		      breakdown = parse_modifiers (head);
9217 		      modifiers = XINT (XCAR (XCDR (breakdown)));
9218 		      /* Attempt to reduce an unbound mouse event to a simpler
9219 			 event that is bound:
9220 			   Drags reduce to clicks.
9221 			   Double-clicks reduce to clicks.
9222 			   Triple-clicks reduce to double-clicks, then to clicks.
9223 			   Down-clicks are eliminated.
9224 			   Double-downs reduce to downs, then are eliminated.
9225 			   Triple-downs reduce to double-downs, then to downs,
9226 			     then are eliminated. */
9227 		      if (modifiers & (down_modifier | drag_modifier
9228 				       | double_modifier | triple_modifier))
9229 			{
9230 			  while (modifiers & (down_modifier | drag_modifier
9231 					      | double_modifier | triple_modifier))
9232 			    {
9233 			      Lisp_Object new_head, new_click;
9234 			      if (modifiers & triple_modifier)
9235 				modifiers ^= (double_modifier | triple_modifier);
9236 			      else if (modifiers & double_modifier)
9237 				modifiers &= ~double_modifier;
9238 			      else if (modifiers & drag_modifier)
9239 				modifiers &= ~drag_modifier;
9240 			      else
9241 				{
9242 				  /* Dispose of this `down' event by simply jumping
9243 				     back to replay_key, to get another event.
9244 	
9245 				     Note that if this event came from mock input,
9246 				     then just jumping back to replay_key will just
9247 				     hand it to us again.  So we have to wipe out any
9248 				     mock input.
9249 	
9250 				     We could delete keybuf[t] and shift everything
9251 				     after that to the left by one spot, but we'd also
9252 				     have to fix up any variable that points into
9253 				     keybuf, and shifting isn't really necessary
9254 				     anyway.
9255 	
9256 				     Adding prefixes for non-textual mouse clicks
9257 				     creates two characters of mock input, and both
9258 				     must be thrown away.  If we're only looking at
9259 				     the prefix now, we can just jump back to
9260 				     replay_key.  On the other hand, if we've already
9261 				     processed the prefix, and now the actual click
9262 				     itself is giving us trouble, then we've lost the
9263 				     state of the keymaps we want to backtrack to, and
9264 				     we need to replay the whole sequence to rebuild
9265 				     it.
9266 	
9267 				     Beyond that, only function key expansion could
9268 				     create more than two keys, but that should never
9269 				     generate mouse events, so it's okay to zero
9270 				     mock_input in that case too.
9271 	
9272 				     FIXME: The above paragraph seems just plain
9273 				     wrong, if you consider things like
9274 				     xterm-mouse-mode.  -stef
9275 	
9276 				     Isn't this just the most wonderful code ever?  */
9277 	
9278 				  /* If mock_input > t + 1, the above simplification
9279 				     will actually end up dropping keys on the floor.
9280 				     This is probably OK for now, but even
9281 				     if mock_input <= t + 1, we need to adjust fkey
9282 				     and keytran.
9283 				     Typical case [header-line down-mouse-N]:
9284 				     mock_input = 2, t = 1, fkey.end = 1,
9285 				     last_real_key_start = 0.  */
9286 				  if (fkey.end > last_real_key_start)
9287 				    {
9288 				      fkey.end = fkey.start
9289 					= min (last_real_key_start, fkey.start);
9290 				      fkey.map = fkey.parent;
9291 				      if (keytran.end > last_real_key_start)
9292 					{
9293 					  keytran.end = keytran.start
9294 					    = min (last_real_key_start, keytran.start);
9295 					  keytran.map = keytran.parent;
9296 					}
9297 				    }
9298 				  if (t == last_real_key_start)
9299 				    {
9300 				      mock_input = 0;
9301 				      goto replay_key;
9302 				    }
9303 				  else
9304 				    {
9305 				      mock_input = last_real_key_start;
9306 				      goto replay_sequence;
9307 				    }
9308 				}
9309 	
9310 			      new_head
9311 				= apply_modifiers (modifiers, XCAR (breakdown));
9312 			      new_click
9313 				= Fcons (new_head, Fcons (EVENT_START (key), Qnil));
9314 	
9315 			      /* Look for a binding for this new key.  follow_key
9316 				 promises that it didn't munge submaps the
9317 				 last time we called it, since key was unbound.  */
9318 			      first_binding
9319 				= (follow_key (new_click,
9320 					       nmaps   - local_first_binding,
9321 					       submaps + local_first_binding,
9322 					       defs    + local_first_binding,
9323 					       submaps + local_first_binding)
9324 				   + local_first_binding);
9325 	
9326 			      /* If that click is bound, go for it.  */
9327 			      if (first_binding < nmaps)
9328 				{
9329 				  key = new_click;
9330 				  break;
9331 				}
9332 			      /* Otherwise, we'll leave key set to the drag event.  */
9333 			    }
9334 			}
9335 		    }
9336 		}
9337 	
9338 	      keybuf[t++] = key;
9339 	      /* Normally, last_nonmenu_event gets the previous key we read.
9340 		 But when a mouse popup menu is being used,
9341 		 we don't update last_nonmenu_event; it continues to hold the mouse
9342 		 event that preceded the first level of menu.  */
9343 	      if (!used_mouse_menu)
9344 		last_nonmenu_event = key;
9345 	
9346 	      /* Record what part of this_command_keys is the current key sequence.  */
9347 	      this_single_command_key_start = this_command_key_count - t;
9348 	
9349 	      if (first_binding < nmaps && NILP (submaps[first_binding]))
9350 		/* There is a binding and it's not a prefix.
9351 		   There is thus no function-key in this sequence.
9352 		   Moving fkey.start is important in this case to allow keytran.start
9353 		   to go over the sequence before we return (since we keep the
9354 		   invariant that keytran.end <= fkey.start).  */
9355 		{
9356 		  if (fkey.start < t)
9357 		    (fkey.start = fkey.end = t, fkey.map = fkey.parent);
9358 		}
9359 	      else
9360 		/* If the sequence is unbound, see if we can hang a function key
9361 		   off the end of it.  */
9362 		/* Continue scan from fkey.end until we find a bound suffix.  */
9363 		while (fkey.end < t)
9364 		  {
9365 		    struct gcpro gcpro1, gcpro2, gcpro3;
9366 		    int done, diff;
9367 	
9368 		    GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
9369 		    done = keyremap_step (keybuf, bufsize, &fkey,
9370 					  max (t, mock_input),
9371 					  /* If there's a binding (i.e.
9372 					     first_binding >= nmaps) we don't want
9373 					     to apply this function-key-mapping.  */
9374 					  fkey.end + 1 == t && first_binding >= nmaps,
9375 					  &diff, prompt);
9376 		    UNGCPRO;
9377 		    if (done)
9378 		      {
9379 			mock_input = diff + max (t, mock_input);
9380 			goto replay_sequence;
9381 		      }
9382 		  }
9383 	
9384 	      /* Look for this sequence in key-translation-map.
9385 		 Scan from keytran.end until we find a bound suffix.  */
9386 	      while (keytran.end < fkey.start)
9387 		{
9388 		  struct gcpro gcpro1, gcpro2, gcpro3;
9389 		  int done, diff;
9390 	
9391 		  GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
9392 		  done = keyremap_step (keybuf, bufsize, &keytran, max (t, mock_input),
9393 					1, &diff, prompt);
9394 		  UNGCPRO;
9395 		  if (done)
9396 		    {
9397 		      mock_input = diff + max (t, mock_input);
9398 		      /* Adjust the function-key-map counters.  */
9399 		      fkey.end += diff;
9400 		      fkey.start += diff;
9401 	
9402 		      goto replay_sequence;
9403 		    }
9404 		}
9405 	
9406 	      /* If KEY is not defined in any of the keymaps,
9407 		 and cannot be part of a function key or translation,
9408 		 and is an upper case letter
9409 		 use the corresponding lower-case letter instead.  */
9410 	      if (first_binding >= nmaps
9411 		  && fkey.start >= t && keytran.start >= t
9412 		  && INTEGERP (key)
9413 		  && ((((XINT (key) & 0x3ffff)
9414 			< XCHAR_TABLE (current_buffer->downcase_table)->size)
9415 		       && UPPERCASEP (XINT (key) & 0x3ffff))
9416 		      || (XINT (key) & shift_modifier)))
9417 		{
9418 		  Lisp_Object new_key;
9419 	
9420 		  original_uppercase = key;
9421 		  original_uppercase_position = t - 1;
9422 	
9423 		  if (XINT (key) & shift_modifier)
9424 		    XSETINT (new_key, XINT (key) & ~shift_modifier);
9425 		  else
9426 		    XSETINT (new_key, (DOWNCASE (XINT (key) & 0x3ffff)
9427 				       | (XINT (key) & ~0x3ffff)));
9428 	
9429 		  /* We have to do this unconditionally, regardless of whether
9430 		     the lower-case char is defined in the keymaps, because they
9431 		     might get translated through function-key-map.  */
9432 		  keybuf[t - 1] = new_key;
9433 		  mock_input = max (t, mock_input);
9434 	
9435 		  goto replay_sequence;
9436 		}
9437 	      /* If KEY is not defined in any of the keymaps,
9438 		 and cannot be part of a function key or translation,
9439 		 and is a shifted function key,
9440 		 use the corresponding unshifted function key instead.  */
9441 	      if (first_binding >= nmaps
9442 		  && fkey.start >= t && keytran.start >= t
9443 		  && SYMBOLP (key))
9444 		{
9445 		  Lisp_Object breakdown;
9446 		  int modifiers;
9447 	
9448 		  breakdown = parse_modifiers (key);
9449 		  modifiers = XINT (XCAR (XCDR (breakdown)));
9450 		  if (modifiers & shift_modifier)
9451 		    {
9452 		      Lisp_Object new_key;
9453 	
9454 		      original_uppercase = key;
9455 		      original_uppercase_position = t - 1;
9456 	
9457 		      modifiers &= ~shift_modifier;
9458 		      new_key = apply_modifiers (modifiers,
9459 						 XCAR (breakdown));
9460 	
9461 		      keybuf[t - 1] = new_key;
9462 		      mock_input = max (t, mock_input);
9463 		      fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
9464 		      keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
9465 	
9466 		      goto replay_sequence;
9467 		    }
9468 		}
9469 	    }
9470 	

At conditional (19): "dummyflag == 0" taking false path

9471 	  if (!dummyflag)
9472 	    read_key_sequence_cmd = (first_binding < nmaps
9473 				     ? defs[first_binding]
9474 				     : Qnil);
9475 	
9476 	  unread_switch_frame = delayed_switch_frame;
9477 	  unbind_to (count, Qnil);
9478 	
9479 	  /* Don't downcase the last character if the caller says don't.
9480 	     Don't downcase it if the result is undefined, either.  */

At conditional (20): "dont_downcase_last != 0" taking true path
At conditional (21): "(t - 1) == original_uppercase_position" taking true path

9481 	  if ((dont_downcase_last || first_binding >= nmaps)
9482 	      && t - 1 == original_uppercase_position)

Event uninit_use: Using uninitialized value "original_uppercase"
Also see events: [var_decl]

9483 	    keybuf[t - 1] = original_uppercase;
9484 	

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem report #60
  2006-04-11 15:48 Problem report #60 Dan Nicolaescu
@ 2006-04-11 17:54 ` Stuart D. Herring
  2006-04-11 18:02   ` David Kastrup
  2006-04-12 17:10   ` Richard Stallman
  0 siblings, 2 replies; 6+ messages in thread
From: Stuart D. Herring @ 2006-04-11 17:54 UTC (permalink / raw)


> 8608 	  volatile Lisp_Object original_uppercase;
> 8609 	  volatile int original_uppercase_position = -1;
> [...]

original_uppercase_position remains -1 if original_uppercase is
uninitialized.

> At conditional (20): "dont_downcase_last != 0" taking true path
> At conditional (21): "(t - 1) == original_uppercase_position" taking true
> path
>
> 9481 	  if ((dont_downcase_last || first_binding >= nmaps)
> 9482 	      && t - 1 == original_uppercase_position)

Assuming that t!=0, t-1==original_uppercase_position implies that the o_u
variables were set.

> Event uninit_use: Using uninitialized value "original_uppercase"
> Also see events: [var_decl]
>
> 9483 	    keybuf[t - 1] = original_uppercase;
> 9484

So this is fine.  It'd be a big bug if t were 0, though, indexing at -1
like that.  Looking back up, it seems that if the while loop iterates even
once, t is > 0, but what if the while test fails the first time?  It looks
like t would be 0, and original_uppercase_position would still be -1, and
uninitialized data would be stored outside of an array.  Nasty, if it can
happen.  Otherwise, no bug.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem report #60
  2006-04-11 17:54 ` Stuart D. Herring
@ 2006-04-11 18:02   ` David Kastrup
  2006-04-12 17:10   ` Richard Stallman
  1 sibling, 0 replies; 6+ messages in thread
From: David Kastrup @ 2006-04-11 18:02 UTC (permalink / raw)
  Cc: emacs-devel

"Stuart D. Herring" <herring@lanl.gov> writes:

>> 8608 	  volatile Lisp_Object original_uppercase;
>> 8609 	  volatile int original_uppercase_position = -1;
>> [...]
>
> original_uppercase_position remains -1 if original_uppercase is
> uninitialized.
>
>> At conditional (20): "dont_downcase_last != 0" taking true path
>> At conditional (21): "(t - 1) == original_uppercase_position" taking true
>> path
>>
>> 9481 	  if ((dont_downcase_last || first_binding >= nmaps)
>> 9482 	      && t - 1 == original_uppercase_position)
>
> Assuming that t!=0, t-1==original_uppercase_position implies that the o_u
> variables were set.
>
>> Event uninit_use: Using uninitialized value "original_uppercase"
>> Also see events: [var_decl]
>>
>> 9483 	    keybuf[t - 1] = original_uppercase;
>> 9484
>
> So this is fine.  It'd be a big bug if t were 0, though, indexing at -1
> like that.  Looking back up, it seems that if the while loop iterates even
> once, t is > 0, but what if the while test fails the first time?  It looks
> like t would be 0, and original_uppercase_position would still be -1, and
> uninitialized data would be stored outside of an array.  Nasty, if it can
> happen.  Otherwise, no bug.

Then this should not be written as

while (condition)
{ body
}

but rather

assert(condition);
do { body
} while (condition);

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem report #60
  2006-04-11 17:54 ` Stuart D. Herring
  2006-04-11 18:02   ` David Kastrup
@ 2006-04-12 17:10   ` Richard Stallman
  2006-04-12 17:29     ` Stuart D. Herring
  1 sibling, 1 reply; 6+ messages in thread
From: Richard Stallman @ 2006-04-12 17:10 UTC (permalink / raw)
  Cc: emacs-devel

    So this is fine.  It'd be a big bug if t were 0, though, indexing at -1
    like that.  Looking back up, it seems that if the while loop iterates even
    once, t is > 0, but what if the while test fails the first time?

Which while test is that?  Which line number?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem report #60
  2006-04-12 17:10   ` Richard Stallman
@ 2006-04-12 17:29     ` Stuart D. Herring
  2006-04-13  3:20       ` Richard Stallman
  0 siblings, 1 reply; 6+ messages in thread
From: Stuart D. Herring @ 2006-04-12 17:29 UTC (permalink / raw)
  Cc: emacs-devel

>     So this is fine.  It'd be a big bug if t were 0, though, indexing at
> -1
>     like that.  Looking back up, it seems that if the while loop iterates
> even
>     once, t is > 0, but what if the while test fails the first time?
>
> Which while test is that?  Which line number?

The while test starts at like 8745 in the problem report (the loop ends at
line 9469).  t is incremented unconditionally at line 9338, and the
dangerous indexing/use is at line 9483.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Problem report #60
  2006-04-12 17:29     ` Stuart D. Herring
@ 2006-04-13  3:20       ` Richard Stallman
  0 siblings, 0 replies; 6+ messages in thread
From: Richard Stallman @ 2006-04-13  3:20 UTC (permalink / raw)
  Cc: emacs-devel

I concluded this bug can really happen, and added a simple
conditional to fix it.

Thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2006-04-13  3:20 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-11 15:48 Problem report #60 Dan Nicolaescu
2006-04-11 17:54 ` Stuart D. Herring
2006-04-11 18:02   ` David Kastrup
2006-04-12 17:10   ` Richard Stallman
2006-04-12 17:29     ` Stuart D. Herring
2006-04-13  3:20       ` Richard Stallman

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.