diff --git a/sshcr.h b/sshcr.h index 18a31ff5..5abf4c17 100644 --- a/sshcr.h +++ b/sshcr.h @@ -46,9 +46,40 @@ } while (0) #define crStop(z) do{ *crLine = 0; return (z); }while(0) #define crStopV do{ *crLine = 0; return; }while(0) -#define crWaitUntil(c) do { crReturn(0); } while (!(c)) -#define crWaitUntilV(c) do { crReturnV; } while (!(c)) -#define crMaybeWaitUntil(c) do { while (!(c)) crReturn(0); } while (0) -#define crMaybeWaitUntilV(c) do { while (!(c)) crReturnV; } while (0) + +/* + * The crMaybeWaitUntil macros could have been more easily written in + * terms of the simple crReturn above, by writing things like + * + * while (!condition) { crReturn(whatever); } + * + * (or do-while in the case of crWaitUntil). But it's better to do it + * directly by writing _once_ to crLine before first testing the + * condition, because this way it's robust against the condition check + * potentially freeing the entire coroutine state structure as a side + * effect (as long as it also evaluates false if it does that), + * because we don't write into crLine between the condition evaluating + * to false and the 'return' statement. + */ +#define crMaybeWaitUntil(c) \ + do { \ + *crLine =__LINE__; \ + case __LINE__: if (!(c)) return 0; \ + } while (0) +#define crMaybeWaitUntilV(c) \ + do { \ + *crLine =__LINE__; \ + case __LINE__: if (!(c)) return; \ + } while (0) +#define crWaitUntil(c) \ + do { \ + *crLine =__LINE__; return; \ + case __LINE__: if (!(c)) return 0; \ + } while (0) +#define crWaitUntilV(c) \ + do { \ + *crLine =__LINE__; return; \ + case __LINE__: if (!(c)) return; \ + } while (0) #endif /* PUTTY_SSHCR_H */