[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH].infokey feature and signal handling are broken
From: |
AIDA Shinra |
Subject: |
[PATCH].infokey feature and signal handling are broken |
Date: |
Mon, 02 Dec 2002 01:06:37 +0900 |
User-agent: |
Wanderlust/2.8.1 (Something) SEMI/1.14.3 (Ushinoya) FLIM/1.14.3 (UnebigoryĆmae) APEL/10.3 MULE XEmacs/21.4 (patch 6) (Common Lisp) (i386-unknown-freebsd4.6) |
I found infokey feature is broken:
* "info infokey" says key bindings in .info take precedence over
the default mapping, but this is not true. Only bindings to
undefined keys take effects.
* Binding to "invalid" action results crash.
* No code to disable prefix keys. Some users might want to bind
escape or C-x to a non-prefix key, but this does not allowed.
In addition, when I 'C-z', 'fg' and then 'q' on my FreeBSD box,
some of my terminal settings break. I found SIGCONT handler was
invoked before SIGTSTP handler waked up. It seemd to be a reentrance
problem.
This patch fixes these problems. It always allows '^h' in incremental
search. Some terminals map 'backspace' to '^h' by default.
AIDA Shinra
Index: freebsd/src/contrib/texinfo/info/infomap.c
diff -u freebsd/src/contrib/texinfo/info/infomap.c:1.1.1.1
freebsd/src/contrib/texinfo/info/infomap.c:1.6
--- freebsd/src/contrib/texinfo/info/infomap.c:1.1.1.1 Sun Jun 9 03:33:00 2002
+++ freebsd/src/contrib/texinfo/info/infomap.c Sun Dec 1 23:12:41 2002
@@ -59,47 +59,154 @@
return (keymap);
}
+#if defined(INFOKEY)
+static FUNCTION_KEYSEQ *
+find_function_keyseq (map, c, rootmap)
+ Keymap map;
+ int c;
+ Keymap rootmap;
+{
+ FUNCTION_KEYSEQ *k;
+
+ if (map[c].type != ISFUNC)
+ abort();
+ if (map[c].function == NULL)
+ return NULL;
+ for (k = map[c].function->keys; k; k = k->next)
+ {
+ const unsigned char *p;
+ Keymap m = rootmap;
+ if (k->map != rootmap)
+ continue;
+ for (p = k->keyseq; *p && m[*p].type == ISKMAP; p++)
+ m = (Keymap)m[*p].function;
+ if (*p != c || p[1])
+ continue;
+ if (m[*p].type != ISFUNC)
+ abort ();
+ break;
+ }
+ return k;
+}
+
+static void
+add_function_keyseq (function, keyseq, rootmap)
+ InfoCommand *function;
+ const unsigned char *keyseq;
+ Keymap rootmap;
+{
+ FUNCTION_KEYSEQ *ks;
+
+ if (function == NULL ||
+ function == InfoCmd(info_do_lowercase_version) ||
+ function == InfoCmd(ea_insert))
+ return;
+ ks = (FUNCTION_KEYSEQ *)xmalloc (sizeof(FUNCTION_KEYSEQ));
+ ks->next = function->keys;
+ ks->map = rootmap;
+ ks->keyseq = xstrdup(keyseq);
+ function->keys = ks;
+}
+
+static void
+remove_function_keyseq (function, keyseq, rootmap)
+ InfoCommand *function;
+ const unsigned char *keyseq;
+ Keymap rootmap;
+{
+
+ FUNCTION_KEYSEQ *k, *kp;
+
+ if (function == NULL ||
+ function == InfoCmd(info_do_lowercase_version) ||
+ function == InfoCmd(ea_insert))
+ return;
+ for (kp = NULL, k = function->keys; k; kp = k, k = k->next)
+ if (k->map == rootmap && strcmp(k->keyseq, keyseq) == 0)
+ break;
+ if (!k)
+ abort ();
+ if (kp)
+ kp->next = k->next;
+ else
+ function->keys = k->next;
+}
+#endif /* INFOKEY */
+
/* Return a new keymap which is a copy of MAP. */
Keymap
-keymap_copy_keymap (map)
- Keymap map;
+keymap_copy_keymap (map, rootmap, newroot)
+ Keymap map;
+ Keymap rootmap;
+ Keymap newroot;
{
int i;
Keymap keymap;
+#if defined(INFOKEY)
+ FUNCTION_KEYSEQ *ks;
+#endif /* INFOKEY */
keymap = keymap_make_keymap ();
+ if (!newroot)
+ newroot = keymap;
for (i = 0; i < 256; i++)
{
keymap[i].type = map[i].type;
- keymap[i].function = map[i].function;
+ switch (map[i].type)
+ {
+ case ISFUNC:
+ keymap[i].function = map[i].function;
+#if defined(INFOKEY)
+ ks = find_function_keyseq (map, i, rootmap, NULL);
+ if (ks)
+ add_function_keyseq(map[i].function, ks->keyseq, newroot);
+#endif /* INFOKEY */
+ break;
+ case ISKMAP:
+ keymap[i].function = (InfoCommand *)keymap_copy_keymap (
+ (Keymap)map[i].function, rootmap);
+ break;
+ }
}
return (keymap);
}
/* Free the keymap and its descendants. */
void
-keymap_discard_keymap (map)
- Keymap (map);
+keymap_discard_keymap (map, rootmap)
+ Keymap map;
+ Keymap rootmap;
{
int i;
if (!map)
return;
+ if (!rootmap)
+ rootmap = map;
for (i = 0; i < 256; i++)
{
+#if defined(INFOKEY)
+ FUNCTION_KEYSEQ *ks;
+#endif /* INFOKEY */
switch (map[i].type)
{
case ISFUNC:
+#if defined(INFOKEY)
+ ks = find_function_keyseq(map, i, rootmap);
+ if (ks)
+ remove_function_keyseq (map[i].function, ks->keyseq, rootmap);
+#endif /* INFOKEY */
break;
case ISKMAP:
- keymap_discard_keymap ((Keymap)map[i].function);
+ keymap_discard_keymap ((Keymap)map[i].function, rootmap);
break;
}
}
+ free(map);
}
/* Conditionally bind key sequence. */
@@ -117,16 +224,23 @@
while ((c = *s++) != '\0')
{
+#if defined(INFOKEY)
+ FUNCTION_KEYSEQ *ks;
+#endif /* INFOKEY */
switch (m[c].type)
{
case ISFUNC:
+#if defined(INFOKEY)
+ ks = find_function_keyseq(m, c, map);
+ if (ks)
+ remove_function_keyseq (m[c].function, ks->keyseq, map);
+#else /* !INFOKEY */
if (!(m[c].function == NULL || (
-#if !defined(INFOKEY)
m != map &&
-#endif /* !INFOKEY */
m[c].function == InfoCmd(info_do_lowercase_version))
))
return 0;
+#endif /* !INFOKEY */
if (*s != '\0')
{
@@ -136,8 +250,13 @@
break;
case ISKMAP:
+#if defined(INFOKEY)
+ if (*s == '\0')
+ keymap_discard_keymap ((Keymap)m[c].function, map);
+#else /* !INFOKEY */
if (*s == '\0')
return 0;
+#endif
break;
}
if (*s != '\0')
@@ -147,18 +266,7 @@
else
{
#if defined(INFOKEY)
- FUNCTION_KEYSEQ *k;
-
- for (k = keyentry->function->keys; k && k->map != map; k = k->next)
- ;
- if (!k)
- {
- FUNCTION_KEYSEQ *ks = (FUNCTION_KEYSEQ *)xmalloc
(sizeof(FUNCTION_KEYSEQ));
- ks->next = keyentry->function->keys;
- ks->map = map;
- ks->keyseq = xstrdup (keyseq);
- keyentry->function->keys = ks;
- }
+ add_function_keyseq (keyentry->function, keyseq, map);
#endif /* INFOKEY */
m[c] = *keyentry;
}
@@ -1722,3 +1830,4 @@
}
#endif /* defined(INFOKEY) */
+/* vim: set sw=2 cino={1s>2sn-s^-se-s: */
Index: freebsd/src/contrib/texinfo/info/session.c
diff -u freebsd/src/contrib/texinfo/info/session.c:1.1.1.1
freebsd/src/contrib/texinfo/info/session.c:1.3
--- freebsd/src/contrib/texinfo/info/session.c:1.1.1.1 Sun Jun 9 03:33:00 2002
+++ freebsd/src/contrib/texinfo/info/session.c Sun Dec 1 01:48:49 2002
@@ -3937,7 +3937,7 @@
key = info_get_input_char ();
window_get_state (window, &mystate);
- if (key == DEL)
+ if (key == DEL || key == Control ('h'))
{
/* User wants to delete one level of search? */
if (!isearch_states_index)
Index: freebsd/src/contrib/texinfo/info/signals.c
diff -u freebsd/src/contrib/texinfo/info/signals.c:1.1.1.1
freebsd/src/contrib/texinfo/info/signals.c:1.5
--- freebsd/src/contrib/texinfo/info/signals.c:1.1.1.1 Mon Jan 17 19:46:55 2000
+++ freebsd/src/contrib/texinfo/info/signals.c Mon Dec 2 00:45:43 2002
@@ -29,9 +29,6 @@
/* */
/* **************************************************************** */
-/* Non-zero when our signal handler has been called to handle SIGWINCH. */
-static int in_sigwinch = 0;
-
#if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
static void
@@ -64,35 +61,88 @@
/* */
/* **************************************************************** */
-typedef RETSIGTYPE signal_handler ();
+#if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\
+ defined (HAVE_SIGSETMASK)
+static void
+mask_termsig (set)
+ sigset_t *set;
+{
+# if defined (SIGTSTP)
+ sigaddset (set, SIGTSTP);
+ sigaddset (set, SIGTTOU);
+ sigaddset (set, SIGTTIN);
+# endif
+# if defined (SIGWINCH)
+ sigaddset (set, SIGWINCH);
+# endif
+#if defined (SIGINT)
+ sigaddset (set, SIGINT);
+#endif
+# if defined (SIGUSR1)
+ sigaddset (set, SIGUSR1);
+# endif
+}
+#endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
-static RETSIGTYPE info_signal_handler ();
-static signal_handler *old_TSTP, *old_TTOU, *old_TTIN;
-static signal_handler *old_WINCH, *old_INT, *old_USR1, *old_CONT;
+static RETSIGTYPE info_signal_proc ();
+#if defined (HAVE_SIGACTION)
+typedef struct sigaction signal_info;
+signal_info info_signal_handler = {
+ info_signal_proc,
+ 0, /* set later */
+ 0
+};
+
+static void
+set_termsig (sig, old)
+ int sig;
+ signal_info *old;
+{
+ sigaction (sig, info_signal_handler, old);
+}
+
+static void
+restore_termsig (sig, saved)
+ int sig;
+ const signal_info *saved;
+{
+ sigaction (sig, saved, NULL);
+}
+#else /* !HAVE_SIGACTION */
+typedef RETSIGTYPE (*signal_info) ();
+#define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc))
+#define restore_termsig(sig, saved) (void)signal (sig, *(saved))
+#define info_signal_handler info_signal_proc
+static int term_conf_busy = 0;
+#endif /* !HAVE_SIGACTION */
+
+static signal_info old_TSTP, old_TTOU, old_TTIN;
+static signal_info old_WINCH, old_INT, old_USR1;
void
initialize_info_signal_handler ()
{
+#if defined (HAVE_SIGACTION)
+ mask_termsig (&info_signal_handler.sa_mask);
+#endif /* HAVE_SIGACTION */
+
#if defined (SIGTSTP)
- old_TSTP = (signal_handler *) signal (SIGTSTP, info_signal_handler);
- old_TTOU = (signal_handler *) signal (SIGTTOU, info_signal_handler);
- old_TTIN = (signal_handler *) signal (SIGTTIN, info_signal_handler);
+ set_termsig (SIGTSTP, &old_TSTP);
+ set_termsig (SIGTTOU, &old_TTOU);
+ set_termsig (SIGTTIN, &old_TTIN);
#endif /* SIGTSTP */
#if defined (SIGWINCH)
- old_WINCH = (signal_handler *) signal (SIGWINCH, info_signal_handler);
-#if defined (SIGCONT)
- old_CONT = (signal_handler *) signal (SIGCONT, info_signal_handler);
-#endif
+ set_termsig (SIGWINCH, &old_WINCH);
#endif
#if defined (SIGINT)
- old_INT = (signal_handler *) signal (SIGINT, info_signal_handler);
+ set_termsig (SIGINT, &old_INT);
#endif
#if defined (SIGUSR1)
/* Used by DJGPP to simulate SIGTSTP on Ctrl-Z. */
- old_USR1 = (signal_handler *) signal (SIGUSR1, info_signal_handler);
+ set_termsig (SIGUSR1, &old_USR1);
#endif
}
@@ -121,11 +171,25 @@
}
static RETSIGTYPE
-info_signal_handler (sig)
+info_signal_proc (sig)
int sig;
{
- signal_handler **old_signal_handler;
+ signal_info *old_signal_handler;
+#if !defined (HAVE_SIGACTION)
+ /* best effort: first increment this counter and later block signals */
+ if (term_conf_busy)
+ return;
+ term_conf_busy++;
+#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
+ {
+ sigset_t nvar, ovar;
+ sigemptyset (&nvar);
+ mask_termsig (&nvar);
+ sigprocmask (SIG_BLOCK, &nvar, &ovar);
+ }
+#endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
+#endif /* !HAVE_SIGACTION */
switch (sig)
{
#if defined (SIGTSTP)
@@ -145,8 +209,10 @@
if (sig == SIGTTIN)
old_signal_handler = &old_TTIN;
#endif /* SIGTSTP */
+#if defined (SIGINT)
if (sig == SIGINT)
old_signal_handler = &old_INT;
+#endif /* SIGINT */
/* For stop signals, restore the terminal IO, leave the cursor
at the bottom of the window, and stop us. */
@@ -154,67 +220,64 @@
terminal_clear_to_eol ();
fflush (stdout);
terminal_unprep_terminal ();
- signal (sig, *old_signal_handler);
- UNBLOCK_SIGNAL (sig);
- kill (getpid (), sig);
+ restore_termsig (sig, old_signal_handler);
+ UNBLOCK_SIGNAL (sig);
+ kill (getpid (), sig);
/* The program is returning now. Restore our signal handler,
turn on terminal handling, redraw the screen, and place the
cursor where it belongs. */
terminal_prep_terminal ();
- *old_signal_handler = (signal_handler *) signal (sig,
info_signal_handler);
- redisplay_after_signal ();
- fflush (stdout);
+ set_termsig (sig, old_signal_handler);
+ /* window size might be changed while sleeping */
+ reset_info_window_sizes ();
}
break;
#if defined (SIGWINCH) || defined (SIGUSR1)
#ifdef SIGWINCH
-#ifdef SIGCONT
- case SIGCONT:
- /* pretend a SIGWINCH in case the terminal window size has changed
- while we've been asleep */
- /* FALLTHROUGH */
-#endif
case SIGWINCH:
#endif
#ifdef SIGUSR1
case SIGUSR1:
#endif
{
- if (!in_sigwinch) {
- in_sigwinch++;
-
- /* Turn off terminal IO, tell our parent that the window has changed,
- then reinitialize the terminal and rebuild our windows. */
+ /* Turn off terminal IO, tell our parent that the window has changed,
+ then reinitialize the terminal and rebuild our windows. */
#ifdef SIGWINCH
- if (sig == SIGWINCH)
- old_signal_handler = &old_WINCH;
-#ifdef SIGCONT
- else if (sig == SIGCONT)
- old_signal_handler = &old_CONT;
-#endif
+ if (sig == SIGWINCH)
+ old_signal_handler = &old_WINCH;
#endif
#ifdef SIGUSR1
- if (sig == SIGUSR1)
- old_signal_handler = &old_USR1;
+ if (sig == SIGUSR1)
+ old_signal_handler = &old_USR1;
#endif
- terminal_goto_xy (0, 0);
- fflush (stdout);
- terminal_unprep_terminal ();
- signal (sig, *old_signal_handler);
- UNBLOCK_SIGNAL (sig);
- kill (getpid (), sig);
-
- /* After our old signal handler returns... */
- *old_signal_handler
- = (signal_handler *) signal (sig, info_signal_handler);
- terminal_prep_terminal ();
- reset_info_window_sizes ();
- in_sigwinch--;
- }
+ terminal_goto_xy (0, 0);
+ fflush (stdout);
+ terminal_unprep_terminal (); /* needless? */
+ restore_termsig (sig, old_signal_handler);
+ UNBLOCK_SIGNAL (sig);
+ kill (getpid (), sig);
+
+ /* After our old signal handler returns... */
+ set_termsig (sig, old_signal_handler); /* needless? */
+ terminal_prep_terminal ();
+ reset_info_window_sizes ();
}
break;
#endif /* SIGWINCH || SIGUSR1 */
}
+#if !defined (HAVE_SIGACTION)
+ /* at this time it is safer to perform unblock after decrement */
+ term_conf_busy--;
+#if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
+ {
+ sigset_t nvar, ovar;
+ sigemptyset (&nvar);
+ mask_termsig (&nvar);
+ sigprocmask (SIG_UNBLOCK, &nvar, &ovar);
+ }
+#endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
+#endif /* !HAVE_SIGACTION */
}
+/* vim: set sw=2 cino={1s>2sn-s^-se-s: */
- [PATCH].infokey feature and signal handling are broken,
AIDA Shinra <=