1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef GLK_ALAN2_JUMPS
24 #define GLK_ALAN2_JUMPS
25 
26 /* This provides a simplified version of the ScummVM coroutines to allow for automated
27  * breakouts to the main game loop from subroutinese rather than using unportable setjmps
28  */
29 
30 #include "common/str.h"
31 
32 namespace Glk {
33 namespace Alan3 {
34 
35 /**
36  * Context used for flagging when a break to the outer game loop
37  */
38 struct Context {
39 	bool _break;
40 	Common::String _label;
41 
42 	/**
43 	 * Constructor
44 	 */
ContextContext45 	Context() : _break(false) {}
46 
47 	/**
48 	 * Clear
49 	 */
clearContext50 	void clear() {
51 		_break = false;
52 		_label = "";
53 	}
54 };
55 
56 #define CALL0(METHOD) { METHOD(context); if (context._break) return; }
57 #define CALL1(METHOD, P1) { METHOD(context, P1); if (context._break) return; }
58 #define CALL2(METHOD, P1, P2) { METHOD(context, P1, P2); if (context._break) return; }
59 #define CALL3(METHOD, P1, P2, P3) { METHOD(context, P1, P2, P3); if (context._break) return; }
60 #define CALL4(METHOD, P1, P2, P3, P4) { METHOD(context, P1, P2, P3, P4); if (context._break) return; }
61 #define FUNC0(METHOD, RET) { RET = METHOD(context); if (context._break) return; }
62 #define FUNC1(METHOD, RET, P1) { RET = METHOD(context, P1); if (context._break) return; }
63 #define FUNC2(METHOD, RET, P1, P2) { RET = METHOD(context, P1, P2); if (context._break) return; }
64 #define FUNC3(METHOD, RET, P1, P2, P3) { RET = METHOD(context, P1, P2, P3); if (context._break) return; }
65 #define FUNC4(METHOD, RET, P1, P2, P3, P4) { RET = METHOD(context, P1, P2, P3, P4); if (context._break) return; }
66 
67 #define R0CALL0(METHOD) { METHOD(context); if (context._break) return 0; }
68 #define R0CALL1(METHOD, P1) { METHOD(context, P1); if (context._break) return 0; }
69 #define R0CALL2(METHOD, P1, P2) { METHOD(context, P1, P2); if (context._break) return 0; }
70 #define R0CALL3(METHOD, P1, P2, P3) { METHOD(context, P1, P2, P3); if (context._break) return 0; }
71 #define R0CALL4(METHOD, P1, P2, P3, P4) { METHOD(context, P1, P2, P3, P4); if (context._break) return 0; }
72 #define R0FUNC0(METHOD, RET) { RET = METHOD(context); if (context._break) return 0; }
73 #define R0FUNC1(METHOD, RET, P1) { RET = METHOD(context, P1); if (context._break) return 0; }
74 #define R0FUNC2(METHOD, RET, P1, P2) { RET = METHOD(context, P1, P2); if (context._break) return 0; }
75 #define R0FUNC3(METHOD, RET, P1, P2, P3) { RET = METHOD(context, P1, P2, P3); if (context._break) return 0; }
76 #define R0FUNC4(METHOD, RET, P1, P2, P3, P4) { RET = METHOD(context, P1, P2, P3, P4); if (context._break) return 0; }
77 
78 #define CONTEXT Context &context
79 #define LONG_JUMP { context._break = true; context._label = "turn"; return; }
80 #define LONG_JUMP0 { context._break = true; return 0; }
81 #define LONG_JUMP_LABEL(LBL) { context._break = true; context._label = LBL; return; }
82 #define LONG_JUMP_LABEL0(LBL) { context._break = true; context._label = LBL; return 0; }
83 
84 } // End of namespace Alan2
85 } // End of namespace Glk
86 
87 #endif
88