blob: 59810e867358c57e5a38e77126ca6eef7de776d2 [file] [log] [blame]
<html lang="en">
<head>
<title>Non-Local Intro - The GNU C Library</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="The GNU C Library">
<meta name="generator" content="makeinfo 4.13">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Non_002dLocal-Exits.html#Non_002dLocal-Exits" title="Non-Local Exits">
<link rel="next" href="Non_002dLocal-Details.html#Non_002dLocal-Details" title="Non-Local Details">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<!--
This file documents the GNU C library.
This is Edition 0.12, last updated 2007-10-27,
of `The GNU C Library Reference Manual', for version
2.8 (Sourcery G++ Lite 2011.03-41).
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002,
2003, 2007, 2008, 2010 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``Free Software Needs Free Documentation''
and ``GNU Lesser General Public License'', the Front-Cover texts being
``A GNU Manual'', and with the Back-Cover Texts as in (a) below. A
copy of the license is included in the section entitled "GNU Free
Documentation License".
(a) The FSF's Back-Cover Text is: ``You have the freedom to
copy and modify this GNU manual. Buying copies from the FSF
supports it in developing GNU and promoting software freedom.''-->
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
pre.display { font-family:inherit }
pre.format { font-family:inherit }
pre.smalldisplay { font-family:inherit; font-size:smaller }
pre.smallformat { font-family:inherit; font-size:smaller }
pre.smallexample { font-size:smaller }
pre.smalllisp { font-size:smaller }
span.sc { font-variant:small-caps }
span.roman { font-family:serif; font-weight:normal; }
span.sansserif { font-family:sans-serif; font-weight:normal; }
--></style>
<link rel="stylesheet" type="text/css" href="../cs.css">
</head>
<body>
<div class="node">
<a name="Non-Local-Intro"></a>
<a name="Non_002dLocal-Intro"></a>
<p>
Next:&nbsp;<a rel="next" accesskey="n" href="Non_002dLocal-Details.html#Non_002dLocal-Details">Non-Local Details</a>,
Up:&nbsp;<a rel="up" accesskey="u" href="Non_002dLocal-Exits.html#Non_002dLocal-Exits">Non-Local Exits</a>
<hr>
</div>
<h3 class="section">23.1 Introduction to Non-Local Exits</h3>
<p>As an example of a situation where a non-local exit can be useful,
suppose you have an interactive program that has a &ldquo;main loop&rdquo; that
prompts for and executes commands. Suppose the &ldquo;read&rdquo; command reads
input from a file, doing some lexical analysis and parsing of the input
while processing it. If a low-level input error is detected, it would
be useful to be able to return immediately to the &ldquo;main loop&rdquo; instead
of having to make each of the lexical analysis, parsing, and processing
phases all have to explicitly deal with error situations initially
detected by nested calls.
<p>(On the other hand, if each of these phases has to do a substantial
amount of cleanup when it exits&mdash;such as closing files, deallocating
buffers or other data structures, and the like&mdash;then it can be more
appropriate to do a normal return and have each phase do its own
cleanup, because a non-local exit would bypass the intervening phases and
their associated cleanup code entirely. Alternatively, you could use a
non-local exit but do the cleanup explicitly either before or after
returning to the &ldquo;main loop&rdquo;.)
<p>In some ways, a non-local exit is similar to using the &lsquo;<samp><span class="samp">return</span></samp>&rsquo;
statement to return from a function. But while &lsquo;<samp><span class="samp">return</span></samp>&rsquo; abandons
only a single function call, transferring control back to the point at
which it was called, a non-local exit can potentially abandon many
levels of nested function calls.
<p>You identify return points for non-local exits by calling the function
<code>setjmp</code>. This function saves information about the execution
environment in which the call to <code>setjmp</code> appears in an object of
type <code>jmp_buf</code>. Execution of the program continues normally after
the call to <code>setjmp</code>, but if an exit is later made to this return
point by calling <code>longjmp</code> with the corresponding <code>jmp_buf</code><!-- /@w -->
object, control is transferred back to the point where <code>setjmp</code> was
called. The return value from <code>setjmp</code> is used to distinguish
between an ordinary return and a return made by a call to
<code>longjmp</code>, so calls to <code>setjmp</code> usually appear in an &lsquo;<samp><span class="samp">if</span></samp>&rsquo;
statement.
<p>Here is how the example program described above might be set up:
<pre class="smallexample"> #include &lt;setjmp.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
jmp_buf main_loop;
void
abort_to_main_loop (int status)
{
longjmp (main_loop, status);
}
int
main (void)
{
while (1)
if (setjmp (main_loop))
puts ("Back at main loop....");
else
do_command ();
}
void
do_command (void)
{
char buffer[128];
if (fgets (buffer, 128, stdin) == NULL)
abort_to_main_loop (-1);
else
exit (EXIT_SUCCESS);
}
</pre>
<p>The function <code>abort_to_main_loop</code> causes an immediate transfer of
control back to the main loop of the program, no matter where it is
called from.
<p>The flow of control inside the <code>main</code> function may appear a little
mysterious at first, but it is actually a common idiom with
<code>setjmp</code>. A normal call to <code>setjmp</code> returns zero, so the
&ldquo;else&rdquo; clause of the conditional is executed. If
<code>abort_to_main_loop</code> is called somewhere within the execution of
<code>do_command</code>, then it actually appears as if the <em>same</em> call
to <code>setjmp</code> in <code>main</code> were returning a second time with a value
of <code>-1</code>.
<p>So, the general pattern for using <code>setjmp</code> looks something like:
<pre class="smallexample"> if (setjmp (<var>buffer</var>))
/* <span class="roman">Code to clean up after premature return.</span> */
...
else
/* <span class="roman">Code to be executed normally after setting up the return point.</span> */
...
</pre>
</body></html>