return value of setjmp 
Author Message
 return value of setjmp

how can I determine the return value from setjmp, if that macro may only be
called

    - as the controlling expression of an if-statement
    - as the controlling expression of a switch-statement
    - as part of an equality comparison.

Am I missing something?

thanks, Thomas



Fri, 09 Jan 2004 23:16:53 GMT  
 return value of setjmp

Quote:

> how can I determine the return value from setjmp, if that macro may only be
> called

>     - as the controlling expression of an if-statement
>     - as the controlling expression of a switch-statement
>     - as part of an equality comparison.

With difficulty. No, I'm not kidding.

Quote:
> Am I missing something?

No.

Richard



Sat, 10 Jan 2004 00:10:36 GMT  
 return value of setjmp

Quote:

>how can I determine the return value from setjmp, if that macro may only be
>called

>    - as the controlling expression of an if-statement
>    - as the controlling expression of a switch-statement
>    - as part of an equality comparison.

>Am I missing something?

Yes, all this:

        An invocation of the setjmp macro shall appear only in the following
        contexts:

        --- the entire controlling expression of a selection or
            iteration statement;
        --- one operand of a relational or equality operator with the other
            operand an integer constant expression, with the resulting
            expression being the entire controlling expression of a selection
            or iteration statement;
        --- the operand of a unary ! operator with the resulting expression
            being the entire controlling expression of a selection or
            iteration statement; or
        --- the entire expression of an expression statement (possibly
            cast to void).

        If the invocation appears in any other context, the behavior
        is undefined.



Sat, 10 Jan 2004 02:31:39 GMT  
 return value of setjmp

Quote:

> >how can I determine the return value from setjmp, if that macro may only
be
> >called

> >    - as the controlling expression of an if-statement
> >    - as the controlling expression of a switch-statement
> >    - as part of an equality comparison.

> >Am I missing something?

> Yes, all this:

> An invocation of the setjmp macro shall appear only in the following
> contexts:

> --- the entire controlling expression of a selection or
>     iteration statement;
> --- one operand of a relational or equality operator with the other
>     operand an integer constant expression, with the resulting
>     expression being the entire controlling expression of a selection
>     or iteration statement;
> --- the operand of a unary ! operator with the resulting expression
>     being the entire controlling expression of a selection or
>     iteration statement; or
> --- the entire expression of an expression statement (possibly
>     cast to void).

> If the invocation appears in any other context, the behavior
> is undefined.

Thanks for your replies so far. Kaz, can I portably determine the return
value or not?
Perhaps like this?

    jmp_buf buf;
    int x;
    x = setjmp (buf);

Thanks again,
Thomas



Sat, 10 Jan 2004 02:42:02 GMT  
 return value of setjmp

Quote:



> > >how can I determine the return value from setjmp, [...]

> > An invocation of the setjmp macro shall appear only in the following
> > contexts:

> > --- the entire controlling expression of a selection or
> >     iteration statement;
> > --- one operand of a relational or equality operator with the other
> >     operand an integer constant expression, with the resulting
> >     expression being the entire controlling expression of a selection
> >     or iteration statement;
> > --- the operand of a unary ! operator with the resulting expression
> >     being the entire controlling expression of a selection or
> >     iteration statement; or
> > --- the entire expression of an expression statement (possibly
> >     cast to void).

> > If the invocation appears in any other context, the behavior
> > is undefined.

> Thanks for your replies so far. Kaz, can I portably determine the return
> value or not?
> Perhaps like this?

>     jmp_buf buf;
>     int x;
>     x = setjmp (buf);

    Well, let's see.  Is this invocation "the entire controlling
expression of a selection or iteration statement?"  No.  Is it "one
operand of a relational or equality operator with the other operand
an integer constant expression, with the resulting expression being
the entire controlling expression of a selection or iteration
statement?"  No.  Is it "the operand of a unary ! operator with the
resulting expression being the entire controlling expression of a
selection or iteration statement?"  No.  Is it "the entire expression
of an expression statement (possibly cast to void)?"  No, again.  Is
it "any other context?"  At last: YES!  And the behavior is <<thinks>>
"undefined!"

    The only portable way I can think of is to use a switch() and
enumerate all the possible values:

        jmp_buf buf;
        int x;
        switch (setjmp(buf)) {
        case 0:
            x = 0;
            /* other stuff */
            break;
        case 1:  x = 1;  break;
        case 2:  x = 2;  break;
        ...
        case N:  x = N;  break;
        default:
            fputs ("unanticipated value from setjmp()\n", stderr);
            exit (EXIT_FAILURE);
        }

