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