bug-bash
[Top][All Lists]
Advanced

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

[PATCH 3/4] Port unwind protection to C23


From: Paul Eggert
Subject: [PATCH 3/4] Port unwind protection to C23
Date: Sun, 26 Mar 2023 16:50:06 -0700

Do not assume that all pointers have the same representation at
the machine level and that address space is linear, as the C
standard does not guarantee this and it is not true on a few
unusual platforms.  Fixing this also uncovered a bug on
conventional 64-bit platforms, where the call 'add_unwind_protect
(pop_scope, should_keep ? "1" : 0)' eventually casts a nonnull
pointer to to an int that is tested against zero to see whether
the pointer was null; this does not work if pointers are 64 bits,
ints are 32 bits, and half the nonnull pointer happens to be all
bits zero.

Strictly speaking, the old code wasn't portable even to C89 on
hypothetical platforms.  However, C23 makes this more urgent since
it removes support for K&R-style function declarations.

Use the generic function type void (*) (void *) for all unwind
cleanups.  When an existing cleanup doesn't already have that
type, change the type if the function is used only as a cleanup,
and add a shim function otherwise.  If the shim is used in more
than one compilation unit, put the shim function next to the
cleanup as an extern function; otherwise, put the shim in the
compilation unit as a static function.

Although this does not finish the job of porting to C23,
one step at a time.

* builtins/mkbuiltins.c, general.h, readline/rltypedefs.h
(_FUNCTION_DEF, Function, VFunction, CPFunction, CPPFunction):
Remove; no longer used, as they are no longer needed.
Their meaning changes in C23 anyway.
* configure.ac (AC_TYPE_INTPTR_T): Use this.
* execute_cmd.c (execute_command_internal):
Remove a 'volatile' that didn't type check and appears to
be a typo anyway.  Perhaps 'void *volatile' was meant, but
in that case the 'volatile' appears to be unnecessary anyway.
* general.h (STREQ, STREQN): Now inline functions instead of
macros; needed for unwind_prot.c now that it passes void *
to STREQ.
* unwind_prot.c (UNWIND_ELT): Use a prototype for head.cleanup.
arg.v is now void *, not char *; this simplifies use.
(without_interrupts): Remove, as this vestigial function just
got in the way of type checking.
---
 builtins/command.def      |   2 +-
 builtins/evalfile.c       |   4 +-
 builtins/evalstring.c     |  35 +++++++++---
 builtins/fc.def           |  10 +++-
 builtins/jobs.def         |   2 +-
 builtins/mkbuiltins.c     |   1 -
 builtins/read.def         |  35 +++++++++---
 builtins/source.def       |   6 +-
 configure.ac              |   1 +
 dispose_cmd.c             |  10 ++++
 dispose_cmd.h             |   2 +
 execute_cmd.c             | 117 +++++++++++++++++++++++++++-----------
 execute_cmd.h             |   3 +
 general.h                 |  22 ++++---
 lib/readline/rltypedefs.h |  21 -------
 pcomplete.c               |  26 ++++++---
 print_cmd.c               |   4 +-
 subst.c                   |   2 +-
 trap.c                    |  10 ++--
 trap.h                    |   8 +--
 unwind_prot.c             |  82 +++++++++++---------------
 unwind_prot.h             |   2 +-
 variables.c               |  11 +++-
 variables.h               |   5 +-
 24 files changed, 254 insertions(+), 167 deletions(-)

diff --git a/builtins/command.def b/builtins/command.def
index e695fdd1..a376131e 100644
--- a/builtins/command.def
+++ b/builtins/command.def
@@ -131,7 +131,7 @@ command_builtin (WORD_LIST *list)
   command->flags |= COMMAND_BUILTIN_FLAGS;
   command->value.Simple->flags |= COMMAND_BUILTIN_FLAGS;
 
-  add_unwind_protect ((char *)dispose_command, command);
+  add_unwind_protect (unwind_dispose_command, command);
   result = execute_command (command);
 
   run_unwind_frame ("command_builtin");
diff --git a/builtins/evalfile.c b/builtins/evalfile.c
index 9b6f4215..46788398 100644
--- a/builtins/evalfile.c
+++ b/builtins/evalfile.c
@@ -247,7 +247,7 @@ file_error_and_exit:
   fa->funcname_a = funcname_a;
   fa->funcname_v = funcname_v;
   if (flags & FEVAL_UNWINDPROT)
-    add_unwind_protect (restore_funcarray_state, fa);
+    add_unwind_protect (unwind_restore_funcarray_state, fa);
 
 #  if defined (DEBUGGER)
   /* Have to figure out a better way to do this when `source' is supplied
@@ -260,7 +260,7 @@ file_error_and_exit:
       tt[0] = '1'; tt[1] = '\0';
       array_push (bash_argc_a, tt);
       if (flags & FEVAL_UNWINDPROT)
-       add_unwind_protect (pop_args, 0);
+       add_unwind_protect (unwind_pop_args, 0);
     }
 #  endif
 #endif
diff --git a/builtins/evalstring.c b/builtins/evalstring.c
index 243becbc..b52a1a26 100644
--- a/builtins/evalstring.c
+++ b/builtins/evalstring.c
@@ -70,14 +70,14 @@ static int cat_file (REDIRECT *);
 
 #if defined (HISTORY)
 static void
-set_history_remembering (void)
+set_history_remembering (void *ignored)
 {
   remember_on_history = enable_history_list;
 }
 #endif
 
 static void
-restore_lastcom (char *x)
+restore_lastcom (void *x)
 {
   FREE (the_printed_command_except_trap);
   the_printed_command_except_trap = x;
@@ -204,6 +204,26 @@ parse_and_execute_cleanup (int old_running_trap)
     parse_and_execute_level = 0;                       /* XXX */
 }
 
+#if defined (HISTORY)
+static void
+unwind_set_current_prompt_level (void *x)
+{
+  set_current_prompt_level ((intptr_t) x);
+}
+#endif
+
+static void
+unwind_pop_stream (void *ignored)
+{
+  pop_stream ();
+}
+
+static void
+unwind_parser_restore_alias (void *ignored)
+{
+  parser_restore_alias ();
+}
+
 static void
 parse_prologue (char *string, int flags, char *tag)
 {
@@ -238,7 +258,8 @@ parse_prologue (char *string, int flags, char *tag)
   if (interactive_shell)
     {
       x = get_current_prompt_level ();
-      add_unwind_protect (set_current_prompt_level, x);
+      add_unwind_protect (unwind_set_current_prompt_level,
+                         (void *) (intptr_t) x);
     }
 
   if (the_printed_command_except_trap)
@@ -247,9 +268,9 @@ parse_prologue (char *string, int flags, char *tag)
       add_unwind_protect (restore_lastcom, lastcom);
     }
 
