mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-08 08:58:00 +00:00
76430f8237
These were just too footling for even me to bother splitting up into
multiple commits:
- a couple of int -> size_t changes left out of the big-bang commit
0cda34c6f
- a few 'const' added to pointer-type casts that are only going to be
read from (leaving out the const provokes a warning if the pointer
was const _before_ the cast)
- a couple of 'return' statements trying to pass the void return of
one function through to another.
- another missing (void) in a declaration in putty.h (but this one
didn't cause any knock-on confusion).
- a few tweaks to macros, to arrange that they eat a semicolon after
the macro call (extra do ... while (0) wrappers, mostly, and one
case where I had to do it another way because the macro included a
variable declaration intended to remain in scope)
- reworked key_type_to_str to stop putting an unreachable 'break'
statement after every 'return'
- removed yet another type-check of a function loaded from a Windows
system DLL
- and finally, a totally spurious semicolon right after an open brace
in mainchan.c.
88 lines
3.3 KiB
C
88 lines
3.3 KiB
C
/*
|
|
* Coroutine mechanics used in PuTTY's SSH code.
|
|
*/
|
|
|
|
#ifndef PUTTY_SSHCR_H
|
|
#define PUTTY_SSHCR_H
|
|
|
|
/*
|
|
* If these macros look impenetrable to you, you might find it helpful
|
|
* to read
|
|
*
|
|
* https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
|
|
*
|
|
* which explains the theory behind these macros.
|
|
*
|
|
* In particular, if you are getting `case expression not constant'
|
|
* errors when building with MS Visual Studio, this is because MS's
|
|
* Edit and Continue debugging feature causes their compiler to
|
|
* violate ANSI C. To disable Edit and Continue debugging:
|
|
*
|
|
* - right-click ssh.c in the FileView
|
|
* - click Settings
|
|
* - select the C/C++ tab and the General category
|
|
* - under `Debug info:', select anything _other_ than `Program
|
|
* Database for Edit and Continue'.
|
|
*/
|
|
|
|
#define crBegin(v) do { int *crLine = &v; switch(v) { case 0:
|
|
#define crBeginState crBegin(s->crLine)
|
|
#define crStateP(t, v) \
|
|
struct t *s; \
|
|
if (!(v)) { s = (v) = snew(struct t); s->crLine = 0; } \
|
|
s = (v);
|
|
#define crState(t) crStateP(t, ssh->t)
|
|
#define crFinish(z) } *crLine = 0; return (z); } while (0)
|
|
#define crFinishV } *crLine = 0; return; } while (0)
|
|
#define crFinishFreed(z) } return (z); } while (0)
|
|
#define crFinishFreedV } return; } while (0)
|
|
#define crFinishFree(z) } sfree(s); return (z); } while (0)
|
|
#define crFinishFreeV } sfree(s); return; } while (0)
|
|
#define crReturn(z) \
|
|
do {\
|
|
*crLine =__LINE__; return (z); case __LINE__:;\
|
|
} while (0)
|
|
#define crReturnV \
|
|
do {\
|
|
*crLine=__LINE__; return; case __LINE__:;\
|
|
} while (0)
|
|
#define crStop(z) do{ *crLine = 0; return (z); }while(0)
|
|
#define crStopV do{ *crLine = 0; return; }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 */
|