This suggestion may sound silly at first -- how, after all, are you
going to enumerate all possible `int' values as case labels? -- but
since it's your own program you are presumably also writing the calls
to longjmp().  If you call longjmp() with a smallish set of values,
exhaustive enumeration may actually make sense.  (And if you call
longjmp() with a largish set of values, you're misusing the mechanism.)

--



Sat, 10 Jan 2004 03:12:43 GMT  
 return value of setjmp

Quote:


>> An invocation of the setjmp macro shall appear only in the following
>> contexts:

>> --- the entire controlling expression of a selection or
>>     iteration statement;
>> --- one operand of a relational or equality operator with the other
>>     operand an integer constant expression, with the resulting
>>     expression being the entire controlling expression of a selection
>>     or iteration statement;
>> --- the operand of a unary ! operator with the resulting expression
>>     being the entire controlling expression of a selection or
>>     iteration statement; or
>> --- the entire expression of an expression statement (possibly
>>     cast to void).

>> If the invocation appears in any other context, the behavior
>> is undefined.

>Thanks for your replies so far. Kaz, can I portably determine the return
>value or not?
>Perhaps like this?

>    jmp_buf buf;
>    int x;
>    x = setjmp (buf);

Note that the setjmp() here does not match any of the above rules, so
the behavior is undefined.  You have an expression-statement, but the
setjmp is not the entire expression statement; rather it is the right
constituent of the assignment operator.

What if the longjmp() return tries to restore the state of local auto
variables? Which effect takes place first then, the assignment to x,
or the restoring of the saved context, affecting x? Since they are all
in one expression, it's anyone's guess.

There isn't any portable way to save the return value. If you want to
pass values upward from the site of the longjmp, perhaps to emulate
exception handling, store a value somewhere, and retrieve it from
there. Use the setjmp() value only to determine whether or not
the return is direct, or via longjmp().

For example:

        struct exception {
                jmp_buf return_here;
                int volatile return_code;
        };

        void thrower(struct exception *pexc)
        {
                pexc->return_code = 42;
                longjmp(pexc->jmp_buf, 1);
        }

        void catcher(void)
        {
                struct exception exc;

                if (setjmp(&exc.jmp_buf) == 0) {
                        // ``try''
                        thrower(&exc);
                } else {
                        // ``catch''

                        int return_code = exc.return_code; // retrieve code
                }
        }

That's the general idea: augment your jmp_buf with additional satellite
information to implement a more sophisticated exception handling system
that can return arbitrary values to the caller and so on.

If you have just a small range of codes, of course you can do:

        switch (setjmp(...)) {
        case 0:
                /* normal return */
                break;
        case PRINTER_OUT_OF_PAPER:
                ...
                break;
        case PRINTER_ON_FIRE:
                ...
                break;
        case PRINTER_PAPER_JAM:
                ...
                break;
        }



Sat, 10 Jan 2004 04:20:15 GMT  
 return value of setjmp

Quote:
>how can I determine the return value from setjmp, if that macro may only be
>called

>    - as the controlling expression of an if-statement
>    - as the controlling expression of a switch-statement
>    - as part of an equality comparison.

The easiest thing is to store it in a global variable and use that
global variable in the longjmp call.  Not very elegant, but it solves
your problem with minimum of headaches and without invoking undefined
behaviour.

Dan
--
Dan Pop
CERN, IT Division

Mail:  CERN - IT, Bat. 31 1-014, CH-1211 Geneve 23, Switzerland



Sat, 10 Jan 2004 05:35:29 GMT  
 
 [ 7 post ] 

 Relevant Pages 

1. setjmp(jmpbuf env) and longjump(jmpbuf env, int value)

2. setjmp in expressions (the 1301st question about setjmp)

3. To setjmp/longjmp or NOT to setjmp/longjmp in C++ programs

4. Simple C++ question: Using return values (by value)

5. Returning error values vs. not returning

6. Not all code paths return a value

7. why my dropdownlist doesn't return right value

8. Named Return Value Optimization

9. Method Output Parameter vs Return Value

10. Array as Return Value

11. Help... return confirmation value

12. Message (OnNotifyMessage), how to return bool value?

 

 
Powered by phpBB® Forum Software