-  add_unwind_protect (pop_stream, (char *)NULL);
+  add_unwind_protect (unwind_pop_stream, NULL);
   if (parser_expanding_alias ())
-    add_unwind_protect (parser_restore_alias, (char *)NULL);
+    add_unwind_protect (unwind_parser_restore_alias, NULL);
 
   if (orig_string && ((flags & SEVAL_NOFREE) == 0))
     add_unwind_protect (xfree, orig_string);
@@ -455,8 +476,8 @@ parse_and_execute (char *string, const char *from_file, int 
flags)
 
              bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
              begin_unwind_frame ("pe_dispose");
-             add_unwind_protect (dispose_fd_bitmap, bitmap);
-             add_unwind_protect (dispose_command, command);    /* XXX */
+             add_unwind_protect (unwind_dispose_fd_bitmap, bitmap);
+             add_unwind_protect (unwind_dispose_command, command); /* XXX */
 
              global_command = (COMMAND *)NULL;
 
diff --git a/builtins/fc.def b/builtins/fc.def
index 06f0f610..94a5ded6 100644
--- a/builtins/fc.def
+++ b/builtins/fc.def
@@ -167,7 +167,7 @@ static void fc_addhist (char *);
 #endif
 
 static void
-set_verbose_flag (void)
+set_verbose_flag (void *ignored)
 {
   echo_input_at_read = verbose_flag;
 }
@@ -180,6 +180,12 @@ set_verbose_flag (void)
 #  define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
 #endif
 
+static void
+unwind_unlink (void *filename)
+{
+  unlink ((const char *) filename);
+}
+
 int
 fc_builtin (WORD_LIST *list)
 {
@@ -525,7 +531,7 @@ fc_builtin (WORD_LIST *list)
      will be echoed as they are read by the parser. */
   begin_unwind_frame ("fc builtin");
   add_unwind_protect (xfree, fn);
-  add_unwind_protect (unlink, fn);
+  add_unwind_protect (unwind_unlink, fn);
   add_unwind_protect (set_verbose_flag, (char *)NULL);
   unwind_protect_int (suppress_debug_trap_verbose);
   echo_input_at_read = 1;
diff --git a/builtins/jobs.def b/builtins/jobs.def
index 316f34bd..fdaa0b8b 100644
--- a/builtins/jobs.def
+++ b/builtins/jobs.def
@@ -206,7 +206,7 @@ execute_list_with_replacements (WORD_LIST *list)
   command->flags |= CMD_INHIBIT_EXPANSION;
   command->value.Simple->flags |= CMD_INHIBIT_EXPANSION;
 
-  add_unwind_protect (dispose_command, command);
+  add_unwind_protect (unwind_dispose_command, command);
   result = execute_command (command);
   dispose_command (command);
 
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
index 78c7a999..acc55356 100644
--- a/builtins/mkbuiltins.c
+++ b/builtins/mkbuiltins.c
@@ -452,7 +452,6 @@ array_free (ARRAY *array)
 /* **************************************************************** */
 
 /* The definition of a function. */
-typedef int Function ();
 typedef int mk_handler_func_t (char *, DEF_FILE *, char *);
 
 /* Structure handles processor directives. */
diff --git a/builtins/read.def b/builtins/read.def
index e0f73749..9b19ff95 100644
--- a/builtins/read.def
+++ b/builtins/read.def
@@ -119,11 +119,11 @@ struct ttsave
 };
 
 #if defined (READLINE)
-static void reset_attempted_completion_function (char *);
+static void reset_attempted_completion_function (void *);
 static int set_itext (void);
 static char *edit_line (char *, char *);
 static void set_eol_delim (int);
-static void reset_eol_delim (char *);
+static void reset_eol_delim (void *);
 static void set_readline_timeout (sh_timer *t, time_t, long);
 #endif
 static SHELL_VAR *bind_read_variable (char *, char *, int);
@@ -131,6 +131,7 @@ static SHELL_VAR *bind_read_variable (char *, char *, int);
 static int read_mbchar (int, char *, int, int, int);
 #endif
 static void ttyrestore (struct ttsave *);
+static void unwind_ttyrestore (void *);
 
 static sighandler sigalrm (int);
 static void reset_timeout (void);
@@ -168,6 +169,11 @@ reset_timeout (void)
 #endif
   read_timeout = 0;
 }
+static void
+unwind_reset_timeout (void *ignored)
+{
+  reset_timeout ();
+}
 
 void
 check_read_timeout (void)
@@ -192,6 +198,14 @@ read_builtin_timeout (int fd)
 #endif
 }
 
+#if defined (READLINE)
+static void
+unwind_bashline_reset_event_hook (void *ignored)
+{
+  bashline_reset_event_hook ();
+}
+#endif
+
 /* Read the value of the shell variables whose names follow.
    The reading is done from the current input stream, whatever
    that may be.  Successive words of the input line are assigned
@@ -509,12 +523,12 @@ read_builtin (WORD_LIST *list)
        }
       if (interactive_shell == 0)
        initialize_terminating_signals ();
-      add_unwind_protect (reset_timeout, (char *)NULL);
+      add_unwind_protect (unwind_reset_timeout, NULL);
 #if defined (READLINE)
       if (edit)
        {
          add_unwind_protect (reset_attempted_completion_function, (char 
*)NULL);
-         add_unwind_protect (bashline_reset_event_hook, (char *)NULL);
+         add_unwind_protect (unwind_bashline_reset_event_hook, NULL);
          set_readline_timeout (read_timeout, tmsec, tmusec);
        }
       else
@@ -555,7 +569,7 @@ read_builtin (WORD_LIST *list)
          if (i < 0)
            sh_ttyerror (1);
          tty_modified = 1;
-         add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
+         add_unwind_protect (unwind_ttyrestore, &termsave);
          if (interactive_shell == 0)
            initialize_terminating_signals ();
        }
@@ -573,7 +587,7 @@ read_builtin (WORD_LIST *list)
        sh_ttyerror (1);
 
       tty_modified = 1;
-      add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
+      add_unwind_protect (unwind_ttyrestore, &termsave);
       if (interactive_shell == 0)
        initialize_terminating_signals ();
     }
@@ -1113,6 +1127,11 @@ ttyrestore (struct ttsave *ttp)
   ttsetattr (ttp->fd, &(ttp->attrs));
   tty_modified = 0;
 }
+static void
+unwind_ttyrestore (void *ttp)
+{
+  ttyrestore (ttp);
+}
 
 void
 read_tty_cleanup (void)
@@ -1133,7 +1152,7 @@ static rl_hook_func_t *old_startup_hook;
 static char *deftext;
 
 static void
-reset_attempted_completion_function (char *cp)
+reset_attempted_completion_function (void *ignored)
 {
   if (rl_attempted_completion_function == 0 && 
old_attempted_completion_function)
     rl_attempted_completion_function = old_attempted_completion_function;
@@ -1241,7 +1260,7 @@ set_eol_delim (int c)
 }
 
 static void
-reset_eol_delim (char *cp)
+reset_eol_delim (void *ignored)
 {
   Keymap cmap;
 
diff --git a/builtins/source.def b/builtins/source.def
index c15dbc51..999557ca 100644
--- a/builtins/source.def
+++ b/builtins/source.def
@@ -80,7 +80,7 @@ $END
 extern int errno;
 #endif /* !errno */
 
