agostino@concour.cs.concordia.ca (Agostino Deligia) (04/26/91)
Hello, Could anyone out there e-mail me an example on how to use setjmp() and longjmp() to return from a low-level function to an upper-level function? For example: void Parse(void) { Init(); DoIt(); fini: /* this is where to jump to before quitting Parse() */ CleanUp(); } ... void P_E(void) { ... P_F(); ... } void P_F(void) { ... if (error) /* jump to 'fini' in Parse() */ ... } I read the man pages for setjmp()/longjmp(), but the code fragment they give doesn't help much. Also, the only book on C that I have doesn't cover setjmp()/longjmp(). Any help would be greatly appreciated. Thank-you. Agostino Deligia -- ------------------------------------------------------------------------------- OO OO Agostino Deligia O O O Systems Architecture O O O Concordia University, Montreal (Canada)
john@newave.UUCP (John A. Weeks III) (04/27/91)
In article <215@daily-planet.concordia.ca> agostino@concour.cs.concordia.ca (Agostino Deligia) writes: > Could anyone out there e-mail me an example on how to use setjmp() and > longjmp() to return from a low-level function to an upper-level function? > I read the man pages for setjmp()/longjmp(), but the code fragment they > give doesn't help much. Also, the only book on C that I have doesn't cover > setjmp()/longjmp(). I'll say--I had to see them work before I caught on. An example can be found in the book "UNIX Programming Environment" by Kernighan and Pike. This book, often refered to as K&P, is a must have for anyone with interest in UNIX and C. Another good book is Using C On The UNIX System by the Nutshell people (O'Reilly & Associates). Think of the setjmp() procedure this way. When your program executes it, it sort of appears to do nothing. But when you call longjmp() later on, your program appears to start executing as if the setjmp() procedure was just called. It acts like a goto. Setjmp() does actually do something when it is called. It saves some facts about your program. This information is needed so the program can pick up running at the setjmp() when your longjmp() is called. It needs a program storage area called a jmp_buf. It stores things like register values and the stack pointer. The real trick is how does your program know if you are returning from setjmp() because you called setjmp(), or because you called longjmp()? The return value of setjmp() lets you know. If you call setjmp(), it returns 0. If longjmp() is called, an integer passed as the second parameter to longjmp() is returned by setjmp(). Why would you want to use setjmp()? I think that it is pretty ugly, just another type of goto, but I like to use it in my error traping code. Often you want to exit() when you get an error, but sometimes you need to do some type of clean-up work. You can longjmp() back somewhere and do whatever you need to do in a central location. Here is an example: jmp_buf retbuf; main() { /* do some stuff */ if ( setjmp( retbuf ) == 0 ) { someproc() } else printf( "exit on some error\n" ); exit( 0 ); } void someproc( void ) { /* do some stuff */ if ( some_type_of_error() ) longjmp( retbuf, 1 ); /* do some more stuff */ } When main() executes, setjmp is called the first time. It returns zero, so the someproc() routine is called. If someproc() does not call longjmp, it will return and the exit is executed. If someproc() calls the longjmp, setjmp will return nonzero, and the program will pick up executing the printf, then exit. Pure black magic! -john- -- ============================================================================= John A. Weeks III (612) 942-6969 john@newave.mn.org NeWave Communications ...uunet!tcnet!wd0gol!newave!john