diff options
Diffstat (limited to 'setjmp')
-rw-r--r-- | setjmp/Makefile | 32 | ||||
-rw-r--r-- | setjmp/longjmp.c | 40 | ||||
-rw-r--r-- | setjmp/setjmp.h | 112 | ||||
-rw-r--r-- | setjmp/sigjmp.c | 36 | ||||
-rw-r--r-- | setjmp/tst-setjmp.c | 61 |
5 files changed, 281 insertions, 0 deletions
diff --git a/setjmp/Makefile b/setjmp/Makefile new file mode 100644 index 0000000000..4a7e4aa85a --- /dev/null +++ b/setjmp/Makefile @@ -0,0 +1,32 @@ +# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public +# License along with the GNU C Library; see the file COPYING.LIB. If +# not, write to the Free Software Foundation, Inc., 675 Mass Ave, +# Cambridge, MA 02139, USA. + +# +# Makefile for setjmp/longjmp routines +# +subdir := setjmp + +headers := setjmp.h jmp_buf.h + +routines := setjmp sigjmp bsd-setjmp bsd-_setjmp \ + longjmp __longjmp + +tests := tst-setjmp + + +include ../Rules diff --git a/setjmp/longjmp.c b/setjmp/longjmp.c new file mode 100644 index 0000000000..d4e4ef7740 --- /dev/null +++ b/setjmp/longjmp.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <stddef.h> +#include <setjmp.h> +#include <signal.h> + + +/* Set the signal mask to the one specified in ENV, and jump + to the position specified in ENV, causing the setjmp + call there to return VAL, or 1 if VAL is 0. */ +void +longjmp (sigjmp_buf env, int val) +{ + if (env[0].__mask_was_saved) + /* Restore the saved signal mask. */ + (void) __sigprocmask (SIG_SETMASK, &env[0].__saved_mask, + (sigset_t *) NULL); + + /* Call the machine-dependent function to restore machine state. */ + __longjmp (env[0].__jmpbuf, val ?: 1); +} + +weak_alias (longjmp, _longjmp) +weak_alias (longjmp, siglongjmp) diff --git a/setjmp/setjmp.h b/setjmp/setjmp.h new file mode 100644 index 0000000000..479cf973ec --- /dev/null +++ b/setjmp/setjmp.h @@ -0,0 +1,112 @@ +/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + * ANSI Standard: 4.6 NON-LOCAL JUMPS <setjmp.h> + */ + +#ifndef _SETJMP_H + +#define _SETJMP_H 1 +#include <features.h> + +__BEGIN_DECLS + +/* Get the machine-dependent definition of `__jmp_buf'. */ +#include <jmp_buf.h> +#include <sigset.h> /* Get `__sigset_t'. */ + +/* Calling environment, plus possibly a saved signal mask. */ +typedef struct + { + /* NOTE: The machine-dependent definitions of `__sigsetjmp' + assume that a `jmp_buf' begins with a `__jmp_buf'. + Do not move this member or add others before it. */ + __jmp_buf __jmpbuf; /* Calling environment. */ + int __mask_was_saved; /* Saved the signal mask? */ + __sigset_t __saved_mask; /* Saved signal mask. */ + } jmp_buf[1]; + + +/* Store the calling environment in ENV, also saving the + signal mask if SAVEMASK is nonzero. Return 0. + This is the internal name for `sigsetjmp'. */ +extern int __sigsetjmp __P ((jmp_buf __env, int __savemask)); + +#ifndef __FAVOR_BSD +/* Set ENV to the current position and return 0, not saving the signal mask. + This is just like `sigsetjmp (ENV, 0)'. + The ANSI C standard says `setjmp' is a macro. */ +#define setjmp(env) __sigsetjmp ((env), 0) +#else +/* We are in 4.3 BSD-compatibility mode in which `setjmp' + saves the signal mask like `sigsetjmp (ENV, 1)'. */ +#define setjmp(env) __sigsetjmp ((env), 1) +#endif /* Favor BSD. */ + +#ifdef __USE_BSD +/* Set ENV to the current position and return 0, not saving the signal mask. + This is the 4.3 BSD name for ANSI `setjmp'. */ +#define _setjmp(env) __sigsetjmp ((env), 0) +#endif + + +/* Jump to the environment saved in ENV, making the + `setjmp' call there return VAL, or 1 if VAL is 0. */ +extern void longjmp __P ((jmp_buf __env, int __val)) + __attribute__ ((__noreturn__)); +#ifdef __USE_BSD +/* Same. Usually `_longjmp' is used with `_setjmp', which does not save + the signal mask. But it is how ENV was saved that determines whether + `longjmp' restores the mask; `_longjmp' is just an alias. */ +extern void _longjmp __P ((jmp_buf __env, int __val)) + __attribute__ ((__noreturn__)); +#endif /* Use BSD. */ + +/* Internal machine-dependent function to restore context sans signal mask. */ +extern void __longjmp __P ((__jmp_buf __env, int __val)) + __attribute__ ((__noreturn__)); + +/* Internal function to possibly save the current mask of blocked signals + in ENV, and always set the flag saying whether or not it was saved. + This is used by the machine-dependent definition of `__sigsetjmp'. + Always returns zero, for convenience. */ +extern int __sigjmp_save __P ((jmp_buf __env, int __savemask)); + + +#ifdef __USE_POSIX +/* Use the same type for `jmp_buf' and `sigjmp_buf'. + The `__mask_was_saved' flag determines whether + or not `longjmp' will restore the signal mask. */ +typedef jmp_buf sigjmp_buf; + +/* Store the calling environment in ENV, also saving the + signal mask if SAVEMASK is nonzero. Return 0. */ +#define sigsetjmp(env, savemask) __sigsetjmp ((env), (savemask)) + +/* Jump to the environment saved in ENV, making the + sigsetjmp call there return VAL, or 1 if VAL is 0. + Restore the signal mask if that sigsetjmp call saved it. + This is just an alias `longjmp'. */ +extern void siglongjmp __P ((sigjmp_buf __env, int __val)) + __attribute__ ((__noreturn__)); +#endif /* Use POSIX. */ + +__END_DECLS + +#endif /* setjmp.h */ diff --git a/setjmp/sigjmp.c b/setjmp/sigjmp.c new file mode 100644 index 0000000000..a01c4120da --- /dev/null +++ b/setjmp/sigjmp.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1992, 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stddef.h> +#include <setjmp.h> +#include <signal.h> + +/* This function is called by the `sigsetjmp' macro + before doing a `__setjmp' on ENV[0].__jmpbuf. + Always return zero. */ + +int +DEFUN(__sigjmp_save, (env, savemask), sigjmp_buf env AND int savemask) +{ + env[0].__mask_was_saved = (savemask && + __sigprocmask (SIG_BLOCK, (sigset_t *) NULL, + &env[0].__saved_mask) == 0); + + return 0; +} diff --git a/setjmp/tst-setjmp.c b/setjmp/tst-setjmp.c new file mode 100644 index 0000000000..ef6e1f5f9f --- /dev/null +++ b/setjmp/tst-setjmp.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <ansidecl.h> +#include <stdio.h> +#include <setjmp.h> +#include <stdlib.h> + +static jmp_buf env; +static int last_value = -1, lose = 0; + +void +DEFUN(jump, (val), int val) +{ + longjmp(env, val); +} + +int +DEFUN_VOID(main) +{ + int value; + + value = setjmp(env); + if (value != last_value + 1) + { + fputs("Shouldn't have ", stdout); + lose = 1; + } + last_value = value; + switch (value) + { + case 0: + puts("Saved environment."); + jump(0); + default: + printf("Jumped to %d.\n", value); + if (value < 10) + jump(value + 1); + } + + if (lose || value != 10) + puts("Test FAILED!"); + else + puts("Test succeeded!"); + exit(lose ? EXIT_FAILURE : EXIT_SUCCESS); +} |