00001
00014
#include <stdio.h>
00015
#include <stdlib.h>
00016
#include <signal.h>
00017
#include <math.h>
00018
00019
#ifdef __HIGHC__
00020
#include <init.h>
00021
#endif
00022
00023
#if defined(WIN32) || defined(_WIN32)
00024
#include <io.h>
00025
#include <fcntl.h>
00026
#include <share.h>
00027
#include <sys/stat.h>
00028
#endif
00029
00030
#include "wattcp.h"
00031
#include "wdpmi.h"
00032
#include "x32vm.h"
00033
#include "powerpak.h"
00034
#include "strings.h"
00035
#include "sock_ini.h"
00036
#include "cpumodel.h"
00037
#include "pcsed.h"
00038
#include "pcpkt.h"
00039
#include "pcconfig.h"
00040
#include "pcdbug.h"
00041
#include "bsddbug.h"
00042
#include "ioport.h"
00043
#include "btrace.h"
00044
#include "timer.h"
00045
#include "misc.h"
00046
00047
00048
00049
const char hex_chars_lower[] =
"0123456789abcdef";
00050
const char hex_chars_upper[] =
"0123456789ABCDEF";
00051
00052 BOOL
win32_dos_box = FALSE;
00053 BOOL
_watt_fatal_error = FALSE;
00054 WORD _watt_os_ver = 0x622;
00055 char _watt_assert_buf[256];
00057
static int num_exit_func_inserts = 0;
00058
00059
00060
00061
00062
int _w32_errno = 0;
00063
00064
#if !defined(__DJGPP__)
00065
int __bss_count = 0;
00066
#endif
00067
00068
#if (DOSX & (PHARLAP|X32VM)) && defined(HAVE_FARPTR48)
00069 FARPTR
_watt_dosFp;
00070
#endif
00071
00072
#if defined(__LCC__)
00073
static _CPUID lcc_cpuid;
00074
char cdecl x86_type = 5;
00075
char cdecl x86_vendor_id[13];
00076
DWORD cdecl x86_capability;
00077
#endif
00078
00079
#if (DOSX)
00080
static void setup_dos_xfer_buf (
void);
00081
static void is_in_stack_init (
void);
00082
#endif
00083
00084
#define STATIC
00085
00086
#if defined(__BORLANDC__)
00087
#pragma inline
00088
#if defined(USE_DEBUG) && (defined(__SMALL__) || defined(__LARGE__))
00089
STATIC
int setup_stk_check (
void);
00090
#endif
00091
00092
#elif defined(WATCOM386) && !defined(WIN32)
00093
extern char cdecl __begtext;
00094
extern UINT cdecl _x386_stacklow;
00095
00096
#if defined(__SW_3S)
00097
void cdecl _fatal_runtime_error (
UINT stk);
00098
#define FATAL_HANDLER _fatal_runtime_error
00099
#else
00100
void cdecl _fatal_runtime_error_ (
UINT stk);
00101
#define FATAL_HANDLER _fatal_runtime_error_
00102
#endif
00103
00104
00105
00106
00107
00108
char *dummy_fatal_rte = (
char*)&FATAL_HANDLER;
00109
00110
#elif defined(_MSC_VER) && defined(__LARGE__) && defined(USE_DEBUG)
00111
extern void (__cdecl *_aaltstkovr) (
void);
00112
static void stk_overflow (
void _far *where);
00113
#endif
00114
00115
#if (DOSX & (PHARLAP|X32VM)) || (DOSX == 0)
00116
#define CS_WRITEABLE
00117
#endif
00118
00119
#define MAKE_CS_WRITEABLE() ((void)0)
00120
#define UNDO_CS_ACCESS() ((void)0)
00123
#if defined(USE_DEBUG) && defined(__BORLANDC__) && (defined(__SMALL__) || defined(__LARGE__))
00124
STATIC
void test_stk_check (
void)
00125 {
00126
char buf[1000];
00127 sprintf (buf,
"In test_stk_check(): CS:IP %04X:%04X\n",
00128 _CS, FP_OFF(test_stk_check));
00129 puts (buf);
00130 }
00131
#endif
00132
00133
00134
00135
00136
00137
00138
#include "nochkstk.h"
00139
00140
#if !defined(USE_BIGENDIAN)
00141
00145 unsigned long cdecl
_w32_intel (
unsigned long val)
00146 {
00147
return ((val & 0x000000FFU) << 24) |
00148 ((val & 0x0000FF00U) << 8) |
00149 ((val & 0x00FF0000U) >> 8) |
00150 ((val & 0xFF000000U) >> 24);
00151 }
00152
00157 unsigned short cdecl
_w32_intel16 (
unsigned short val)
00158 {
00159
return ((val & 0x00FF) << 8) | ((val & 0xFF00) >> 8);
00160 }
00161
00162
#if (DOSX) && defined(CS_WRITEABLE)
00163
static const BYTE bswap32[] = {
00164 0x8B,0x44,0x24,0x04,
00165 0x0F,0xC8,
00166 0xC3
00167 };
00168
00169
static const BYTE bswap16[] = {
00170 0x8B,0x44,0x24,0x04,
00171 0x0F,0xC8,
00172 0xC1,0xE8,0x10,
00173 0xC3
00174 };
00175
00176
00177
00178
00179
00180
00181
00182
static void patch_with_bswap (
void)
00183 {
00184 MAKE_CS_WRITEABLE();
00185 memcpy ((
void*)_w32_intel, (
const void*)&bswap32,
sizeof(bswap32));
00186 memcpy ((
void*)_w32_intel16,(
const void*)&bswap16,
sizeof(bswap16));
00187 UNDO_CS_ACCESS();
00188 }
00189
#endif
00190
#endif
00191
00192
00198 DWORD get_day_num (
void)
00199 {
00200
#if defined(WIN32)
00201
time_t now;
00202
00203 time (&now);
00204
return ((
DWORD)now / (24*3600));
00205
#else
00206
struct dosdate_t d;
00207
00208 memset (&d, 0,
sizeof(d));
00209 _dos_getdate (&d);
00210 --d.month;
00211 --d.day;
00212
return ((d.year-1970) * 365 + d.month * 31 + d.day);
00213
#endif
00214
}
00215
00216
00217
#if (DOSX) && !defined(USE_BIGENDIAN)
00218
00219
00220
00221
00222
00223
static BOOL RDTSC_enabled (
void)
00224 {
00225
const char *env = getenv (
"USE_RDTSC");
00226
00227
use_rdtsc = (env && ATOI(env) > 0);
00228
00229
if (!
use_rdtsc ||
00230 x86_type < 5)
00231
return (FALSE);
00232
00233
if (!strncmp(x86_vendor_id,
"AuthenticAMD",12) &&
00234 (x86_capability & X86_CAPA_TSC))
00235
return (TRUE);
00236
00237
if (!strncmp(x86_vendor_id,
"CentaurHauls",12))
00238 {
00239
#if 0
00240
00241
00242
00243
00244
DWORD eax, ebx, ecx, edx;
00245
00246 get_cpuid (0xC0000000, &eax, &ebx, &ecx, &edx);
00247 centaur_eflag = (eax >= 0xC0000001);
00248
if (centaur_eflag)
00249 {
00250 get_cpuid (0xC0000001, &eax, &ebx, &ecx, &edx);
00251 use_ace = ((edx & (0x3<<6)) == (0x3<<6));
00252 use_rng = ((edx & (0x3<<2)) == (0x3<<2));
00253 }
00254
#endif
00255
return (TRUE);
00256 }
00257
00258
if (strncmp(x86_vendor_id,
"GenuineIntel",12) ||
00259 (x86_capability & X86_CAPA_TSC) == 0)
00260
return (FALSE);
00261
00262
#if (DOSX) && !defined(__LCC__) && !defined(BORLAND_WIN32)
00263
return ((Get_CR4() & CR4_TS_DISABLE) == 0);
00264
#else
00265
return (TRUE);
00266
#endif
00267
}
00268
#endif
00269
00270
00271
#if (DOSX == 0) && defined(USE_DEBUG)
00272
00279
#define OffsetOf(x) (unsigned)&(x)
00280
00281
static BOOL check_reg_struct (
void)
00282 {
00283
#if defined(__WATCOMC__)
00284
struct IREGS *r1 = NULL;
00285
union REGPACK *r2 = NULL;
00286
00287
if ((OffsetOf(r2->w.ax) != OffsetOf(r1->r_ax)) ||
00288 (OffsetOf(r2->w.bx) != OffsetOf(r1->r_bx)) ||
00289 (OffsetOf(r2->w.cx) != OffsetOf(r1->r_cx)) ||
00290 (OffsetOf(r2->w.dx) != OffsetOf(r1->r_dx)) ||
00291 (OffsetOf(r2->w.bp) != OffsetOf(r1->r_bp)) ||
00292 (OffsetOf(r2->w.si) != OffsetOf(r1->r_si)) ||
00293 (OffsetOf(r2->w.di) != OffsetOf(r1->r_di)) ||
00294 (OffsetOf(r2->w.ds) != OffsetOf(r1->r_ds)) ||
00295 (OffsetOf(r2->w.es) != OffsetOf(r1->r_es)) ||
00296 (OffsetOf(r2->x.flags) != OffsetOf(r1->r_flags)))
00297
return (FALSE);
00298
00299
#elif defined(__BORLANDC__)
00300
struct IREGS *r1 = NULL;
00301
struct REGPACK *r2 = NULL;
00302
00303
if ((OffsetOf(r2->r_ax) != OffsetOf(r1->r_ax)) ||
00304 (OffsetOf(r2->r_bx) != OffsetOf(r1->r_bx)) ||
00305 (OffsetOf(r2->r_cx) != OffsetOf(r1->r_cx)) ||
00306 (OffsetOf(r2->r_dx) != OffsetOf(r1->r_dx)) ||
00307 (OffsetOf(r2->r_bp) != OffsetOf(r1->r_bp)) ||
00308 (OffsetOf(r2->r_si) != OffsetOf(r1->r_si)) ||
00309 (OffsetOf(r2->r_di) != OffsetOf(r1->r_di)) ||
00310 (OffsetOf(r2->r_ds) != OffsetOf(r1->r_ds)) ||
00311 (OffsetOf(r2->r_es) != OffsetOf(r1->r_es)) ||
00312 (OffsetOf(r2->r_flags) != OffsetOf(r1->r_flags)))
00313
return (FALSE);
00314
#endif
00315
return (TRUE);
00316 }
00317
#endif
00318
00322 void init_misc (
void)
00323 {
00324
static BOOL init = FALSE;
00325
00326
if (init)
00327
return;
00328
00329
_watt_assert_buf[0] =
'\0';
00330
00331
#if (DOSX)
00332
is_in_stack_init();
00333
#endif
00334
00335
#if defined(WIN32)
00336
init_winmisc();
00337
00338
#elif defined(__DJGPP__)
00339
_watt_os_ver = _get_dos_version (1);
00340
00341
#elif defined(MSC386)
00342
_watt_os_ver = 0x500;
00343
00344
#else
00345
_watt_os_ver = (_osmajor << 8) + _osminor;
00346
#endif
00347
00348
#if defined(WIN32)
00349
win32_dos_box = FALSE;
00350
#else
00351
win32_dos_box = (
_watt_os_ver >= 0x700 ||
00352
_watt_os_ver == 0x501 ||
00353
_watt_os_ver == 0x532);
00354
#endif
00355
00356
#if (DOSX & PHARLAP) && defined(HAVE_FARPTR48)
00357
00358
00359
00360
00361 FP_SET (
_watt_dosFp, 0, SS_DOSMEM);
00362
00363
#elif (DOSX & X32VM)
00364
_watt_dosFp = MK_FP (_x386_zero_base_selector, 0);
00365
00366
#elif defined(HAVE_FARPTR48)
00367 UNFINISHED();
00368
#endif
00369
00370
#if defined(__DJGPP__) || defined(__HIGHC__)
00371
00372
#endif
00373
00374
#if (DOSX)
00375
setup_dos_xfer_buf();
00376
00377
#elif defined(USE_DEBUG)
00378
if (!check_reg_struct())
00379 {
00380 outsnl (__FILE__
": IREGS/REGPACK size mismatch!");
00381 exit (-1);
00382 }
00383
00384
#if defined(_MSC_VER) && defined(__LARGE__)
00385
(
DWORD)_aaltstkovr = (
DWORD)stk_overflow;
00386
#endif
00387
00388
#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__LARGE__))
00389
setup_stk_check();
00390
#endif
00391
#endif
00392
00393
00394
00395
00396
#if (DOSX) && !defined(USE_BIGENDIAN)
00397
#if defined(__LCC__)
00398
if (_cpuidPresent())
00399 {
00400 _cpuid (&lcc_cpuid);
00401 memcpy (&x86_vendor_id, &lcc_cpuid.Vendor,
sizeof(x86_vendor_id));
00402 x86_capability = X86_CAPA_TSC;
00403 }
00404
#elif !defined(BORLAND_WIN32)
00405
CheckCpuType();
00406
#endif
00407
00408
if (RDTSC_enabled())
00409
has_rdtsc = TRUE;
00410
00411
#if defined(CS_WRITEABLE)
00412
if (x86_type >= 4)
00413 patch_with_bswap();
00414
#endif
00415
#endif
00416
00417
#if defined(WIN32)
00418
srand (GetTickCount());
00419
#else
00420
srand (PEEKW(0,0x46C));
00421
#endif
00422
00423
init_timers();
00424 init = TRUE;
00425 }
00426
00430 void exit_misc (
void)
00431 {
00432 num_exit_func_inserts = 0;
00433 }
00434
00441 FILE *
fopen_excl (
const char *file,
const char *mode)
00442 {
00443
#if defined(WIN32) && !defined(__WATCOMC__)
00444
int fd, flags = _O_CREAT | _O_TRUNC | _O_WRONLY;
00445
00446
#ifdef _O_SEQUENTIAL
00447
flags += _O_SEQUENTIAL;
00448
#endif
00449
if (mode[strlen(mode)-1] ==
'b')
00450 flags += O_BINARY;
00451
00452 fd = _sopen (file, flags, SH_DENYWR, S_IREAD | S_IWRITE);
00453
if (fd <= -1)
00454
return (NULL);
00455
return fdopen (fd, mode);
00456
#else
00457
return fopen (file, mode);
00458
#endif
00459
}
00460
00465 struct on_exit {
00466 void (*func)(
void);
00467
const char *name;
00468
int order;
00469 };
00470
00471
static struct on_exit exit_list [40];
00472
00473
static int list_compare (
const struct on_exit *a,
const struct on_exit *b)
00474 {
00475
return (a->
order - b->order);
00476 }
00477
00481 int rundown_add (
void (*func)(
void),
const char *name,
int order,
00482
const char *file,
unsigned line)
00483 {
00484
int i;
00485
00486
for (i = 0; i < num_exit_func_inserts; i++)
00487 {
00488
if (!exit_list[i].
func)
00489
continue;
00490
00491
if (exit_list[i].
func == func)
00492
goto modify;
00493
00494
if (exit_list[i].
order == order)
00495 {
00496
#if defined(USE_DEBUG)
00497
(*_printf) (
"%s(%u): rundown_add (\"%s\",%d): order already "
00498
"in exit_list[]\n", file, line, name, order);
00499 exit (-1);
00500
#else
00501
return (-1);
00502
#endif
00503
}
00504 }
00505
00506 WATT_ASSERT (num_exit_func_inserts < DIM(exit_list));
00507 i = num_exit_func_inserts++;
00508
00509 modify:
00510 exit_list[i].
func = func;
00511 exit_list[i].
name = name;
00512 exit_list[i].
order = order;
00513
00514 qsort (&exit_list, DIM(exit_list),
sizeof(exit_list[0]),
00515 (
int(*)(
const void *,
const void *))list_compare);
00516
00517 ARGSUSED (file);
00518 ARGSUSED (line);
00519
return (num_exit_func_inserts);
00520 }
00521
00525 void rundown_run (
void)
00526 {
00527
struct on_exit *oe;
00528 void (*func)(
void);
00529
int i;
00530
00531
for (i = 0, oe = exit_list; i < DIM(exit_list); i++, oe++)
00532 {
00533
if (!oe->func)
00534
continue;
00535
00536
#if defined(USE_DEBUG)
00537
if (debug_on >= 3)
00538 {
00539 (*_printf) (
"Calling rundown-func `%s' at order %d\n",
00540 oe->name, oe->order);
00541 fflush (stdout);
00542 }
00543
#endif
00544
func = oe->func;
00545 oe->func = NULL;
00546 (*func)();
00547 }
00548 }
00549
00550
#if defined(USE_DEBUG)
00551
00554 void rundown_dump (
void)
00555 {
00556
const struct on_exit *oe;
00557
int i, num_active;
00558
00559 (*_printf) (
"rundown_dump():\n");
00560
for (i = num_active = 0, oe = exit_list; i < DIM(exit_list); i++, oe++)
00561 {
00562
if (!oe->func)
00563
continue;
00564 (*_printf) (
" order %3d: %s\n", oe->order, oe->name);
00565 num_active++;
00566 }
00567 (*_printf) (
" %s\n", num_active == i ?
"possible overflow" :
"okay");
00568 }
00569
#endif
00570
00571
00572
00573
00574
00575
#if defined(USE_CRTDBG)
00576
00577
00578
00579
00580
#if !defined(_CRT_RPTHOOK_INSTALL) && (_MSC_VER < 1300)
00581
#define _CRT_RPTHOOK_INSTALL 0
00582
#define _CRT_RPTHOOK_REMOVE 1
00583
00584 _CRTIMP _CRT_REPORT_HOOK __cdecl
00585 _CrtSetReportHook2 (
int, _CRT_REPORT_HOOK);
00586
#endif
00587
00588
static _CrtMemState last_state;
00589
static void __cdecl crtdbg_exit (
void);
00590
00591
static const char *report_name (
int type)
00592 {
00593
return (type == _CRT_WARN ?
"Warn" :
00594 type == _CRT_ERROR ?
"Error" :
00595 type == _CRT_ASSERT ?
"Assert" :
00596 type == _CRT_ERRCNT ?
"ErrCnt" :
"??");
00597 }
00598
00599
00600
00601
00602
static void __cdecl crtdbg_dump (
const void *buf, size_t len)
00603 {
00604
const BYTE *p = (
const BYTE*) buf;
00605 size_t i;
00606
int c;
00607
00608 fprintf (stderr,
"dump: buf %p, %u bytes\n", buf, len);
00609 len = min (len, 30);
00610
for (i = 0; i < len; i++)
00611 {
00612 c = *p++;
00613 fprintf (stderr,
"%c", isprint(c) ? c :
'.');
00614 }
00615 }
00616
00617 static int __cdecl
crtdbg_report (
int type,
char *message,
int *ret_val)
00618 {
00619 BOOL stop;
00620
00621 fprintf (stderr,
"%s: %s\n", report_name(type), message);
00622 stop = (type == _CRT_ASSERT);
00623
if (stop)
00624 {
00625
00626 crtdbg_exit();
00627
00628 }
00629
if (ret_val)
00630 *ret_val = stop;
00631
return (stop);
00632 }
00633
00634
static void __cdecl crtdbg_exit (
void)
00635 {
00636
#if 0
00637
_CrtMemDumpStatistics (&last_state);
00638 _CrtCheckMemory();
00639 _CrtDumpMemoryLeaks();
00640
#endif
00641
00642
#if (_MSC_VER >= 1300) && 0
00643
_CrtSetReportHook2 (_CRT_RPTHOOK_REMOVE, crtdbg_report);
00644
#else
00645
_CrtSetReportHook (NULL);
00646
#endif
00647
}
00648
00649
void memdbg_init (
void)
00650 {
00651
#if (_MSC_VER < 1500) || 1
00652 _HFILE file = _CRTDBG_FILE_STDERR;
00653
int mode = _CRTDBG_MODE_FILE;
00654
int flags = _CRTDBG_LEAK_CHECK_DF |
00655 _CRTDBG_DELAY_FREE_MEM_DF |
00656
00657 _CRTDBG_CHECK_ALWAYS_DF |
00658 _CRTDBG_ALLOC_MEM_DF;
00659
00660 _CrtSetReportFile (_CRT_ASSERT, file);
00661 _CrtSetReportMode (_CRT_ASSERT, mode);
00662 _CrtSetReportFile (_CRT_ERROR, file);
00663 _CrtSetReportMode (_CRT_ERROR, mode);
00664 _CrtSetReportFile (_CRT_WARN, file);
00665 _CrtSetReportMode (_CRT_WARN, mode);
00666
00667 _CrtSetDbgFlag (flags | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
00668
00669
#if (_MSC_VER >= 1300) && 0
00670
_CrtSetReportHook2 (_CRT_RPTHOOK_INSTALL, crtdbg_report);
00671
#else
00672
_CrtSetReportHook (crtdbg_report);
00673
#endif
00674
00675 _CrtMemCheckpoint (&last_state);
00676 _CrtSetDumpClient (crtdbg_dump);
00677
00678 RUNDOWN_ADD (crtdbg_exit, 305);
00679
#endif
00680
}
00681
00682
#elif defined(USE_FORTIFY)
00683
00688 static void fortify_report (
void)
00689 {
00690
if (debug_on >= 2)
00691 {
00692 Fortify_SetOutputFunc ((Fortify_OutputFuncPtr)printf);
00693 Fortify_OutputStatistics();
00694 }
00695
else
00696 Fortify_SetOutputFunc (NULL);
00697 Fortify_LeaveScope();
00698 }
00699
00700
void memdbg_init (
void)
00701 {
00702
const char *env = getenv (
"FORTIFY_FAIL");
00703
00704 Fortify_EnterScope();
00705
if (env)
00706 Fortify_SetAllocateFailRate (atoi(env));
00707
00708
#if defined(USE_DEBUG) && defined(USE_BSD_API)
00709
Fortify_SetOutputFunc (bsd_fortify_print);
00710
#endif
00711
00712 RUNDOWN_ADD (fortify_report, 305);
00713
00714
#if defined(WIN32)
00715
LoadLibrary (
"exchndl.dll");
00716
#endif
00717
}
00718
#endif
00719
00720
00721
#if defined(USE_DEBUG) && !defined(NDEBUG)
00722
00725 void assert_fail (
const char *file,
unsigned line,
const char *what)
00726 {
00727
#if defined(SNPRINTF)
00728
SNPRINTF (
_watt_assert_buf,
sizeof(
_watt_assert_buf)-1,
00729 #
else
00730 sprintf (
_watt_assert_buf,
00731 #endif
00732
"%s (%u): Assertion `%s' failed.\n", file, line, what);
00733
00734 (*_printf) (
"%s\n",
_watt_assert_buf);
00735
00736 #ifdef __DJGPP__
00737
00738
00739
00740
rundown_run();
00741 abort();
00742 #
else
00743 exit (-1);
00744 #endif
00745 }
00746 #endif
00747
00748
00752 unsigned Random (
unsigned a,
unsigned b)
00753 {
00754
if (a == b)
00755
return (a);
00756
00757
if (a > b)
00758 {
00759
unsigned tmp = b;
00760 b = a;
00761 a = tmp;
00762 }
00763
return (a + (
unsigned)(rand() % (b-a+1)));
00764 }
00765
00769 void RandomWait (
unsigned a,
unsigned b)
00770 {
00771
DWORD t = set_timeout (
Random(a, b));
00772
00773
while (!
chk_timeout(t))
00774 {
00775 #
if defined(WIN32)
00776 Sleep (1);
00777 #
else
00778 ENABLE();
00779 #endif
00780 }
00781 }
00782
00786 void Wait (
unsigned msec)
00787 {
00788
DWORD t = set_timeout (msec);
00789
00790
while (!
chk_timeout(t))
00791 {
00792 #
if defined(WIN32)
00793 Sleep (1);
00794 #
else
00795 ENABLE();
00796 #endif
00797 }
00798 }
00799
00800
00801
00802
00803
const char *dos_extender_name (
void)
00804 {
00805 #
if (DOSX & DOS4GW)
00806
return dos4gw_extender_name();
00807 #elif (DOSX & DJGPP)
00808
return (
"djgpp");
00809 #elif (DOSX & PHARLAP)
00810
return (
"PharLap");
00811 #elif (DOSX & POWERPAK)
00812
return (
"PowerPak");
00813 #elif (DOSX & X32VM)
00814
return (
"X32VM");
00815 #elif (DOSX & WINWATT)
00816
return (
"Win32");
00817 #
else
00818
return (NULL);
00819 #endif
00820 }
00821
00822
00823
void os_yield (
void)
00824 {
00825 #
if defined(WIN32)
00826 Sleep (1);
00827 #
else
00828
static BOOL do_yield = TRUE;
00829
00830 #
if defined(__DJGPP__)
00831
if (do_yield)
00832 {
00833 __dpmi_yield();
00834 do_yield = (errno != ENOSYS);
00835 }
00836 #
else
00837
if (!
watt_kbhit() && do_yield)
00838 {
00839 IREGS reg;
00840 memset (®, 0,
sizeof(reg));
00841 reg.r_ax = 0x1680;
00842 GEN_INTERRUPT (0x2F, ®);
00843 do_yield = (loBYTE(reg.r_ax) != 0x80);
00844 }
00845
#endif
00846
#endif
00847 }
00848
00849
00850
#if defined(NOT_USED)
00851
BOOL watt_check_break (
void)
00852 {
00853
WORD head = 0x400 + PEEKW (0, 0x41A);
00854
WORD tail = 0x400 + PEEKW (0, 0x41C);
00855
int ofs, num;
00856
00857 printf (
"\nwatt_check_break(): head %04X, tail %04X, keys:\n",
00858 head, tail);
00859
for (num = 0, ofs = head; ofs != tail && num < 32; num++)
00860 {
00861 printf (
" ofs %04X: %02X\n", ofs, PEEKB(0,ofs));
00862
if (++ofs > 32+0x41E)
00863 ofs = 0x41E;
00864 }
00865 puts (
"");
00866
return (FALSE);
00867 }
00868
#endif
00869
00870
00874 int watt_kbhit (
void)
00875 {
00876
if (_watt_cbroke)
00877
return (1);
00878
00879
#if defined(WIN32)
00880
Sleep (1);
00881
return kbhit();
00882
00883
#else
00884
if (PEEKW(0,0x41A) == PEEKW(0,0x41C))
00885
return (0);
00886
00887
00888
00889
00890
00891
00892
return kbhit();
00893
#endif
00894
}
00895
00896
00897
#if defined(USE_DEBUG)
00898
00901 const char *
list_lookup (
DWORD type,
const struct search_list *list,
int num)
00902 {
00903
static char buf[15];
00904
00905
while (num > 0 && list->name)
00906 {
00907
if (list->type == type)
00908
return (list->name);
00909 num--;
00910 list++;
00911 }
00912 sprintf (buf,
"?%lu", type);
00913
return (buf);
00914 }
00915
00916
const char *list_lookupX (
DWORD type,
const struct search_list *list,
int num)
00917 {
00918
static char buf[15];
00919
00920
while (num > 0 && list->name)
00921 {
00922
if (list->type == type)
00923
return (list->name);
00924 num--;
00925 list++;
00926 }
00927 sprintf (buf,
"?0x%lX", type);
00928
return (buf);
00929 }
00930
00935 const char *
MAC_address (
const void *addr)
00936 {
00937
static char buf[2][25];
00938
static int idx = 0;
00939
char *rc = buf [idx];
00940
char *p = rc;
00941
const char *a = (
const char*)addr;
00942
00943 p += sprintf (p,
"%02X:%02X:%02X:%02X:%02X:%02X",
00944 a[0] & 255, a[1] & 255, a[2] & 255,
00945 a[3] & 255, a[4] & 255, a[5] & 255);
00946
00947
00948
00949
if (
_pktdevclass == PDCLASS_AX25)
00950 sprintf (p,
":%02X", a[6] & 255);
00951
00952 idx ^= 1;
00953
return (rc);
00954 }
00955
00956
void unfinished (
const char *func,
const char *file,
unsigned line)
00957 {
00958
if (func)
00959 fprintf (stderr,
"In `%s' ", func);
00960 fprintf (stderr,
"%s (%u):\7 Help! Unfinished code.\n", file, line);
00961 exit (-1);
00962 }
00963
00968 const char *
dword_str (
DWORD val)
00969 {
00970
static char buf[20];
00971
char tmp[20];
00972
00973
if (val < 1000UL)
00974 {
00975 sprintf (buf,
"%lu", val);
00976
return (buf);
00977 }
00978
if (val < 1000000UL)
00979 {
00980 sprintf (buf,
"%lu,%03lu", val/1000UL, val % 1000UL);
00981
return (buf);
00982 }
00983
if (val < 1000000000UL)
00984 {
00985 sprintf (tmp,
"%9lu", val);
00986 sprintf (buf,
"%.3s,%.3s,%.3s", tmp, tmp+3, tmp+6);
00987
return strltrim (buf);
00988 }
00989 sprintf (tmp,
"%12lu", val);
00990 sprintf (buf,
"%.3s,%.3s,%.3s,%.3s", tmp, tmp+3, tmp+6, tmp+9);
00991
return strltrim (buf);
00992 }
00993
#endif
00994
00995
00996
#if (DOSX)
00997
#if defined(BORLAND386) || defined(DMC386) || defined(MSC386)
00998
DWORD get_ds_limit (
void)
00999 {
01000
DWORD res;
01001
asm mov ax, ds
01002
asm and eax, 0FFFFh
01003
asm lsl eax, eax
01004
asm mov res, eax
01005
return (res);
01006 }
01007
01008
DWORD get_cs_limit (
void)
01009 {
01010
DWORD res;
01011
asm mov ax, cs
01012
asm and eax, 0FFFFh
01013
asm lsl eax, eax
01014
asm mov res, eax
01015
return (res);
01016 }
01017
01018
DWORD get_ss_limit (
void)
01019 {
01020
DWORD res;
01021
asm mov ax, ss
01022
asm and eax, 0FFFFh
01023
asm lsl eax, eax
01024
asm mov res, eax
01025
return (res);
01026 }
01027
01028
#elif defined(__CCDL__)
01029
DWORD get_ds_limit (
void)
01030 {
01031
asm {
01032 mov ax, ds
01033 and eax, 0xFFFF
01034 lsl eax, eax
01035 }
01036
return (_EAX);
01037 }
01038
01039
DWORD get_cs_limit (
void)
01040 {
01041
asm {
01042 mov ax, cs
01043 and eax, 0xFFFF
01044 lsl eax, eax
01045 }
01046
return (_EAX);
01047 }
01048
01049
DWORD get_ss_limit (
void)
01050 {
01051
asm {
01052 mov ax, ss
01053 and eax, 0xFFFF
01054 lsl eax, eax
01055 }
01056
return (_EAX);
01057 }
01058
#endif
01059
01060
01061
01062
01063
01064
01065
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
01066
#define THREADLOCAL __declspec(thread)
01067
#else
01068
#define THREADLOCAL
01069
#endif
01070
01071 THREADLOCAL
static const char *stack_bottom = 0;
01072
01073
#if defined(__DJGPP__) && 0
01074
extern unsigned dj_end
asm (
"end");
01075
extern unsigned _stklen, __djgpp_stack_limit;
01076
#define STK_START() (DWORD)&dj_end
01077
#endif
01078
01079
static unsigned get_frame_size (
const char *x)
01080 {
01081
char y = 0;
01082
return (
unsigned)(x - &y);
01083 }
01084
01085
static void is_in_stack_init (
void)
01086 {
01087
char x = 0;
01088 stack_bottom = &x + get_frame_size(&x) * 2;
01089 }
01090
01091 BOOL is_in_stack (
const void *ptr)
01092 {
01093
char x;
01094
char *stack_top = &x;
01095
char *p = (
char*) ptr;
01096
01097
if (stack_top > stack_bottom)
01098
return (p > stack_bottom && p < stack_top);
01099
return (p > stack_top && p < stack_bottom);
01100 }
01101
01102
unsigned used_stack (
void)
01103 {
01104
char x;
01105
char *stack_top = &x;
01106
01107
if (stack_top > stack_bottom)
01108
return (
unsigned)(stack_top - stack_bottom);
01109
return (
unsigned)(stack_bottom - stack_top);
01110 }
01111
01112
01113
01114
01115
01116
01117
01118
01119 BOOL valid_addr (
const void *addr,
unsigned len)
01120 {
01121
#if defined(WIN32)
01122
if (IsBadWritePtr((
void*)addr,len) && IsBadReadPtr(addr,len))
01123
return (FALSE);
01124
01125
#else
01126
DWORD limit, addr_ = (
DWORD)addr;
01127
01128
if (addr_ < 4096)
01129
return (FALSE);
01130
01131
01132
01133
#if defined(DMC386) && (DOSX & X32VM) && 0
01134
if (selector == MY_SS())
01135 {
01136 limit = get_ss_limit();
01137
if (addr_ < _x386_stacklow || addr_ + len >= limit)
01138
return (FALSE);
01139
if (limit > len && addr_ >= limit - len)
01140
return (FALSE);
01141 }
01142
else if (selector != MY_DS())
01143
return (FALSE);
01144
#endif
01145
01146
#if defined(__DJGPP__)
01147
limit = __dpmi_get_segment_limit (_my_ds());
01148
#elif defined(__HIGHC__)
01149
limit = _mwlsl (_mwgetcs());
01150
#else
01151
limit = get_ds_limit();
01152
#endif
01153
01154
if (addr_ + len >= limit)
01155
return (FALSE);
01156
if (limit > len && addr_ >= limit - len)
01157
return (FALSE);
01158
#endif
01159
01160
return (TRUE);
01161 }
01162
#endif
01163
01164
01165
01166
01167
01168
01169
01170
#if (DOSX & (PHARLAP|X32VM))
01171
REALPTR _watt_dosTbr;
01172
DWORD _watt_dosTbSize = 0;
01173
static WORD rm_seg = 0;
01174
01175
static void free_selector (
void)
01176 {
01177
if (rm_seg)
01178 _dx_real_free (rm_seg);
01179 rm_seg = 0;
01180 _watt_dosTbr = 0;
01181 _watt_dosTbSize = 0;
01182 }
01183
01184
static void setup_dos_xfer_buf (
void)
01185 {
01186 FARPTR dos_tbp;
01187 REALPTR r2p_addr;
01188
WORD temp;
01189
int len = 1024;
01190
01191 _dx_rmlink_get (&r2p_addr, &_watt_dosTbr,
01192 &_watt_dosTbSize, &dos_tbp);
01193
01194
if (_watt_dosTbSize < len &&
01195 _dx_real_above(len, &rm_seg, &temp) == 0)
01196 {
01197 RP_SET (_watt_dosTbr, 0, rm_seg);
01198 _watt_dosTbSize = len;
01199 RUNDOWN_ADD (free_selector, 15);
01200 }
01201 }
01202
01203
#elif (DOSX & DOS4GW)
01204
WORD _watt_dosTbSeg = 0;
01205
WORD _watt_dosTbSel = 0;
01206
DWORD _watt_dosTbSize = 0;
01207
01208
static void free_selector (
void)
01209 {
01210
if (_watt_dosTbSel)
01211
#ifdef __CCDL__
01212
dpmi_free_selector (_watt_dosTbSel);
01213
#else
01214
dpmi_real_free (_watt_dosTbSel);
01215
#endif
01216
_watt_dosTbSel = 0;
01217 }
01218
01219
static void setup_dos_xfer_buf (
void)
01220 {
01221 _watt_dosTbSize = 1024;
01222
#ifdef __CCDL__
01223
if (dpmi_alloc_real_memory (&_watt_dosTbSel, &_watt_dosTbSeg, _watt_dosTbSize) >= 0)
01224 _watt_dosTbSeg = 0;
01225
#else
01226
_watt_dosTbSeg = dpmi_real_malloc (_watt_dosTbSize, &_watt_dosTbSel);
01227
#endif
01228
01229
if (!_watt_dosTbSeg)
01230 _watt_dosTbSize = 0;
01231
else RUNDOWN_ADD (free_selector, 15);
01232 }
01233
01234
#elif (DOSX & POWERPAK)
01235
WORD _watt_dos_ds;
01236
WORD _watt_dosTbSeg = 0;
01237
WORD _watt_dosTbSel = 0;
01238
DWORD _watt_dosTbr = 0;
01239
DWORD _watt_dosTbSize = 0;
01240
01241
static void free_selector (
void)
01242 {
01243
if (_watt_dosTbSel)
01244 dpmi_real_free (_watt_dosTbSel);
01245 _watt_dosTbSel = 0;
01246
if (_watt_dos_ds)
01247 dpmi_free_dos_selector (_watt_dos_ds);
01248 _watt_dos_ds = 0;
01249 _watt_dosTbr = 0;
01250 }
01251
01252
static void setup_dos_xfer_buf (
void)
01253 {
01254 _watt_dos_ds = dpmi_create_dos_selector();
01255
if (!_watt_dos_ds)
01256 {
01257 fprintf (stderr,
"Fatal: Failed to create DOS selector. "
01258
"DPMI error 0x%04X.\n", __dpmi_errno);
01259 exit (-1);
01260 }
01261 _watt_dosTbSize = 1024;
01262 _watt_dosTbSeg = dpmi_real_malloc (_watt_dosTbSize, &_watt_dosTbSel);
01263
if (!_watt_dosTbSeg)
01264 _watt_dosTbSize = 0;
01265
else
01266 {
01267 RUNDOWN_ADD (free_selector, 15);
01268 _watt_dosTbr = (_watt_dosTbSeg << 16);
01269 }
01270 }
01271
01272
#elif (DOSX)
01273
static void setup_dos_xfer_buf (
void)
01274 {
01275
01276 }
01277
#endif
01278
01279
01280
#if defined(USE_BSD_API)
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
int _w32_ffs (
int i)
01308 {
01309
static const BYTE table[] = {
01310 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
01311 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
01312 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
01313 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
01314 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
01315 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
01316 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
01317 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
01318 };
01319
DWORD a, x;
01320
01321
#if (DOSX) && !defined(__LCC__) && !defined(BORLAND_WIN32)
01322
if (x86_type >= 3)
01323
return asm_ffs (i);
01324
#endif
01325
01326 x = i & -i;
01327 a = x <= 0xFFFFUL ? (x <= 0xFF ? 0 : 8) : (x <= 0xFFFFFF ? 16 : 24);
01328
return (table[x >> a] + a);
01329 }
01330
#endif
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
#if defined(__LARGE__)
01358
void watt_large_check (
const void *sock,
int size,
01359
const char *file,
unsigned line)
01360 {
01361
if ((
unsigned)(FP_OFF(sock)) > (
unsigned)(-size))
01362 {
01363
#if defined(USE_DEBUG)
01364
fprintf (stderr,
"%s (%d): user stack size error", file, line);
01365
#else
01366
outsnl (
"user stack size error");
01367 ARGSUSED (file);
01368 ARGSUSED (line);
01369
#endif
01370
exit (3);
01371 }
01372 }
01373
#endif
01374
01375
01376
#if defined(USE_DEBUG)
01377
#if defined(NOT_USED)
01378
BOOL is_big_endian (
void)
01379 {
01380
01381
01382
union {
01383
long l;
01384
char c[
sizeof(
long)];
01385 } u;
01386
01387 u.l = 1;
01388
return (u.c[
sizeof(
long)-1] == 1);
01389 }
01390
01394
#include <sys/pack_on.h>
01395
01396 struct cmd_block {
01397
BYTE len;
01398
char buf[256];
01399 };
01400
01401
#include <sys/pack_off.h>
01402
01403 BOOL shell_exec (
const char *cmd)
01404 {
01405
struct cmd_block blk;
01406 size_t i =
sizeof(blk.
buf)-1;
01407 IREGS regs;
01408
01409
StrLcpy (blk.
buf, cmd, i);
01410 i = min (i, strlen(blk.
buf));
01411 blk.
len = i;
01412 blk.
buf[i] =
'\r';
01413
01414
#if (DOSX & DJGPP)
01415
regs.r_ds = __tb / 16;
01416 regs.r_si = __tb & 15;
01417 dosmemput (&blk,
sizeof(blk), __tb);
01418
01419
#elif (DOSX == 0)
01420
regs.r_ds = FP_SEG (&blk);
01421 regs.r_si = FP_OFF (&blk);
01422
#endif
01423
01424 GEN_INTERRUPT (0x2E, ®s);
01425
return (regs.r_ax != 0xFFFF);
01426 }
01427
#endif
01428
01429
01433
#if (defined(_MSC_VER) || defined(__DMC__)) && (DOSX == 0)
01434
#undef intr
01435 void _w32_intr (
int int_no, IREGS *reg)
01436 {
01437
union REGS r;
01438
struct SREGS s;
01439
01440 r.x.ax = reg->r_ax;
01441 r.x.bx = reg->r_bx;
01442 r.x.cx = reg->r_cx;
01443 r.x.dx = reg->r_dx;
01444 r.x.si = reg->r_si;
01445 r.x.di = reg->r_di;
01446 s.ds = reg->r_ds;
01447 s.es = reg->r_es;
01448 int86x (int_no, &r, &r, &s);
01449 reg->r_flags = r.x.cflag;
01450 reg->r_ax = r.x.ax;
01451 reg->r_bx = r.x.bx;
01452 reg->r_cx = r.x.cx;
01453 reg->r_dx = r.x.dx;
01454 reg->r_si = r.x.si;
01455 reg->r_di = r.x.di;
01456 reg->r_ds = s.ds;
01457 reg->r_es = s.es;
01458 }
01459
#endif
01460
01461
01462
#if defined(__BORLANDC__) && defined(__LARGE__)
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474 STATIC
void stk_overflow (
WORD ret_addr)
01475 {
01476
static WORD cs, ip;
01477
static WORD stk[128];
01478
01479 cs = *(
WORD*) (&ret_addr-1);
01480 ip = *(
WORD*) (&ret_addr-2);
01481
01482 _SS = FP_SEG (stk);
01483 _SP = (
WORD) &stk [DIM(stk)-1];
01484 _stklen = 0x7FFF;
01485
_watt_fatal_error = TRUE;
01486 fprintf (stderr,
"\nStack overflow at %04X:%04X!\n", cs, ip);
01487
_eth_release();
01488 _exit (-1);
01489 }
01490
01491 STATIC
int setup_stk_check (
void)
01492 {
01493
BYTE sign[] = { 0x39, 0x26, 0,0, 0x77, 5, 0x9A };
01494
BYTE *p = (
BYTE*)
_eth_arrived;
01495
int i;
01496
01497 *(
WORD*)&sign[2] = FP_OFF (&_stklen);
01498
for (i = 0; i < 10; i++, p++)
01499
if (!memcmp(p, sign,
sizeof(sign)))
01500 {
01501
DWORD addr = *(
DWORD*) (p +
sizeof(sign));
01502
BYTE *patch;
01503
01504
01505 patch = (
BYTE*) addr;
01506 *patch++ = 0x2E;
01507 *patch++ = 0xFF;
01508 *patch++ = 0x2E;
01509 *(
WORD*)patch = 6 - 1 + (
WORD)addr;
01510 patch += 2;
01511 *(
WORD*)patch = FP_OFF (stk_overflow);
01512 patch += 2;
01513 *(
WORD*)patch = FP_SEG (stk_overflow);
01514
01515
01516
01517
01518
01519
01520
#if 0
01521
printf (
"test_stk_check() at CS:IP %04X:%04X\n",
01522 _CS, FP_OFF(test_stk_check));
01523 _stklen = 10;
01524 test_stk_check();
01525
#endif
01526
return (1);
01527 }
01528
return (0);
01529 }
01530
01531
#elif defined(__BORLANDC__) && defined(__SMALL__)
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
extern int __brklvl;
01544
01545
static void stk_overflow (
UINT ret_addr)
01546 {
01547
static WORD cs, ip;
01548
static WORD stk[128];
01549
01550 cs = _CS;
01551 ip = *(
WORD*) (&ret_addr-1);
01552
01553 _SS = FP_SEG (stk);
01554 _SP = (
WORD) &stk [DIM(stk)-1];
01555
01556 _stklen = 0x7FFF;
01557
_watt_fatal_error = TRUE;
01558 fprintf (stderr,
"\nStack overflow at %04X:%04X!\n", cs, ip);
01559
_eth_release();
01560 _exit (1);
01561 }
01562
01563
static int stk_check_setup (
void)
01564 {
01565
BYTE sign[] = { 0x39, 0x26, 0,0, 0x72, 3, 0xE8 };
01566
BYTE *p = (
BYTE*)
_eth_arrived;
01567
int i;
01568
01569 *(
WORD*)&sign[2] = FP_OFF (&__brklvl);
01570
for (i = 0; i < 10; i++, p++)
01571
if (!memcmp(p, sign,
sizeof(sign)))
01572 {
01573
BYTE *addr = *(
BYTE*)(++p);
01574 *addr = (
BYTE*) stk_overflow;
01575
return (1);
01576 }
01577
return (0);
01578 }
01579
01580
#elif defined(WATCOM386) && !defined(WIN32)
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
static void stk_overflow (
WORD cs,
UINT eip)
01592 {
01593
UINT size = *(
UINT*)(eip-9);
01594
01595 eip -= (
UINT)&__begtext - 9;
01596
01597
_watt_fatal_error = TRUE;
01598 fprintf (stderr,
"Stack overflow (%u bytes needed) detected at %X:%08lXh\n",
01599 size, cs, (
DWORD)eip);
01600
_eth_release();
01601 _exit (1);
01602 }
01603
01604
void FATAL_HANDLER (
UINT stk)
01605 {
01606
#if defined(__SMALL__)
01607
_x386_stacklow = stk + 2;
01608 stk_overflow (MY_CS(), *(
DWORD*)(&stk+1));
01609
01610
#elif defined(__LARGE__)
01611
_x386_stacklow = stk + 4;
01612 stk_overflow (*(
WORD*)(&stk+1), *(
WORD*)(&stk+2));
01613
01614
#else
01615 _x386_stacklow = stk + 4;
01616 stk_overflow (MY_CS(), *(
WORD*)(&stk+1));
01617
#endif
01618
}
01619
01620
#elif defined(_MSC_VER) && defined(__LARGE__)
01621
static void stk_overflow (
void _far *where)
01622 {
01623 fprintf (stderr,
"Stack overflow detected at %04X:%04Xh\n",
01624 FP_SEG(where), FP_OFF(where));
01625
_eth_release();
01626 _exit (1);
01627 }
01628
#endif
01629
#endif
01630
01631
01632
01633
01634
#if defined(__GNUC__)
01635
#undef __SYS_SWAP_BYTES_H
01636
#undef _w32_SYS_SWAP_BYTES_H
01637
#undef _w32_CPUMODEL_H
01638
#undef _w32_MISC_H
01639
#undef _w32_IOPORT_H
01640
#undef BEEP
01641
#undef WIN_ASSERT
01642
01643
#define extern
01644
#define __inline__
01645
#define __inline
01646
01647
#if defined(__MINGW32__) || defined(__CYGWIN__)
01648
#undef intel
01649
#undef intel16
01650
#define __NO_INLINE__
01651
#endif
01652
01653
#include <sys/swap.h>
01654
#include "misc.h"
01655
#include "cpumodel.h"
01656
01657
#if defined(__EMX__)
01658
#include "ioport.h"
01659
#endif
01660
01661
#endif
01662
01663
01664
#if defined(TEST_PROG)
01665
01666
01667
01668 BOOL get_mem_strat (
BYTE *strat)
01669 {
01670 IREGS reg;
01671
01672 memset (®, 0,
sizeof(reg));
01673 reg.r_ax = 0x5800;
01674 GEN_INTERRUPT (0x21, ®);
01675
if (reg.r_flags & CARRY_BIT)
01676
return (FALSE);
01677 *strat = loBYTE (reg.r_ax);
01678
return (TRUE);
01679 }
01680
01681 BOOL set_mem_strat (
BYTE strat)
01682 {
01683 IREGS reg;
01684
01685 memset (®, 0,
sizeof(reg));
01686 reg.r_ax = 0x5801;
01687 reg.r_bx = strat;
01688 GEN_INTERRUPT (0x21, ®);
01689
if (reg.r_flags & CARRY_BIT)
01690
return (FALSE);
01691
return (TRUE);
01692 }
01693
01694
void foo_10 (
void) { puts (
"I'm foo_10()"); }
01695
void foo_20 (
void) { puts (
"I'm foo_20()"); }
01696
void foo_30 (
void) { puts (
"I'm foo_30()"); }
01697
void foo_40 (
void) { puts (
"I'm foo_40()"); }
01698
void foo_50 (
void) { puts (
"I'm foo_50()"); }
01699
void foo_60 (
void) { puts (
"I'm foo_60()"); }
01700
void foo_70 (
void) { puts (
"I'm foo_70()"); }
01701
01702
int main (
void)
01703 {
01704
BYTE strat;
01705
01706 printf (
"DOS memory allocation strategy: ");
01707
if (!get_mem_strat(&strat))
01708 puts (
"failed");
01709
else printf (
"0x%02X\n", strat);
01710
01711 printf (
"Setting \"low memory best fit\" ");
01712
if (!set_mem_strat(1))
01713 puts (
"failed");
01714
else puts (
"okay");
01715
01716 set_mem_strat (strat);
01717
01718 RUNDOWN_ADD (foo_40, 40);
01719 RUNDOWN_ADD (foo_10, 10);
01720 RUNDOWN_ADD (foo_60, 60);
01721 RUNDOWN_ADD (foo_30, 30);
01722 RUNDOWN_ADD (foo_20, 20);
01723 RUNDOWN_ADD (foo_50, 50);
01724 RUNDOWN_ADD (foo_70, 70);
01725 debug_on = 2;
01726
rundown_run();
01727
return (0);
01728 }
01729
#endif
01730