sshcr.h 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Coroutine mechanics used in PuTTY's SSH code.
  3. */
  4. #ifndef PUTTY_SSHCR_H
  5. #define PUTTY_SSHCR_H
  6. /*
  7. * If these macros look impenetrable to you, you might find it helpful
  8. * to read
  9. *
  10. * https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
  11. *
  12. * which explains the theory behind these macros.
  13. *
  14. * In particular, if you are getting `case expression not constant'
  15. * errors when building with MS Visual Studio, this is because MS's
  16. * Edit and Continue debugging feature causes their compiler to
  17. * violate ANSI C. To disable Edit and Continue debugging:
  18. *
  19. * - right-click ssh.c in the FileView
  20. * - click Settings
  21. * - select the C/C++ tab and the General category
  22. * - under `Debug info:', select anything _other_ than `Program
  23. * Database for Edit and Continue'.
  24. */
  25. #define crBegin(v) do { int *crLine = &v; switch(v) { case 0:
  26. #define crBeginState crBegin(s->crLine)
  27. #define crStateP(t, v) \
  28. struct t *s; \
  29. if (!(v)) { s = (v) = snew(struct t); s->crLine = 0; } \
  30. s = (v);
  31. #define crState(t) crStateP(t, ssh->t)
  32. #define crFinish(z) } *crLine = 0; return (z); } while (0)
  33. #define crFinishV } *crLine = 0; return; } while (0)
  34. #define crFinishFreed(z) } return (z); } while (0)
  35. #define crFinishFreedV } return; } while (0)
  36. #define crFinishFree(z) } sfree(s); return (z); } while (0)
  37. #define crFinishFreeV } sfree(s); return; } while (0)
  38. #define crReturn(z) \
  39. do {\
  40. *crLine =__LINE__; return (z); case __LINE__:;\
  41. } while (0)
  42. #define crReturnV \
  43. do {\
  44. *crLine=__LINE__; return; case __LINE__:;\
  45. } while (0)
  46. #define crStop(z) do{ *crLine = 0; return (z); }while(0)
  47. #define crStopV do{ *crLine = 0; return; }while(0)
  48. /*
  49. * The crMaybeWaitUntil macros could have been more easily written in
  50. * terms of the simple crReturn above, by writing things like
  51. *
  52. * while (!condition) { crReturn(whatever); }
  53. *
  54. * (or do-while in the case of crWaitUntil). But it's better to do it
  55. * directly by writing _once_ to crLine before first testing the
  56. * condition, because this way it's robust against the condition check
  57. * potentially freeing the entire coroutine state structure as a side
  58. * effect (as long as it also evaluates false if it does that),
  59. * because we don't write into crLine between the condition evaluating
  60. * to false and the 'return' statement.
  61. */
  62. #define crMaybeWaitUntil(c) \
  63. do { \
  64. *crLine =__LINE__; \
  65. case __LINE__: if (!(c)) return 0; \
  66. } while (0)
  67. #define crMaybeWaitUntilV(c) \
  68. do { \
  69. *crLine =__LINE__; \
  70. case __LINE__: if (!(c)) return; \
  71. } while (0)
  72. #define crWaitUntil(c) \
  73. do { \
  74. *crLine =__LINE__; return; \
  75. case __LINE__: if (!(c)) return 0; \
  76. } while (0)
  77. #define crWaitUntilV(c) \
  78. do { \
  79. *crLine =__LINE__; return; \
  80. case __LINE__: if (!(c)) return; \
  81. } while (0)
  82. #endif /* PUTTY_SSHCR_H */