-static void maybe_pop_dollar_vars (void);
+static void maybe_pop_dollar_vars (void *);
 
 /* If non-zero, `.' uses $PATH to look up the script to be sourced. */
 int source_uses_path = 1;
@@ -96,7 +96,7 @@ int source_searches_cwd = 1;
    not executing a shell function, we leave the new values alone and free
    the saved values. */
 static void
-maybe_pop_dollar_vars (void)
+maybe_pop_dollar_vars (void *ignored)
 {
   if (variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN))
     dispose_saved_dollar_vars ();
@@ -170,7 +170,7 @@ source_builtin (WORD_LIST *list)
   if (list->next)
     {
       push_dollar_vars ();
-      add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL);
+      add_unwind_protect (maybe_pop_dollar_vars, NULL);
       if (debugging_mode || shell_compatibility_level <= 44)
        init_bash_argv ();      /* Initialize BASH_ARGV and BASH_ARGC */
       remember_args (list->next, 1);
diff --git a/configure.ac b/configure.ac
index 343320ec..0533ae4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -964,6 +964,7 @@ AC_TYPE_MODE_T
 AC_TYPE_UID_T
 AC_TYPE_PID_T
 AC_TYPE_SIZE_T
+AC_TYPE_INTPTR_T
 AC_TYPE_UINTPTR_T
 
 AC_CHECK_TYPE(ssize_t, int)
diff --git a/dispose_cmd.c b/dispose_cmd.c
index a79201ab..227bb300 100644
--- a/dispose_cmd.c
+++ b/dispose_cmd.c
@@ -203,6 +203,11 @@ dispose_command (COMMAND *command)
     }
   free (command);
 }
+void
+unwind_dispose_command (void *command)
+{
+  dispose_command (command);
+}
 
 #if defined (COND_COMMAND)
 /* How to free a node in a conditional command. */
@@ -271,6 +276,11 @@ dispose_words (WORD_LIST *list)
 #endif
     }
 }
+void
+unwind_dispose_words (void *list)
+{
+  dispose_words (list);
+}
 
 #ifdef INCLUDE_UNUSED
 /* How to dispose of an array of pointers to char.  This is identical to
diff --git a/dispose_cmd.h b/dispose_cmd.h
index 0e6eabc9..2c0cdf88 100644
--- a/dispose_cmd.h
+++ b/dispose_cmd.h
@@ -24,9 +24,11 @@
 #include "stdc.h"
 
 extern void dispose_command (COMMAND *);
+extern void unwind_dispose_command (void *);
 extern void dispose_word_desc (WORD_DESC *);
 extern void dispose_word (WORD_DESC *);
 extern void dispose_words (WORD_LIST *);
+extern void unwind_dispose_words (void *);
 extern void dispose_word_array (char **);
 extern void dispose_redirects (REDIRECT *);
 
diff --git a/execute_cmd.c b/execute_cmd.c
index 6546ea8c..6236146d 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -123,7 +123,7 @@ static int shell_control_structure (enum command_type);
 static void cleanup_redirects (REDIRECT *);
 
 #if defined (JOB_CONTROL)
-static int restore_signal_mask (sigset_t *);
+static void restore_signal_mask (void *);
 #endif
 
 static int builtin_status (int);
@@ -343,6 +343,11 @@ dispose_fd_bitmap (struct fd_bitmap *fdbp)
   FREE (fdbp->bitmap);
   free (fdbp);
 }
+void
+unwind_dispose_fd_bitmap (void *fdbp)
+{
+  dispose_fd_bitmap (fdbp);
+}
 
 void
 close_fd_bitmap (struct fd_bitmap *fdbp)
@@ -359,6 +364,17 @@ close_fd_bitmap (struct fd_bitmap *fdbp)
          }
     }
 }
+static void
+unwind_close_fd_bitmap (void *fdbp)
+{
+  close_fd_bitmap (fdbp);
+}
+
+void
+unwind_close (void *fd)
+{
+  close ((intptr_t) fd);
+}
 
 /* Return the line number of the currently executing command. */
 int
@@ -403,7 +419,7 @@ execute_command (COMMAND *command)
   current_fds_to_close = (struct fd_bitmap *)NULL;
   bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
   begin_unwind_frame ("execute-command");
-  add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
+  add_unwind_protect (unwind_dispose_fd_bitmap, bitmap);
 
   /* Just do the command, but not asynchronously. */
   result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap);
@@ -462,6 +478,16 @@ cleanup_redirects (REDIRECT *list)
   do_redirections (list, RX_ACTIVE);
   dispose_redirects (list);
 }
+static void
+unwind_cleanup_redirects (void *list)
+{
+  cleanup_redirects (list);
+}
+static void
+unwind_dispose_redirects (void *list)
+{
+  dispose_redirects (list);
+}
 
 void
 undo_partial_redirects (void)
@@ -505,10 +531,10 @@ dispose_partial_redirects (void)
 #if defined (JOB_CONTROL)
 /* A function to restore the signal mask to its proper value when the shell
    is interrupted or errors occur while creating a pipeline. */
-static int
-restore_signal_mask (sigset_t *set)
+static void
+restore_signal_mask (void *set)
 {
-  return (sigprocmask (SIG_SETMASK, set, (sigset_t *)NULL));
+  sigprocmask (SIG_SETMASK, set, NULL);
 }
 #endif /* JOB_CONTROL */
 
