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 /* Portable interfaces to OS-specific functions
24  *
25  * This file defines interfaces to certain functions that must be called
26  * from portable code, but which must have system-specific implementations.
27  */
28 
29 #ifndef GLK_TADS_TADS2_OS
30 #define GLK_TADS_TADS2_OS
31 
32 #include "common/system.h"
33 #include "glk/tads/os_frob_tads.h"
34 #include "glk/tads/os_glk.h"
35 #include "glk/tads/tads2/lib.h"
36 #include "glk/tads/tads2/appctx.h"
37 
38 namespace Glk {
39 namespace TADS {
40 namespace TADS2 {
41 
42 
43 /* ------------------------------------------------------------------------ */
44 /*
45  *   A note on character sets:
46  *
47  *   Except where noted, all character strings passed to and from the
48  *   osxxx functions defined herein use the local operating system
49  *   representation.  On a Windows machine localized to Eastern Europe,
50  *   for example, the character strings passed to and from the osxxx
51  *   functions would use single-byte characters in the Windows code page
52  *   1250 representation.
53  *
54  *   Callers that use multiple character sets must implement mappings to
55  *   and from the local character set when calling the osxxx functions.
56  *   The osxxx implementations are thus free to ignore any issues related
57  *   to character set conversion or mapping.
58  *
59  *   The osxxx implementations are specifically not permitted to use
60  *   double-byte Unicode as the native character set, nor any other
61  *   character set where a null byte could appear as part of a non-null
62  *   character.  In particular, callers may assume that null-terminated
63  *   strings passed to and from the osxxx functions contain no embedded
64  *   null bytes.  Multi-byte character sets (i.e., character sets with
65  *   mixed single-byte and double-byte characters) may be used as long as
66  *   a null byte is never part of any multi-byte character, since this
67  *   would guarantee that a null byte could always be taken as a null
68  *   character without knowledge of the encoding or context.
69  */
70 
71 /* ------------------------------------------------------------------------ */
72 /*
73  *   "Far" Pointers.  Most platforms can ignore this.  For platforms with
74  *   mixed-mode addressing models, where pointers of different sizes can
75  *   be used within a single program and hence some pointers require
76  *   qualification to indicate that they use a non-default addressing
77  *   model, the keyword OSFAR should be defined to the appropriate
78  *   compiler-specific extension keyword.
79  *
80  *   If you don't know what I'm talking about here, you should just ignore
81  *   it, because your platform probably doesn't have anything this
82  *   sinister.  As of this writing, this applies only to MS-DOS, and then
83  *   only to 16-bit implementations that must interact with other 16-bit
84  *   programs via dynamic linking or other mechanisms.
85  */
86 
87 
88 /* ------------------------------------------------------------------------ */
89 /*
90  *   ANSI C99 exact-size integer types.
91  *
92  *   C99 defines a set of integer types with exact bit sizes, named intXX_t
93  *   for a signed integer with XX bits, and uintXX_t for unsigned.  XX can be
94  *   8, 16, 32, or 64.  TADS uses the 16- and 32-bit sizes, so each platform
95  *   is responsible for defining the following types:
96  *
97  *.    int16_t   - a signed integer type storing EXACTLY 16 bits
98  *.    uint16_t  - an unsigned integer type storing EXACTLY 16 bits
99  *.    int32_t   - a signed integer type storing EXACTLY 32 bits
100  *.    uint32_t  - an unsigned integer type storing EXACTLY 32 bits
101  *
102  *   Many modern compilers provide definitions for these types via the
103  *   standard header stdint.h.  Where stdint.h is provided, the platform code
104  *   can merely #include <stdint.h>.
105  *
106  *   For compilers where stdint.h isn't available, you must provide suitable
107  *   typedefs.  Note that the types must be defined with the exact bit sizes
108  *   specified; it's not sufficient to use a bigger type, because we depend
109  *   in some cases on overflow and sign extension behavior at the specific
110  *   bit size.
111  */
112 
113 
114 /* ------------------------------------------------------------------------ */
115 /*
116  *   Thread-local storage (TLS).
117  *
118  *   When TADS is compiled with threading support, it requires some variables
119  *   to be "thread-local".  This means that the variables have global scope
120  *   (so they're not stored in "auto" variables on the stack), but each
121  *   thread has a private copy of each such variable.
122  *
123  *   Nearly all systems that support threads also support thread-local
124  *   storage.  Like threading support itself, though, TLS support is at
125  *   present implemented only in non-portable OS APIs rather than standard C
126  *   language features.  TLS is a requirement if TADS is compiled with
127  *   threading, but it's not needed for non-threaded builds.  TADS only
128  *   requires threading at present (version 3.1) for its network features;
129  *   since these features are optional, systems that don't have threading and
130  *   TLS support will simply need to disable the network features, which will
131  *   allow all of the threading and TLS definitions in osifc to be omitted.
132  *
133  *   There appear to be two common styles of TLS programming models.  The
134  *   first provides non-standard compiler syntax for declarative creation of
135  *   thread-local variables.  The Microsoft (on Windows) and Gnu compilers
136  *   (on Linux and Unix) do this: they provide custom storage class modifiers
137  *   for declaring thread locals (__declspec(thread) for MSVC, __thread for
138  *   gcc).  Compilers that support declarative thread locals handle the
139  *   implementation details through code generation, so the program merely
140  *   needs to add the special TLS storage class qualifier to an otherwise
141  *   ordinary global variable declaration, and then can access the thread
142  *   local as though it were an ordinary global.
143  *
144  *   The second programming model is via explicit OS API calls to create,
145  *   initialize, and access thread locals.  pthreads provides such an API, as
146  *   does Win32.  In fact, when you use the declarative syntax with MSVC or
147  *   gcc, the compiler generates the appropriate API calls, but the details
148  *   are transparent to the program; in contrast, when using pthreads
149  *   directly, the program must actively call the relevant APIs.
150  *
151  *   It's probably the case that every system that has compiler-level support
152  *   for declarative thread local creation also has procedural APIs, so the
153  *   simplest way to abstract the platform differences would be to do
154  *   everything in terms of APIs.  However, it seems likely that compilers
155  *   with declarative syntax might be able to generate more efficient code,
156  *   since optimizers always benefit from declarative information.  So we'd
157  *   like to use declarative syntax whenever it's available, but fall back on
158  *   explicit API calls when it's not.  So our programming model is a union
159  *   of the two styles:
160  *
161  *   1. For each thread local, declare the thread local:
162  *.      OS_DECL_TLS(char *, my_local);
163  *
164  *   2. At main program startup (for the main thread only), initialize each
165  *   thread local:
166  *.      os_tls_create(my_local);
167  *
168  *   3. Never get or set the value of a thread local directly; instead, use
169  *   the get/set functions:
170  *.      char *x = os_tls_get(char *, my_local);
171  *.      os_tls_set(my_local, "hello");
172  *
173  *   One key feature of this implementation is that each thread local is
174  *   stored as a (void *) value.  We do it this way to allow a simple direct
175  *   mapping to the pthreads APIs, since that's going to be the most common
176  *   non-declarative implementation.  This means that a thread local variable
177  *   can contain any pointer type, but *only* a pointer type.  The standard
178  *   pattern for dealing with anything more ocmplex is the same as in
179  *   pthreads: gather up the data into a structure, malloc() an instance of
180  *   that structure at entry to each thread (including the main thread), and
181  *   os_tls_set() the variable to contain a pointer to that structure.  From
182  *   then on, use os_tls_set(my_struct *, my_local)->member to access the
183  *   member variables in the structure.  And finally, each thread must delete
184  *   the structure at thread exit.
185  */
186 
187 /*
188  *
189  *   Declare a thread local.
190  *
191  *   - For compilers that support declarative TLS variables, the local OS
192  *   headers should use the compiler support by #defining OS_DECL_TLS to the
193  *   appropriate local declarative keyword.
194  *
195  *   - For systems without declarative TLS support but with TLS APIs, the
196  *   global declared by this macro actually stores the slot ID (what pthreads
197  *   calls the "key") for the variable.  This macro should therefore expand
198  *   to a declaration of the appropriate API type for a slot ID; for example,
199  *   on pthreads, #define OS_DECL_TLS(t, v) pthread_key_t v.
200  *
201  *   - For builds with no thread support, simply #define this to declare the
202  *   variable as an ordinary global: #define OS_DECL_TLS(t, v) t v.
203  */
204 /* #define OS_DECL_TLS(typ, varname)  __thread typ varname */
205 
206 /*
207  *   For API-based systems without declarative support in the compiler, the
208  *   main program startup code must explicitly create a slot for each thread-
209  *   local variable by calling os_tls_create().  The API returns a slot ID,
210  *   which is shared among threads and therefore can be stored in an ordinary
211  *   global variable.  OS_DECL_TLS will have declared the global variable
212  *   name in this case as an ordinary global of the slot ID type.  The
213  *   os_tls_create() macro should therefore expand to a call to the slot
214  *   creation API, storing the new slot ID in the global.
215  *
216  *   Correspondingly, before the main thread exits, it should delete each
217  *   slot it created, b calling os_tls_delete().
218  *
219  *   For declarative systems, there's no action required here, so these
220  *   macros can be defined to empty.
221  */
222 /* #define os_tls_create(varname)  pthread_key_create(&varname, NULL) */
223 /* #define os_tls_delete(varname)  pthread_key_delete(varname) */
224 
225 
226 /*
227  *   On API-based systems, each access to get or set the thread local
228  *   requires an API call, using the slot ID stored in the actual global to
229  *   get the per-thread instance of the variable's storage.
230  *.    #define os_tls_get(typ, varname) ((typ)pthread_getspecific(varname))
231  *.    #define os_tls_set(varname, val) pthread_setspecific(varname, val)
232  *
233  *   On declarative systems, the global variable itself is the thread local,
234  *   so get/set can be implemented as direct access to the variable.
235  *.    #define os_tls_get(typ, varname) varname
236  *.    #define os_tls_set(varname, val) varname = (val)
237  */
238 
239 /*
240  *   Common TLS definitions - declarative thread locals
241  *
242  *   For systems with declarative TLS support in the compiler, the OS header
243  *   can #define OS_DECLARATIVE_TLS to pick up suitable definitions for the
244  *   os_tls_xxx() macros.  The OS header must separately define OS_DECL_TLS
245  *   as appropriate for the local system.
246  */
247 #ifdef OS_DECLARATIVE_TLS
248 #define os_tls_create(varname)
249 #define os_tls_delete(varname)
250 #define os_tls_get(typ, varname) varname
251 #define os_tls_set(varname, val) varname = (val)
252 #endif
253 
254 /*
255  *   Common TLS definitions - pthreads
256  *
257  *   For pthreads systems without declarative TLS support in the compiler,
258  *   the OS header can simply #define OS_PTHREAD_TLS to pick up the standard
259  *   definitions below.
260  */
261 #ifdef OS_PTHREAD_TLS
262 #include <pthread.h>
263 #define OS_DECL_TLS(typ, varname) pthread_key_t varname
264 #define os_tls_create(varname) pthread_key_create(&varname, NULL)
265 #define os_tls_delete(varname) pthread_key_delete(varname)
266 #define os_tls_get(typ, varname) ((typ)pthread_getspecific(varname))
267 #define os_tls_set(varname, val) pthread_setspecific(varname, val)
268 #endif
269 
270 /* ------------------------------------------------------------------------ */
271 /*
272  *   OS main entrypoint
273  */
274 int os0main(int oargc, char **oargv,
275             int (*mainfn)(int, char **, char *),
276             const char *before, const char *config);
277 
278 /*
279  *   new-style OS main entrypoint - takes an application container context
280  */
281 int os0main2(int oargc, char **oargv,
282              int (*mainfn)(int, char **, appctxdef *, char *),
283              const char *before, const char *config,
284              appctxdef *appctx);
285 
286 
287 /* open the error message file for reading */
288 osfildef *oserrop(const char *arg0);
289 
290 /* ------------------------------------------------------------------------ */
291 /*
292  *   Special "switch" statement optimization flags.  These definitions are
293  *   OPTIONAL - if a platform doesn't provide these definitions, suitable
294  *   code that's fully portable will be used.
295  *
296  *   On some compilers, the performance of a "switch" statement can be
297  *   improved by fully populating the switch with all possible "case"
298  *   values.  When the compiler can safely assume that every possible "case"
299  *   value is specifically called out in the switch, the compiler can
300  *   generate somewhat faster code by omitting any range check for the
301  *   controlling expression of the switch: a range check is unnecessary
302  *   because the compiler knows that the value can never be outside the
303  *   "case" table.
304  *
305  *   This type of optimization doesn't apply to all compilers.  When a given
306  *   platform's compiler can be coerced to produce faster "switch"
307  *   statements, though, there might be some benefit in defining these
308  *   symbols according to local platform rules.
309  *
310  *   First, #define OS_FILL_OUT_CASE_TABLES if you want this type of switch
311  *   optimization at all.  This symbol is merely a flag, so it doesn't need
312  *   a value - #defining it is enough to activate the special code.  If you
313  *   don't define this symbol, then the code that cares about this will
314  *   simply generate ordinary switches, leaving holes in the case table and
315  *   using "default:" to cover them.  If the platform's osxxx.h header does
316  *   #define OS_FILL_OUT_CASE_TABLES, then the portable code will know to
317  *   fill out case tables with all possible alternatives where it's possible
318  *   and potentially beneficial to do so.
319  *
320  *   Second, if you #define OS_FILL_OUT_CASE_TABLES, you MUST ALSO #define
321  *   OS_IMPOSSIBLE_DEFAULT_CASE.  The value for this symbol must be some
322  *   code to insert into a "switch" statement at the point where a
323  *   "default:" case would normally go.  On some compilers, special
324  *   extensions allow the program to explicitly indicate within a switch
325  *   that all possible cases are covered, so that the compiler doesn't have
326  *   to be relied upon to infer this for itself (which would be impossible
327  *   for it to do in many cases anyway).  You can use an empty definition
328  *   for this symbol if your compiler doesn't have any special construct for
329  *   indicating a fully-populated case table.
330  *
331  *   Note that *most* switch statements in portable code won't care one way
332  *   or the other about these definitions.  There's a time/space trade-off
333  *   in fully populating a switch's case table, so only the most
334  *   time-critical code will bother trying.
335  */
336 
337 
338 
339 /* ------------------------------------------------------------------------ */
340 /*
341  *   TADS 2 swapping configuration.  Define OS_DEFAULT_SWAP_ENABLED to 0
342  *   if you want swapping turned off, 1 if you want it turned on.  If we
343  *   haven't defined a default swapping mode yet, turn swapping on by
344  *   default.
345  */
346 #ifndef OS_DEFAULT_SWAP_ENABLED
347 # define OS_DEFAULT_SWAP_ENABLED   1
348 #endif
349 
350 /*
351  *   If the system "long description" (for the banner) isn't defined, make
352  *   it the same as the platform ID string.
353  */
354 #ifndef OS_SYSTEM_LDESC
355 # define OS_SYSTEM_LDESC  OS_SYSTEM_NAME
356 #endif
357 
358 /*
359  *   TADS 2 Usage Lines
360  *
361  *   If the "usage" lines (i.e., the descriptive lines of text describing
362  *   how to run the various programs) haven't been otherwise defined,
363  *   define defaults for them here.  Some platforms use names other than
364  *   tc, tr, and tdb for the tools (for example, on Unix they're usually
365  *   tadsc, tadsr, and tadsdb), so the usage lines should be adjusted
366  *   accordingly; simply define them earlier than this point (in this file
367  *   or in one of the files included by this file, such as osunixt.h) for
368  *   non-default text.
369  */
370 #ifndef OS_TC_USAGE
371 # define OS_TC_USAGE  "usage: tc [options] file"
372 #endif
373 #ifndef OS_TR_USAGE
374 # define OS_TR_USAGE  "usage: tr [options] file"
375 #endif
376 #ifndef OS_TDB_USAGE
377 # define OS_TDB_USAGE  "usage: tdb [options] file"
378 #endif
379 
380 /*
381  *   Ports can define a special TDB startup message, which is displayed
382  *   after the copyright/version banner.  If it's not defined at this
383  *   point, define it to an empty string.
384  */
385 #ifndef OS_TDB_STARTUP_MSG
386 # define OS_TDB_STARTUP_MSG ""
387 #endif
388 
389 /*
390  *   If a system patch sub-level isn't defined, define it here as zero.
391  *   The patch sub-level is used on some systems where a number of ports
392  *   are derived from a base port (for example, a large number of ports
393  *   are based on the generic Unix port).  For platforms like the Mac,
394  *   where the porting work applies only to that one platform, this
395  *   sub-level isn't meaningful.
396  */
397 #ifndef OS_SYSTEM_PATCHSUBLVL
398 # define OS_SYSTEM_PATCHSUBLVL  "0"
399 #endif
400 
401 } // End of namespace TADS2
402 } // End of namespace TADS
403 } // End of namespace Glk
404 
405 #endif
406