| | 1 | /* OS-layer functions and macros. |
| | 2 | * |
| | 3 | * This file does not introduce any curses (or other screen-API) |
| | 4 | * dependencies; it can be used for both the interpreter as well as the |
| | 5 | * compiler. |
| | 6 | */ |
| | 7 | #ifndef OSFROBTADS_H |
| | 8 | #define OSFROBTADS_H |
| | 9 | |
| | 10 | #include "common.h" |
| | 11 | |
| | 12 | /* Standard C headers should never be included from inside an extern "C" |
| | 13 | * block. However, we are included from tads2/os.h from inside such a |
| | 14 | * block ourselves, so everything we include will be extern "C" too. |
| | 15 | * We need to reverse this or some compilers will bark (Sun C++ 5.9 on |
| | 16 | * Linux, for example.) |
| | 17 | */ |
| | 18 | #ifdef __cplusplus |
| | 19 | extern "C++" { |
| | 20 | #endif |
| | 21 | #include <stdlib.h> |
| | 22 | #include <stdio.h> |
| | 23 | #include <unistd.h> |
| | 24 | #ifdef __cplusplus |
| | 25 | } |
| | 26 | #endif |
| | 27 | |
| | 28 | /* Some parts in the basecode behave differently when UNIX is defined, |
| | 29 | like using "Makefile.t3m" instead "makefile.t3m" as the default |
| | 30 | project file and turning off stdout buffering in the test suite. |
| | 31 | */ |
| | 32 | #ifndef UNIX |
| | 33 | #define UNIX |
| | 34 | #endif |
| | 35 | |
| | 36 | /* We don't support the Atari 2600. */ |
| | 37 | #include "osbigmem.h" |
| | 38 | |
| | 39 | /* Provide some non-standard functions (memicmp(), etc). */ |
| | 40 | #include "missing.h" |
| | 41 | |
| | 42 | /* Our Tads OEM identifier. */ |
| | 43 | #define TADS_OEM_NAME PACKAGE_MAINTAINER " <" PACKAGE_BUGREPORT ">" |
| | 44 | |
| | 45 | /* We assume that the C-compiler is mostly ANSI compatible. */ |
| | 46 | #define OSANSI |
| | 47 | |
| | 48 | /* Special function qualifier needed for certain types of callback |
| | 49 | * functions. This is for old 16-bit systems; we don't need it and |
| | 50 | * define it to nothing. */ |
| | 51 | #define OS_LOADDS |
| | 52 | |
| | 53 | /* Unices don't suffer the near/far pointers brain damage (thank God) so |
| | 54 | * we make this a do-nothing macro. */ |
| | 55 | #define osfar_t |
| | 56 | |
| | 57 | /* This is used to explicitly discard computed values (some compilers |
| | 58 | * would otherwise give a warning like "computed value not used" in some |
| | 59 | * cases). Casting to void should work on every ANSI-Compiler. */ |
| | 60 | #define DISCARD (void) |
| | 61 | |
| | 62 | /* Copies a struct into another. ANSI C allows the assignment operator |
| | 63 | * to be used with structs. */ |
| | 64 | #define OSCPYSTRUCT(x,y) ((x)=(y)) |
| | 65 | |
| | 66 | /* Link error messages into the application. */ |
| | 67 | #define ERR_LINK_MESSAGES |
| | 68 | |
| | 69 | /* Program Exit Codes. */ |
| | 70 | #define OSEXSUCC 0 /* Successful completion. */ |
| | 71 | #define OSEXFAIL 1 /* Failure. */ |
| | 72 | |
| | 73 | /* The default size for the UNDO-buffer is quite small; the player is |
| | 74 | * only allowed to UNDO about 5 or 6 times. We'll make the size of this |
| | 75 | * buffer configurable by the user. |
| | 76 | * |
| | 77 | * See tads3/vmparam.h for more info. |
| | 78 | * |
| | 79 | * We achieve this by redefining the macro that TADS uses to store the |
| | 80 | * buffer-size as a normal variable. Fortunately, TADS3 allocates this |
| | 81 | * buffer either through 'new' or malloc(), never as a static array, so |
| | 82 | * this approach works on every compiler no matter if dynamically-sized |
| | 83 | * arrays are supported or not (ISO C++ forbids things like |
| | 84 | * "int a[variable];"). |
| | 85 | * |
| | 86 | * This stuff is only useful for the interpreter, so we omit it when |
| | 87 | * building the compiler. |
| | 88 | */ |
| | 89 | #ifdef RUNTIME |
| | 90 | /* First, we need to know what TADS3 uses as default. This is defined |
| | 91 | * in vmparam.h. */ |
| | 92 | #include "vmparam.h" |
| | 93 | /* We store the default in a static variable since the macro-expansion |
| | 94 | * needs to happen right now as we redefine this macro later. */ |
| | 95 | static const int defaultVmUndoMaxRecords = VM_UNDO_MAX_RECORDS; |
| | 96 | /* Since we'll redefine this macro, we must undefine it first, as is |
| | 97 | * required by standard C and C++. */ |
| | 98 | #undef VM_UNDO_MAX_RECORDS |
| | 99 | #undef VM_UNDO_MAX_SAVEPTS |
| | 100 | /* Now we'll turn the macro into a normal variable. */ |
| | 101 | #define VM_UNDO_MAX_RECORDS frobVmUndoMaxRecords |
| | 102 | extern int frobVmUndoMaxRecords; |
| | 103 | /* The maximum number of allowed savepoints has a hard-coded upper-limit |
| | 104 | * of 255 in the TADS3 base code. Since this value has no direct effect |
| | 105 | * on memory consumption (it's the max undo records that matters) we'll |
| | 106 | * just use the maximum and won't provide a way to change it. */ |
| | 107 | #define VM_UNDO_MAX_SAVEPTS 255 |
| | 108 | #endif /* RUNTIME */ |
| | 109 | |
| | 110 | /* Here we configure the osgen layer; refer to tads2/osgen3.c for more |
| | 111 | * information about the meaning of these macros. */ |
| | 112 | #define USE_DOSEXT |
| | 113 | #define USE_NULLSTYPE |
| | 114 | #define USE_NULL_SET_TITLE |
| | 115 | /* STD_OSCLS is undocumented; it enables a standard oscls() |
| | 116 | * implementation. */ |
| | 117 | #define STD_OSCLS |
| | 118 | /* Undocumented; enables a standard implementation of the highlighting & |
| | 119 | * colors routines. It also enables the osgen3 banner API |
| | 120 | * implementation. */ |
| | 121 | #define STD_OS_HILITE |
| | 122 | /* The following osgen configuration macros aren't needed by the |
| | 123 | * compiler, so we only define them if we are building the interpreter. |
| | 124 | */ |
| | 125 | #ifdef RUNTIME |
| | 126 | # define USE_STATLINE |
| | 127 | # define USE_SCROLLBACK |
| | 128 | # define USE_HISTORY |
| | 129 | /* OS_SBSTAT is undocumented, but needed by osgen3; it should contain |
| | 130 | * the string to print when scrollback-mode is activated. */ |
| | 131 | # define OS_SBSTAT "Review Mode - Keys: Up/Down/PageUp/PageDown - F1/Esc to exit" |
| | 132 | /* Undocumented; size of the command-history buffer. */ |
| | 133 | # define HISTBUFSIZE 1000 |
| | 134 | /* status_mode is an undocumented variable, but needed by osgen3. It |
| | 135 | * keeps track of where game-text should go (statusline, game window, |
| | 136 | * nowhere). We don't need to know anything about that though; we just |
| | 137 | * define it so that osgen3.c compiles and links without errors, as it |
| | 138 | * doesn't define it itself for some reason. */ |
| | 139 | extern int status_mode; |
| | 140 | #else |
| | 141 | /* Tell osgen to use stdio-routines for certain functions (the |
| | 142 | * compiler doesn't need anything more than that). */ |
| | 143 | # define USE_STDIO |
| | 144 | /* Use a do-nothing os_score() function. */ |
| | 145 | # define USE_NULLSCORE |
| | 146 | /* The compiler doesn't actually use os_xlat_html4(); we just define |
| | 147 | * it as an empty macro so the linker won't bark. */ |
| | 148 | # define os_xlat_html4(html4_char,result,result_buf_len) |
| | 149 | #endif |
| | 150 | |
| | 151 | /* Tell tads2/osnoui.c that we provide our own implementation of |
| | 152 | * tempfile creation/deletion routines. */ |
| | 153 | #define OSNOUI_OMIT_TEMPFILE |
| | 154 | |
| | 155 | /* Override the default makefile for the TADS 3 compiler. We'll |
| | 156 | * capitalize the fist letter (as is usual in Unix). */ |
| | 157 | #ifdef T3_DEFAULT_PROJ_FILE |
| | 158 | # undef T3_DEFAULT_PROJ_FILE |
| | 159 | # define T3_DEFAULT_PROJ_FILE "Makefile.t3m" |
| | 160 | #endif |
| | 161 | |
| | 162 | /* System identifier and system descriptive name. We also state |
| | 163 | * "Windows" since we compile and run just fine under MS Windows. We |
| | 164 | * ommit "curses" in the compilers, as only the interpreter uses |
| | 165 | * curses. */ |
| | 166 | #ifdef RUNTIME |
| | 167 | # define OS_SYSTEM_NAME "CURSES" |
| | 168 | # define OS_SYSTEM_LDESC "curses (POSIX/Unix/MS-Windows)" |
| | 169 | #else |
| | 170 | # define OS_SYSTEM_NAME "POSIX_UNIX_MSWINDOWS" |
| | 171 | # define OS_SYSTEM_LDESC "POSIX/Unix/MS-Windows" |
| | 172 | #endif |
| | 173 | |
| | 174 | /* Theoretical maximum osmalloc() size. |
| | 175 | * Unix systems have at least a 32-bit memory space. Even on 64-bit |
| | 176 | * systems, 2^32 is a good value, so we don't bother trying to find out |
| | 177 | * an exact value. */ |
| | 178 | #define OSMALMAX 0xffffffffL |
| | 179 | |
| | 180 | /* Maximum length of a filename. */ |
| | 181 | #define OSFNMAX 255 |
| | 182 | |
| | 183 | #ifndef OSPATHALT |
| | 184 | /* Other path separator characters. */ |
| | 185 | #define OSPATHALT "" |
| | 186 | #endif |
| | 187 | |
| | 188 | #ifndef OSPATHURL |
| | 189 | /* Path separator characters for URL conversions. */ |
| | 190 | #define OSPATHURL "/" |
| | 191 | #endif |
| | 192 | |
| | 193 | #ifndef OSPATHCHAR |
| | 194 | /* Normal path separator character. */ |
| | 195 | #define OSPATHCHAR '/' |
| | 196 | #endif |
| | 197 | |
| | 198 | #ifndef OS_NEWLINE_SEQ |
| | 199 | /* ASCII string giving the local newline sequence to write on output. */ |
| | 200 | #define OS_NEWLINE_SEQ "\n" |
| | 201 | #endif |
| | 202 | |
| | 203 | /* Directory separator for PATH-style environment variables. */ |
| | 204 | #define OSPATHSEP ':' |
| | 205 | |
| | 206 | /* File handle structure for osfxxx functions. */ |
| | 207 | typedef FILE osfildef; |
| | 208 | |
| | 209 | /* The maximum width of a line of text. |
| | 210 | * |
| | 211 | * We ignore this, but the base code needs it defined. If the |
| | 212 | * interpreter is run inside a console or terminal with more columns |
| | 213 | * than the value defined here, weird things will happen, so we go safe |
| | 214 | * and use a large value. */ |
| | 215 | #define OS_MAXWIDTH 255 |
| | 216 | |
| | 217 | /* Disable the Tads swap file; computers have plenty of RAM these days. |
| | 218 | */ |
| | 219 | #define OS_DEFAULT_SWAP_ENABLED 0 |
| | 220 | |
| | 221 | /* TADS 2 macro/function configuration. Modern configurations always |
| | 222 | * use the no-macro versions, so these definitions should always be set |
| | 223 | * as shown below. */ |
| | 224 | #define OS_MCM_NO_MACRO |
| | 225 | #define ERR_NO_MACRO |
| | 226 | |
| | 227 | /* Not really needed; just a dummy. */ |
| | 228 | #define OS_TR_USAGE "usage: frob [options] file" |
| | 229 | |
| | 230 | /* TADS 2 compiler usage message. We should actually use the name the |
| | 231 | * user used to invoke the compiler, but the base code doesn't provide |
| | 232 | * for that. */ |
| | 233 | #define OS_TC_USAGE "Usage: tadsc [options] file" |
| | 234 | |
| | 235 | /* File timestamp type. |
| | 236 | * |
| | 237 | * Needed by the TADS 3 compiler. */ |
| | 238 | struct os_file_time_t { |
| | 239 | time_t t; |
| | 240 | }; |
| | 241 | |
| | 242 | /* These values are used for the "mode" parameter of osfseek() to |
| | 243 | * indicate where to seek in the file. */ |
| | 244 | #define OSFSK_SET SEEK_SET /* Set position relative to the start of the file. */ |
| | 245 | #define OSFSK_CUR SEEK_CUR /* Set position relative to the current file position. */ |
| | 246 | #define OSFSK_END SEEK_END /* Set position relative to the end of the file. */ |
| | 247 | |
| | 248 | |
| | 249 | /* ============= Functions follow ================ */ |
| | 250 | |
| | 251 | /* Allocate a block of memory of the given size in bytes. */ |
| | 252 | #define osmalloc malloc |
| | 253 | |
| | 254 | /* Free memory previously allocated with osmalloc(). */ |
| | 255 | #define osfree free |
| | 256 | |
| | 257 | /* Reallocate memory previously allocated with osmalloc() or osrealloc(), |
| | 258 | * changing the block's size to the given number of bytes. */ |
| | 259 | #define osrealloc realloc |
| | 260 | |
| | 261 | /* Open text file for reading. */ |
| | 262 | #define osfoprt(fname,typ) (fopen((fname),"r")) |
| | 263 | |
| | 264 | /* Open text file for writing. */ |
| | 265 | #define osfopwt(fname,typ) (fopen((fname),"w")) |
| | 266 | |
| | 267 | /* Open text file for reading and writing, keeping the file's existing |
| | 268 | * contents if the file already exists or creating a new file if no |
| | 269 | * such file exists. */ |
| | 270 | osfildef* |
| | 271 | osfoprwt( const char* fname, os_filetype_t typ ); |
| | 272 | |
| | 273 | /* Open text file for reading/writing. If the file already exists, |
| | 274 | * truncate the existing contents. Create a new file if it doesn't |
| | 275 | * already exist. */ |
| | 276 | #define osfoprwtt(fname,typ) (fopen((fname),"w+")) |
| | 277 | |
| | 278 | /* Open binary file for writing. */ |
| | 279 | #define osfopwb(fname,typ) (fopen((fname),"wb")) |
| | 280 | |
| | 281 | /* Open source file for reading - use the appropriate text or binary |
| | 282 | * mode. */ |
| | 283 | #define osfoprs osfoprt |
| | 284 | |
| | 285 | /* Open binary file for reading. */ |
| | 286 | #define osfoprb(fname,typ) (fopen((fname),"rb")) |
| | 287 | |
| | 288 | /* Open binary file for reading/writing. If the file already exists, |
| | 289 | * keep the existing contents. Create a new file if it doesn't already |
| | 290 | * exist. */ |
| | 291 | osfildef* |
| | 292 | osfoprwb( const char* fname, os_filetype_t typ ); |
| | 293 | |
| | 294 | /* Open binary file for reading/writing. If the file already exists, |
| | 295 | * truncate the existing contents. Create a new file if it doesn't |
| | 296 | * already exist. */ |
| | 297 | #define osfoprwtb(fname,typ) (fopen((fname),"w+b")) |
| | 298 | |
| | 299 | /* Get a line of text from a text file. */ |
| | 300 | #define osfgets fgets |
| | 301 | |
| | 302 | /* Write a line of text to a text file. */ |
| | 303 | #define osfputs fputs |
| | 304 | |
| | 305 | /* Write bytes to file. */ |
| | 306 | #define osfwb(fp,buf,bufl) (fwrite((buf),(bufl),1,(fp))!=1) |
| | 307 | |
| | 308 | /* Flush buffered writes to a file. */ |
| | 309 | #define osfflush fflush |
| | 310 | |
| | 311 | /* Read bytes from file. */ |
| | 312 | #define osfrb(fp,buf,bufl) (fread((buf),(bufl),1,(fp))!=1) |
| | 313 | |
| | 314 | /* Read bytes from file and return the number of bytes read. */ |
| | 315 | #define osfrbc(fp,buf,bufl) (fread((buf),1,(bufl),(fp))) |
| | 316 | |
| | 317 | /* Get the current seek location in the file. */ |
| | 318 | #define osfpos ftell |
| | 319 | |
| | 320 | /* Seek to a location in the file. */ |
| | 321 | #define osfseek fseek |
| | 322 | |
| | 323 | /* Close a file. */ |
| | 324 | #define osfcls fclose |
| | 325 | |
| | 326 | /* Delete a file. */ |
| | 327 | #define osfdel remove |
| | 328 | |
| | 329 | /* Access a file - determine if the file exists. |
| | 330 | * |
| | 331 | * We map this to the access() function. It should be available in |
| | 332 | * virtually every system out there, as it appears in many standards |
| | 333 | * (SVID, AT&T, POSIX, X/OPEN, BSD 4.3, DOS, MS Windows, maybe more). */ |
| | 334 | #define osfacc(fname) (access((fname), F_OK)) |
| | 335 | |
| | 336 | /* Get a character from a file. */ |
| | 337 | #define osfgetc fgetc |
| | 338 | |
| | 339 | /* Set busy cursor. |
| | 340 | * |
| | 341 | * We don't have a mouse cursor so there's no need to implement this. */ |
| | 342 | #define os_csr_busy(a) |
| | 343 | |
| | 344 | /* Update progress display. |
| | 345 | * |
| | 346 | * We don't provide any kind of "compilation progress display", so we |
| | 347 | * just define this as an empty macro. |
| | 348 | */ |
| | 349 | #define os_progress(fname,linenum) |
| | 350 | |
| | 351 | /* Initialize the time zone. |
| | 352 | * |
| | 353 | * We don't need this (I think). */ |
| | 354 | #define os_tzset() |
| | 355 | |
| | 356 | #endif /* OSFROBTADS_H */ |