@@ -570,7 +596,7 @@ execute_command_internal (COMMAND *command, int 
asynchronous, int pipe_in, int p
   volatile int save_line_number;
 #if defined (PROCESS_SUBSTITUTION)
   volatile int ofifo, nfifo, osize, saved_fifo;
-  volatile void *ofifo_list;
+  void *ofifo_list;
 #endif
 
   if (breaking || continuing)
@@ -791,7 +817,7 @@ execute_command_internal (COMMAND *command, int 
asynchronous, int pipe_in, int p
 #if defined (PROCESS_SUBSTITUTION)
       if (saved_fifo)
        {
-         free ((void *)ofifo_list);
+         free (ofifo_list);
           discard_unwind_frame ("internal_fifos");
        }
 #endif
@@ -826,10 +852,10 @@ execute_command_internal (COMMAND *command, int 
asynchronous, int pipe_in, int p
     begin_unwind_frame ("loop_redirections");
 
   if (my_undo_list)
-    add_unwind_protect ((Function *)cleanup_redirects, my_undo_list);
+    add_unwind_protect (unwind_cleanup_redirects, my_undo_list);
 
   if (exec_undo_list)
-    add_unwind_protect ((Function *)dispose_redirects, exec_undo_list);
+    add_unwind_protect (unwind_dispose_redirects, exec_undo_list);
 
   QUIT;
 
@@ -1103,8 +1129,8 @@ execute_command_internal (COMMAND *command, int 
asynchronous, int pipe_in, int p
     {
       nfifo = num_fifos ();
       if (nfifo > ofifo)
-       close_new_fifos ((void *)ofifo_list, osize);
-      free ((void *)ofifo_list);
+       close_new_fifos (ofifo_list, osize);
+      free (ofifo_list);
       discard_unwind_frame ("internal_fifos");
     }
 #endif
@@ -2437,12 +2463,27 @@ restore_stdin (int s)
       close (s);
     }
 }
+static void
+unwind_restore_stdin (void *s)
+{
+  restore_stdin ((intptr_t) s);
+}
+static void
+unwind_set_error_trap (void *command)
+{
+  set_error_trap (command);
+}
+static void
+unwind_merge_temporary_env (void *ignored)
+{
+  merge_temporary_env ();
+}
 
 /* Catch-all cleanup function for lastpipe code for unwind-protects */
 static void
-lastpipe_cleanup (int s)
+lastpipe_cleanup (void *s)
 {
-  set_jobs_list_frozen (s);
+  set_jobs_list_frozen ((intptr_t) s);
 }
 
 static int
@@ -2516,12 +2557,12 @@ execute_pipeline (COMMAND *command, int asynchronous, 
int pipe_in, int pipe_out,
         unwind-protects are run, and the storage used for the
         bitmaps freed up. */
       begin_unwind_frame ("pipe-file-descriptors");
-      add_unwind_protect (dispose_fd_bitmap, fd_bitmap);
-      add_unwind_protect (close_fd_bitmap, fd_bitmap);
+      add_unwind_protect (unwind_dispose_fd_bitmap, fd_bitmap);
+      add_unwind_protect (unwind_close_fd_bitmap, fd_bitmap);
       if (prev >= 0)
-       add_unwind_protect (close, prev);
+       add_unwind_protect (unwind_close, (void *) (intptr_t) prev);
       dummyfd = fildes[1];
-      add_unwind_protect (close, dummyfd);
+      add_unwind_protect (unwind_close, (void *) (intptr_t) dummyfd);
 
 #if defined (JOB_CONTROL)
       add_unwind_protect (restore_signal_mask, &oset);
@@ -2568,11 +2609,13 @@ execute_pipeline (COMMAND *command, int asynchronous, 
int pipe_in, int pipe_out,
        {
          do_piping (prev, pipe_out);
          prev = NO_PIPE;
-         add_unwind_protect (restore_stdin, lstdin);
+         add_unwind_protect (unwind_restore_stdin,
+                             (void *) (intptr_t) lstdin);
          lastpipe_flag = 1;
          old_frozen = freeze_jobs_list ();
          lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL);    /* XXX */
-         add_unwind_protect (lastpipe_cleanup, old_frozen);
+         add_unwind_protect (lastpipe_cleanup,
+                             (void *) (intptr_t) old_frozen);
 #if defined (JOB_CONTROL)
          UNBLOCK_CHILD (oset);         /* XXX */
 #endif
@@ -2581,7 +2624,7 @@ execute_pipeline (COMMAND *command, int asynchronous, int 
pipe_in, int pipe_out,
        cmd->flags |= CMD_LASTPIPE;
     }    
   if (prev >= 0)
-    add_unwind_protect (close, prev);
+    add_unwind_protect (unwind_close, (void *) (intptr_t) prev);
 
   exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, 
fds_to_close);
 
@@ -2841,14 +2884,14 @@ execute_for_command (FOR_COM *for_command)
   list = releaser = expand_words_no_vars (for_command->map_list);
 
   begin_unwind_frame ("for");
-  add_unwind_protect (dispose_words, releaser);
+  add_unwind_protect (unwind_dispose_words, releaser);
 
 #if 0
   if (lexical_scoping)
     {
       old_value = copy_variable (find_variable (identifier));
       if (old_value)
-       add_unwind_protect (dispose_variable, old_value);
+       add_unwind_protect (unwind_dispose_variable, old_value);
     }
 #endif
 
@@ -3375,7 +3418,7 @@ execute_select_command (SELECT_COM *select_command)
     }
 
   begin_unwind_frame ("select");
-  add_unwind_protect (dispose_words, releaser);
+  add_unwind_protect (unwind_dispose_words, releaser);
 
   if (select_command->flags & CMD_IGNORE_RETURN)
     select_command->action->flags |= CMD_IGNORE_RETURN;
@@ -4539,7 +4582,7 @@ itrace("execute_simple_command: posix mode tempenv 
assignment error");
       builtin = 0;
     }
 
-  add_unwind_protect (dispose_words, words);
+  add_unwind_protect (unwind_dispose_words, words);
   QUIT;
 
   /* Bind the last word in this command to "$_" after execution. */
@@ -4798,7 +4841,7 @@ execute_builtin (sh_builtin_func_t *builtin, WORD_LIST 
*words, int flags, int su
        {
          error_trap = savestring (error_trap);
          add_unwind_protect (xfree, error_trap);
-         add_unwind_protect (set_error_trap, error_trap);
+         add_unwind_protect (unwind_set_error_trap, error_trap);
          restore_default_signal (ERROR_TRAP);
        }
       exit_immediately_on_error = 0;
@@ -4838,7 +4881,7 @@ execute_builtin (sh_builtin_func_t *builtin, WORD_LIST 
*words, int flags, int su
          if (flags & CMD_COMMAND_BUILTIN)
            should_keep = 0;
          if (subshell == 0)
-           add_unwind_protect (pop_scope, should_keep ? "1" : 0);
+           add_unwind_protect (pop_scope, (void *) (intptr_t) should_keep);
           temporary_env = (HASH_TABLE *)NULL;    
        }
     }
@@ -4877,7 +4920,7 @@ execute_builtin (sh_builtin_func_t *builtin, WORD_LIST 
*words, int flags, int su
   if (posixly_correct && subshell == 0 && builtin == return_builtin && (flags 
& CMD_COMMAND_BUILTIN) == 0 && temporary_env)
     {
       begin_unwind_frame ("return_temp_env");
-      add_unwind_protect (merge_temporary_env, (char *)NULL);
+      add_unwind_protect (unwind_merge_temporary_env, NULL);
     }
 
   executing_builtin++;
@@ -4908,8 +4951,9 @@ execute_builtin (sh_builtin_func_t *builtin, WORD_LIST 
*words, int flags, int su
 }
 
 static void
-maybe_restore_getopt_state (sh_getopt_state_t *gs)
+maybe_restore_getopt_state (void *arg)
 {
+  sh_getopt_state_t *gs = arg;
   /* If we have a local copy of OPTIND and it's at the right (current)
      context, then we restore getopt's internal state.  If not, we just
      let it go.  We know there is a local OPTIND if gs->gs_flags & 1.
@@ -4936,6 +4980,11 @@ restore_funcarray_state (struct func_array_state *fa)
 
   free (fa);
 }
+void
+unwind_restore_funcarray_state (void *fa)
+{
+  return restore_funcarray_state (fa);
+}
 #endif
 
 static int
@@ -4996,13 +5045,13 @@ execute_function (SHELL_VAR *var, WORD_LIST *words, int 
flags, struct fd_bitmap
         local variables may cause the restore of a local declaration of
         OPTIND to force a getopts state reset. */
       add_unwind_protect (maybe_restore_getopt_state, gs);
-      add_unwind_protect (pop_context, (char *)NULL);
+      add_unwind_protect (pop_context, NULL);
       unwind_protect_int (line_number);
       unwind_protect_int (line_number_for_err_trap);
       unwind_protect_int (function_line_number);
       unwind_protect_int (return_catch_flag);
       unwind_protect_jmp_buf (return_catch);
-      add_unwind_protect (dispose_command, (char *)tc);
+      add_unwind_protect (unwind_dispose_command, tc);
       unwind_protect_pointer (this_shell_function);
       unwind_protect_int (funcnest);
       unwind_protect_int (loop_level);
@@ -5085,7 +5134,7 @@ execute_function (SHELL_VAR *var, WORD_LIST *words, int 
flags, struct fd_bitmap
   fa->funcname_a = (ARRAY *)funcname_a;
   fa->funcname_v = funcname_v;
   if (subshell == 0)
-    add_unwind_protect (restore_funcarray_state, fa);
+    add_unwind_protect (unwind_restore_funcarray_state, fa);
 #endif
 
   /* The temporary environment for a function is supposed to apply to
@@ -5103,7 +5152,7 @@ execute_function (SHELL_VAR *var, WORD_LIST *words, int 
flags, struct fd_bitmap
     {
       push_args (words->next);
       if (subshell == 0)
-       add_unwind_protect (pop_args, 0);
+       add_unwind_protect (unwind_pop_args, NULL);
     }
 
   /* Number of the line on which the function body starts. */
@@ -5202,7 +5251,7 @@ execute_shell_function (SHELL_VAR *var, WORD_LIST *words)
 
   bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
   begin_unwind_frame ("execute-shell-function");
-  add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
+  add_unwind_protect (unwind_dispose_fd_bitmap, bitmap);
       
   ret = execute_function (var, words, 0, bitmap, 0, 0);
 
@@ -5383,7 +5432,7 @@ execute_builtin_or_function (WORD_LIST *words,
   if (saved_undo_list)
     {
       begin_unwind_frame ("saved-redirects");
-      add_unwind_protect (cleanup_redirects, (char *)saved_undo_list);
+      add_unwind_protect (unwind_cleanup_redirects, saved_undo_list);
     }
 
   redirection_undo_list = (REDIRECT *)NULL;
diff --git a/execute_cmd.h b/execute_cmd.h
index d9c3e7b1..ec86dee7 100644
--- a/execute_cmd.h
+++ b/execute_cmd.h
@@ -71,7 +71,9 @@ extern SHELL_VAR *this_shell_function;
 
 extern struct fd_bitmap *new_fd_bitmap (int);
 extern void dispose_fd_bitmap (struct fd_bitmap *);
+extern void unwind_dispose_fd_bitmap (void *);
 extern void close_fd_bitmap (struct fd_bitmap *);
+extern void unwind_close (void *);
 extern int executing_line_number (void);
 extern int execute_command (COMMAND *);
 extern int execute_command_internal (COMMAND *, int, int, int, struct 
fd_bitmap *);
@@ -118,6 +120,7 @@ extern void close_all_files (void);
 
 #if defined (ARRAY_VARS)
 extern void restore_funcarray_state (struct func_array_state *);
+extern void unwind_restore_funcarray_state (void *);
 #endif
 
 extern void bind_lastarg (char *);
diff --git a/general.h b/general.h
index eb296f56..2b81f683 100644
--- a/general.h
+++ b/general.h
@@ -159,9 +159,16 @@ typedef struct {
 #endif /* !__GNUC__ */
 
 /* String comparisons that possibly save a function call each. */
-#define STREQ(a, b) ((a)[0] == (b)[0] && strcmp(a, b) == 0)
-#define STREQN(a, b, n) ((n == 0) ? (1) \
-                                 : ((a)[0] == (b)[0] && strncmp(a, b, n) == 0))
+static inline int
+STREQ (const char *a, const char *b)
+{
+  return a[0] == b[0] && strcmp (a, b) == 0;
+}
+static inline int
+STREQN (const char *a, const char *b, size_t n)
+{
+  return !n || (a[0] == b[0] && strncmp (a, b, n) == 0);
+}
 
 /* More convenience definitions that possibly save system or libc calls. */
 #define STRLEN(s) (((s) && (s)[0]) ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 
0)
@@ -186,15 +193,6 @@ typedef struct {
       } \
   } while (0)
 
-/* Function pointers can be declared as (Function *)foo. */
-#if !defined (_FUNCTION_DEF)
-#  define _FUNCTION_DEF
-typedef int Function ();
-typedef void VFunction ();
-typedef char *CPFunction ();           /* no longer used */
-typedef char **CPPFunction ();         /* no longer used */
-#endif /* _FUNCTION_DEF */
-
 #ifndef SH_FUNCTION_TYPEDEF
 #  define SH_FUNCTION_TYPEDEF
 
diff --git a/lib/readline/rltypedefs.h b/lib/readline/rltypedefs.h
index 16365492..b6ebcec2 100644
--- a/lib/readline/rltypedefs.h
+++ b/lib/readline/rltypedefs.h
@@ -26,27 +26,6 @@
 extern "C" {
 #endif
 
-/* Old-style, attempt to mark as deprecated in some way people will notice. */
-
-#if !defined (_FUNCTION_DEF)
-#  define _FUNCTION_DEF
-
-#if defined(__GNUC__) || defined(__clang__)
-typedef int Function () __attribute__((deprecated));
-typedef void VFunction () __attribute__((deprecated));
-typedef char *CPFunction () __attribute__((deprecated));
-typedef char **CPPFunction () __attribute__((deprecated));
-#else
-typedef int Function ();
-typedef void VFunction ();
-typedef char *CPFunction ();
-typedef char **CPPFunction ();
-#endif
-
-#endif /* _FUNCTION_DEF */
-
-/* New style. */
-
 #if !defined (_RL_FUNCTION_TYPEDEF)
 #  define _RL_FUNCTION_TYPEDEF
 
diff --git a/pcomplete.c b/pcomplete.c
index e79b8a71..22e079f9 100644
--- a/pcomplete.c
+++ b/pcomplete.c
@@ -134,7 +134,7 @@ static char *pcomp_filename_completion_function (const char 
*, int);
 static SHELL_VAR *bind_comp_words (WORD_LIST *);
 #endif
 static void bind_compfunc_variables (char *, int, WORD_LIST *, int, int);
-static void unbind_compfunc_variables (int);
+static void unbind_compfunc_variables (void *);
 static WORD_LIST *build_arg_list (const char *, const char *, const char *, 
WORD_LIST *, int);
 static WORD_LIST *command_line_to_word_list (char *, int, int, int *, int *);
 
@@ -981,7 +981,7 @@ bind_compfunc_variables (char *line, int ind, WORD_LIST 
*lwords, int cw, int exp
 }
 
 static void
-unbind_compfunc_variables (int exported)
+unbind_compfunc_variables (void *exported)
 {
   unbind_variable_noref ("COMP_LINE");
   unbind_variable_noref ("COMP_POINT");
@@ -1034,6 +1034,18 @@ build_arg_list (const char *cmd, const char *cname, 
const char *text, WORD_LIST
   return ret;
 }
 
+static void
+unwind_restore_parser_state (void *ps)
+{
+  restore_parser_state (ps);
+}
+
+static void
+unwind_rl_set_signals (void *ignored)
+{
+  rl_set_signals ();
+}
+
 /* Build a command string with
        $0 == cs->funcname      (function to execute for completion list)
        $1 == command name      (command being completed)
@@ -1090,12 +1102,12 @@ gen_shell_function_matches (COMPSPEC *cs, const char 
*cmd, const char *text,
   pps = &ps;
   save_parser_state (pps);
   begin_unwind_frame ("gen-shell-function-matches");
-  add_unwind_protect (restore_parser_state, (char *)pps);
-  add_unwind_protect (dispose_words, (char *)cmdlist);
-  add_unwind_protect (unbind_compfunc_variables, (char *)0);
+  add_unwind_protect (unwind_restore_parser_state, pps);
+  add_unwind_protect (unwind_dispose_words, cmdlist);
+  add_unwind_protect (unbind_compfunc_variables, NULL);
   if (local_compgen == 0)
     {
-      add_unwind_protect (rl_set_signals, (char *)NULL);
+      add_unwind_protect (unwind_rl_set_signals, NULL);
       rl_clear_signals ();
     }
 
@@ -1205,7 +1217,7 @@ gen_command_matches (COMPSPEC *cs, const char *cmd, const 
char *text,
   /* Now clean up and destroy everything. */
   dispose_words (cmdlist);
   free (cscmd);
-  unbind_compfunc_variables (1);
+  unbind_compfunc_variables ("");
 
   if (csbuf == 0 || *csbuf == '\0')
     {
diff --git a/print_cmd.c b/print_cmd.c
index 2410b8a2..365692e5 100644
--- a/print_cmd.c
+++ b/print_cmd.c
@@ -57,7 +57,7 @@ typedef void PFUNC (const char *, ...);
 static void cprintf (const char *, ...)  __attribute__((__format__ (printf, 1, 
2)));
 static void xprintf (const char *, ...)  __attribute__((__format__ (printf, 1, 
2)));
 
-static void reset_locals (void);
+static void reset_locals (void *);
 static void newline (char *);
 static void indent (int);
 static void semicolon (void);
@@ -1241,7 +1241,7 @@ print_redirection (REDIRECT *redirect)
 }
 
 static void
-reset_locals (void)
+reset_locals (void *unused)
 {
   inside_function_def = 0;
   indentation = 0;
diff --git a/subst.c b/subst.c
index f45e29b8..3e5966c7 100644
--- a/subst.c
+++ b/subst.c
@@ -6960,7 +6960,7 @@ command_substitute (char *string, int quoted, int flags)
 
       begin_unwind_frame ("read-comsub");
       dummyfd = fildes[0];
-      add_unwind_protect (close, dummyfd);
+      add_unwind_protect (unwind_close, (void *) (intptr_t) dummyfd);
 
       /* Block SIGINT while we're reading from the pipe. If the child
         process gets a SIGINT, it will either handle it or die, and the
diff --git a/trap.c b/trap.c
index 07e7ddec..0bfa338c 100644
--- a/trap.c
+++ b/trap.c
@@ -652,10 +652,10 @@ set_sigchld_trap (const char *command_string)
    reset the disposition to the default and not have the original signal
    accidentally restored, undoing the user's command. */
 void
-maybe_set_sigchld_trap (const char *command_string)
+maybe_set_sigchld_trap (void *command_string)
 {
   if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0 && trap_list[SIGCHLD] == (char 
*)IMPOSSIBLE_TRAP_HANDLER)
-    set_signal (SIGCHLD, command_string);
+    set_signal (SIGCHLD, (const char *) command_string);
 }
 
 /* Temporarily set the SIGCHLD trap string to IMPOSSIBLE_TRAP_HANDLER.  Used
@@ -705,7 +705,7 @@ set_debug_trap (const char *command)
    SIG_TRAPPED will be set and we don't bother restoring the original trap 
string.
    This is used by both functions and the source builtin. */
 void
-maybe_set_debug_trap (const char *command)
+maybe_set_debug_trap (void *command)
 {
   trap_if_untrapped (DEBUG_TRAP, command);
 }
@@ -717,7 +717,7 @@ set_error_trap (const char *command)
 }
 
 void
-maybe_set_error_trap (const char *command)
+maybe_set_error_trap (void *command)
 {
   trap_if_untrapped (ERROR_TRAP, command);
 }
@@ -729,7 +729,7 @@ set_return_trap (const char *command)
 }
 
 void
-maybe_set_return_trap (const char *command)
+maybe_set_return_trap (void *command)
 {
   trap_if_untrapped (RETURN_TRAP, command);
 }
diff --git a/trap.h b/trap.h
index e031e5fe..048f65ca 100644
--- a/trap.h
+++ b/trap.h
@@ -73,7 +73,7 @@ extern void initialize_traps (void);
 extern void run_pending_traps (void);
 
 extern void queue_sigchld_trap (int);
-extern void maybe_set_sigchld_trap (const char *);
+extern void maybe_set_sigchld_trap (void *);
 extern void set_impossible_sigchld_trap (void);
 extern void set_sigchld_trap (const char *);
 
@@ -81,9 +81,9 @@ extern void set_debug_trap (const char *);
 extern void set_error_trap (const char *);
 extern void set_return_trap (const char *);
 
-extern void maybe_set_debug_trap (const char *);
-extern void maybe_set_error_trap (const char *);
-extern void maybe_set_return_trap (const char *);
+extern void maybe_set_debug_trap (void *);
+extern void maybe_set_error_trap (void *);
+extern void maybe_set_return_trap (void *);
 
 extern void set_sigint_trap (const char *);
 extern void set_signal (int, const char *);
diff --git a/unwind_prot.c b/unwind_prot.c
index c471b98a..3b5ce215 100644
--- a/unwind_prot.c
+++ b/unwind_prot.c
@@ -65,11 +65,11 @@ typedef struct {
 typedef union uwp {
   struct uwp_head {
     union uwp *next;
-    Function *cleanup;
+    void (*cleanup) (void *);
   } head;
   struct {
     struct uwp_head uwp_head;
-    char *v;
+    void *v;
   } arg;
   struct {
     struct uwp_head uwp_head;
@@ -77,15 +77,14 @@ typedef union uwp {
   } sv;
 } UNWIND_ELT;
 
-static void without_interrupts (VFunction *, char *, char *);
-static void unwind_frame_discard_internal (char *, char *);
-static void unwind_frame_run_internal (char *, char *);
-static void add_unwind_protect_internal (Function *, char *);
-static void remove_unwind_protect_internal (char *, char *);
-static void run_unwind_protects_internal (char *, char *);
-static void clear_unwind_protects_internal (char *, char *);
-static inline void restore_variable (SAVED_VAR *);
-static void unwind_protect_mem_internal (char *, char *);
+static void unwind_frame_discard_internal (char *);
+static void unwind_frame_run_internal (char *);
+static void add_unwind_protect_internal (void (*) (void *), void *);
+static void remove_unwind_protect_internal ();
+static void run_unwind_protects_internal ();
+static void clear_unwind_protects_internal (int);
+static inline void restore_variable (void *);
+static void unwind_protect_mem_internal (char *, int);
 
 static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
 
@@ -108,19 +107,11 @@ uwp_init (void)
   ocache_create (uwcache, UNWIND_ELT, UWCACHESIZE);
 }
 
-/* Run a function without interrupts.  This relies on the fact that the
-   FUNCTION cannot call QUIT (). */
-static void
-without_interrupts (VFunction *function, char *arg1, char *arg2)
-{
-  (*function)(arg1, arg2);
-}
-
 /* Start the beginning of a region. */
 void
 begin_unwind_frame (char *tag)
 {
-  add_unwind_protect ((Function *)NULL, tag);
+  add_unwind_protect (NULL, tag);
 }
 
 /* Discard the unwind protects back to TAG. */
@@ -128,7 +119,7 @@ void
 discard_unwind_frame (char *tag)
 {
   if (unwind_protect_list)
-    without_interrupts (unwind_frame_discard_internal, tag, (char *)NULL);
+    unwind_frame_discard_internal (tag);
 }
 
 /* Run the unwind protects back to TAG. */
@@ -136,14 +127,14 @@ void
 run_unwind_frame (char *tag)
 {
   if (unwind_protect_list)
-    without_interrupts (unwind_frame_run_internal, tag, (char *)NULL);
+    unwind_frame_run_internal (tag);
 }
 
 /* Add the function CLEANUP with ARG to the list of unwindable things. */
 void
-add_unwind_protect (Function *cleanup, char *arg)
+add_unwind_protect (void (*cleanup) (void *), void *arg)
 {
-  without_interrupts (add_unwind_protect_internal, (char *)cleanup, arg);
+  add_unwind_protect_internal (cleanup, arg);
 }
 
 /* Remove the top unwind protect from the list. */
@@ -151,8 +142,7 @@ void
 remove_unwind_protect (void)
 {
   if (unwind_protect_list)
-    without_interrupts
-      (remove_unwind_protect_internal, (char *)NULL, (char *)NULL);
+    remove_unwind_protect_internal ();
 }
 
 /* Run the list of cleanup functions in unwind_protect_list. */
@@ -160,22 +150,15 @@ void
 run_unwind_protects (void)
 {
   if (unwind_protect_list)
-    without_interrupts
-      (run_unwind_protects_internal, (char *)NULL, (char *)NULL);
+    run_unwind_protects_internal ();
 }
 
 /* Erase the unwind-protect list.  If flags is 1, free the elements. */
 void
 clear_unwind_protect_list (int flags)
 {
-  char *flag;
-
   if (unwind_protect_list)
-    {
-      flag = flags ? "" : (char *)NULL;
-      without_interrupts
-        (clear_unwind_protects_internal, flag, (char *)NULL);
-    }
+    clear_unwind_protects_internal (flags);
 }
 
 int
@@ -206,7 +189,7 @@ unwind_protect_tag_on_stack (const char *tag)
 /* **************************************************************** */
 
 static void
-add_unwind_protect_internal (Function *cleanup, char *arg)
+add_unwind_protect_internal (void (*cleanup) (void *), void *arg)
 {
   UNWIND_ELT *elt;
 
@@ -218,7 +201,7 @@ add_unwind_protect_internal (Function *cleanup, char *arg)
 }
 
 static void
-remove_unwind_protect_internal (char *ignore1, char *ignore2)
+remove_unwind_protect_internal ()
 {
   UNWIND_ELT *elt;
 
@@ -231,24 +214,24 @@ remove_unwind_protect_internal (char *ignore1, char 
*ignore2)
 }
 
 static void
-run_unwind_protects_internal (char *ignore1, char *ignore2)
+run_unwind_protects_internal ()
 {
-  unwind_frame_run_internal ((char *) NULL, (char *) NULL);
+  unwind_frame_run_internal (NULL);
 }
 
 static void
-clear_unwind_protects_internal (char *flag, char *ignore)
+clear_unwind_protects_internal (int flag)
 {
   if (flag)
     {
       while (unwind_protect_list)
-       remove_unwind_protect_internal ((char *)NULL, (char *)NULL);
+       remove_unwind_protect_internal ();
     }
   unwind_protect_list = (UNWIND_ELT *)NULL;
 }
 
 static void
-unwind_frame_discard_internal (char *tag, char *ignore)
+unwind_frame_discard_internal (char *tag)
 {
   UNWIND_ELT *elt;
   int found;
@@ -275,13 +258,14 @@ unwind_frame_discard_internal (char *tag, char *ignore)
    sv->desired_setting is a block of memory SIZE bytes long holding the
    value itself.  This block of memory is copied back into the variable. */
 static inline void
-restore_variable (SAVED_VAR *sv)
+restore_variable (void *arg)
 {
+  SAVED_VAR *sv = arg;
   FASTCOPY (sv->desired_setting, sv->variable, sv->size);
 }
 
 static void
-unwind_frame_run_internal (char *tag, char *ignore)
+unwind_frame_run_internal (char *tag)
 {
   UNWIND_ELT *elt;
   int found;
@@ -303,7 +287,7 @@ unwind_frame_run_internal (char *tag, char *ignore)
        }
       else
        {
-         if (elt->head.cleanup == (Function *) restore_variable)
+         if (elt->head.cleanup == restore_variable)
            restore_variable (&elt->sv.v);
          else
            (*(elt->head.cleanup)) (elt->arg.v);
@@ -316,19 +300,17 @@ unwind_frame_run_internal (char *tag, char *ignore)
 }
 
 static void
-unwind_protect_mem_internal (char *var, char *psize)
+unwind_protect_mem_internal (char *var, int size)
 {
-  int size;
   size_t allocated;
   UNWIND_ELT *elt;
 
-  size = *(int *) psize;
   allocated = size + offsetof (UNWIND_ELT, sv.v.desired_setting[0]);
   if (allocated < sizeof (UNWIND_ELT))
     allocated = sizeof (UNWIND_ELT);
   elt = (UNWIND_ELT *)xmalloc (allocated);
   elt->head.next = unwind_protect_list;
-  elt->head.cleanup = (Function *) restore_variable;
+  elt->head.cleanup = restore_variable;
   elt->sv.v.variable = var;
   elt->sv.v.size = size;
   FASTCOPY (var, elt->sv.v.desired_setting, size);
@@ -341,7 +323,7 @@ unwind_protect_mem_internal (char *var, char *psize)
 void
 unwind_protect_mem (char *var, int size)
 {
-  without_interrupts (unwind_protect_mem_internal, var, (char *) &size);
+  unwind_protect_mem_internal (var, size);
 }
 
 #if defined (DEBUG)
diff --git a/unwind_prot.h b/unwind_prot.h
index 7493c22e..730512b8 100644
--- a/unwind_prot.h
+++ b/unwind_prot.h
@@ -27,7 +27,7 @@ extern void uwp_init (void);
 extern void begin_unwind_frame (char *);
 extern void discard_unwind_frame (char *);
 extern void run_unwind_frame (char *);
-extern void add_unwind_protect (); /* Not portable to arbitrary C99 hosts.  */
+extern void add_unwind_protect (void (*) (void *), void *);
 extern void remove_unwind_protect (void);
 extern void run_unwind_protects (void);
 extern void clear_unwind_protect_list (int);
diff --git a/variables.c b/variables.c
index 1d67cc8c..5e17a976 100644
--- a/variables.c
+++ b/variables.c
@@ -5330,7 +5330,7 @@ push_exported_var (PTR_T data)
    variables in its temporary environment. In the first case, we call
    push_builtin_var, which does the right thing. */
 void
-pop_scope (int is_special)
+pop_scope (void *is_special)
 {
   VAR_CONTEXT *vcxt, *ret;
   int is_bltinenv;
@@ -5354,7 +5354,7 @@ pop_scope (int is_special)
   FREE (vcxt->name);
   if (vcxt->table)
     {
-      if (is_special)
+      if ((intptr_t) is_special)
        hash_flush (vcxt->table, push_builtin_var);
       else
        hash_flush (vcxt->table, push_exported_var);
@@ -5453,7 +5453,7 @@ push_context (char *name, int is_subshell, HASH_TABLE 
*tempvars)
 /* Only called when subshell == 0, so we don't need to check, and can
    unconditionally pop the dollar vars off the stack. */
 void
-pop_context (void)
+pop_context (void *ignored)
 {
   pop_dollar_vars ();
   variable_context--;
@@ -5591,6 +5591,11 @@ pop_args (void)
   array_dispose_element (ce);
 #endif /* ARRAY_VARS && DEBUGGER */
 }
+void
+unwind_pop_args (void *unused)
+{
+  pop_args ();
+}
 
 /*************************************************
  *                                              *
diff --git a/variables.h b/variables.h
index 1616d455..fb603966 100644
--- a/variables.h
+++ b/variables.h
@@ -345,12 +345,12 @@ extern void dispose_var_context (VAR_CONTEXT *);
 extern VAR_CONTEXT *push_var_context (char *, int, HASH_TABLE *);
 extern void pop_var_context (void);
 extern VAR_CONTEXT *push_scope (int, HASH_TABLE *);
-extern void pop_scope (int);
+extern void pop_scope (void *);
 
 extern void clear_dollar_vars (void);
 
 extern void push_context (char *, int, HASH_TABLE *);
-extern void pop_context (void);
+extern void pop_context (void *);
 extern void push_dollar_vars (void);
 extern void pop_dollar_vars (void);
 extern void dispose_saved_dollar_vars (void);
@@ -359,6 +359,7 @@ extern void init_bash_argv (void);
 extern void save_bash_argv (void);
 extern void push_args (WORD_LIST *);
 extern void pop_args (void);
+extern void unwind_pop_args (void *);
 
 extern void adjust_shell_level (int);
 extern void non_unsettable (char *);
-- 
2.39.2






reply via email to

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